From a0afbc356b548349919a7ff9453d2d2356de4a48 Mon Sep 17 00:00:00 2001 From: Mario Doiron <4956+doiron@users.noreply.github.com> Date: Fri, 24 Mar 2023 15:17:28 -0700 Subject: [PATCH 01/10] merge v2.29.0 --- .babelrc.js | 7 - .commitlintrc.json | 22 +- .eslintrc.json | 51 - .gitignore | 6 +- .npmignore | 10 + .prettierignore | 7 + .prettierrc | 12 + .prettierrc.json | 8 + CONTRIBUTING.md | 13 +- bin/ask-skill.js | 13 - bin/ask-skill.ts | 12 + bin/ask-smapi.js | 19 - bin/ask-smapi.ts | 19 + bin/ask-util.js | 13 - bin/ask-util.ts | 11 + bin/ask.js | 33 - bin/ask.ts | 51 + bin/askx-skill.ts | 12 + bin/askx-smapi.ts | 19 + bin/askx-util.ts | 11 + docs/FAQ.md | 6 - .../Alexa-Skill-Project-Definition.md | 2 +- jsconfig.json | 15 +- .../build-flows/abstract-build-flow.js | 154 +- lib/builtins/build-flows/custom.js | 82 +- lib/builtins/build-flows/java-mvn.js | 106 +- lib/builtins/build-flows/nodejs-npm.js | 92 +- lib/builtins/build-flows/python-pip.js | 110 +- lib/builtins/build-flows/zip-only.js | 50 +- .../cfn-deployer/assets/basic-lambda.yaml | 42 +- .../deploy-delegates/cfn-deployer/helper.js | 350 +- .../deploy-delegates/cfn-deployer/index.js | 444 +- .../lambda-deployer/helper.js | 620 +- .../deploy-delegates/lambda-deployer/index.js | 204 +- lib/clients/aws-client/abstract-aws-client.js | 32 +- lib/clients/aws-client/aws-util.js | 104 +- .../aws-client/cloudformation-client.js | 222 +- lib/clients/aws-client/iam-client.js | 118 +- lib/clients/aws-client/lambda-client.js | 269 +- lib/clients/aws-client/s3-client.js | 664 +- lib/clients/git-client.js | 457 +- lib/clients/http-client.js | 146 +- lib/clients/lwa-auth-code-client/index.js | 262 +- lib/clients/metric-client/index.js | 175 - lib/clients/metric-client/index.ts | 247 + lib/clients/smapi-client/index.js | 231 - lib/clients/smapi-client/index.ts | 307 + .../smapi-client/resources/account-linking.js | 98 +- .../smapi-client/resources/alexa-hosted.js | 198 +- .../smapi-client/resources/beta-test.js | 472 +- lib/clients/smapi-client/resources/catalog.js | 294 +- .../smapi-client/resources/evaluations.js | 66 +- lib/clients/smapi-client/resources/history.js | 62 +- .../resources/interaction-model.js | 164 +- lib/clients/smapi-client/resources/isp.js | 454 +- .../smapi-client/resources/manifest.js | 42 - .../smapi-client/resources/manifest.ts | 62 + .../smapi-client/resources/private-skill.js | 114 +- .../smapi-client/resources/publishing.js | 176 +- .../smapi-client/resources/skill-package.js | 158 +- lib/clients/smapi-client/resources/skill.js | 279 - lib/clients/smapi-client/resources/skill.ts | 310 + lib/clients/smapi-client/resources/task.js | 110 +- lib/clients/smapi-client/resources/test.js | 78 - lib/clients/smapi-client/resources/test.ts | 162 + lib/clients/smapi-client/resources/vendor.js | 34 +- lib/commands/abstract-command.js | 250 - lib/commands/abstract-command.ts | 265 + .../configure/ask-profile-setup-helper.js | 152 +- .../configure/aws-profile-setup-helper.js | 284 +- lib/commands/configure/helper.js | 75 +- lib/commands/configure/index.js | 120 - lib/commands/configure/index.ts | 126 + lib/commands/configure/messages.js | 30 +- lib/commands/configure/questions.js | 195 +- lib/commands/configure/ui.js | 267 +- lib/commands/deploy/helper.js | 138 +- lib/commands/deploy/index.js | 208 - lib/commands/deploy/index.ts | 251 + lib/commands/deploy/ui.js | 44 + lib/commands/dialog/helper.js | 62 - lib/commands/dialog/helper.ts | 49 + lib/commands/dialog/index.js | 154 - lib/commands/dialog/index.ts | 163 + lib/commands/dialog/interactive-mode.js | 37 - lib/commands/dialog/interactive-mode.ts | 43 + lib/commands/dialog/replay-mode.js | 63 - lib/commands/dialog/replay-mode.ts | 72 + lib/commands/init/helper.js | 260 +- lib/commands/init/index.js | 222 - lib/commands/init/index.ts | 215 + lib/commands/init/ui.js | 228 +- lib/commands/new/helper.js | 128 - lib/commands/new/helper.ts | 133 + lib/commands/new/hosted-skill-helper.js | 256 - lib/commands/new/hosted-skill-helper.ts | 263 + lib/commands/new/index.js | 120 - lib/commands/new/index.ts | 172 + lib/commands/new/template-helper.ts | 48 + lib/commands/new/ui.js | 138 - lib/commands/new/ui.ts | 237 + lib/commands/new/wizard-helper.js | 217 - lib/commands/new/wizard-helper.ts | 241 + lib/commands/option-model.json | 82 +- lib/commands/option-validator.js | 114 - lib/commands/option-validator.ts | 153 + lib/commands/run/helper.js | 133 +- lib/commands/run/index.js | 164 - lib/commands/run/index.ts | 182 + .../run/run-flow/abstract-run-flow.js | 20 +- lib/commands/run/run-flow/java-run.js | 42 +- lib/commands/run/run-flow/nodejs-run.js | 66 +- lib/commands/run/run-flow/python-run.js | 87 +- lib/commands/skill/add-locales/helper.js | 238 +- lib/commands/skill/add-locales/index.js | 56 - lib/commands/skill/add-locales/index.ts | 56 + lib/commands/skill/add-locales/ui.js | 76 +- lib/commands/skill/skill-commander.js | 16 - lib/commands/skill/skill-commander.ts | 15 + .../export-package/helper.js | 44 +- .../appended-commands/export-package/index.js | 87 - .../appended-commands/export-package/index.ts | 86 + .../smapi/appended-commands/get-task/index.js | 46 - .../smapi/appended-commands/get-task/index.ts | 48 + .../appended-commands/search-task/index.js | 58 - .../appended-commands/search-task/index.ts | 61 + .../upload-catalog/helper.js | 108 +- .../appended-commands/upload-catalog/index.js | 90 - .../appended-commands/upload-catalog/index.ts | 99 + lib/commands/smapi/before-send-processor.js | 74 +- .../smapi/cli-customization-processor.js | 345 +- .../smapi/customizations/aliases.json | 36 +- .../smapi/customizations/parameters-map.js | 16 +- .../smapi/customizations/parameters.json | 124 +- lib/commands/smapi/smapi-command-handler.js | 365 +- lib/commands/smapi/smapi-commander.js | 135 - lib/commands/smapi/smapi-commander.ts | 198 + lib/commands/smapi/smapi-docs.js | 79 +- .../util/generate-lwa-tokens/index.js | 72 - .../util/generate-lwa-tokens/index.ts | 75 + .../util/git-credentials-helper/index.js | 89 - .../util/git-credentials-helper/index.ts | 90 + lib/commands/util/upgrade-project/helper.js | 524 +- .../upgrade-project/hosted-skill-helper.js | 187 +- lib/commands/util/upgrade-project/index.js | 145 - lib/commands/util/upgrade-project/index.ts | 144 + lib/commands/util/upgrade-project/ui.js | 75 +- lib/commands/util/util-commander.js | 18 - lib/commands/util/util-commander.ts | 19 + .../authorization-controller/index.js | 310 +- .../authorization-controller/messages.js | 14 +- lib/controllers/dialog-controller/index.js | 177 - lib/controllers/dialog-controller/index.ts | 176 + .../simulation-response-parser.js | 84 - .../hosted-skill-controller/clone-flow.js | 204 +- .../hosted-skill-controller/helper.js | 260 +- .../hosted-skill-controller/index.js | 388 +- .../skill-code-controller/code-builder.js | 88 +- .../skill-code-controller/index.js | 154 +- .../deploy-delegate.js | 224 +- .../skill-infrastructure-controller/index.js | 647 +- .../skill-metadata-controller/index.js | 901 +- .../skill-simulation-controller/index.js | 87 - .../skill-simulation-controller/index.ts | 120 + lib/exceptions/cli-cfn-deployer-error.js | 10 +- lib/exceptions/cli-data-format-error.ts | 12 + lib/exceptions/cli-error.js | 8 +- lib/exceptions/cli-file-not-found-error.js | 10 +- lib/exceptions/cli-retriable-error.ts | 26 + lib/exceptions/cli-warn.js | 10 +- lib/model/abstract-config-file.js | 216 +- lib/model/app-config.js | 174 +- lib/model/build-status-local-cache.ts | 91 + lib/model/callback.ts | 2 + lib/model/dialog-replay-file.js | 214 +- lib/model/dialog-save-skill-io-file.js | 72 +- lib/model/dialog/inputs.ts | 107 + lib/model/import-status.ts | 69 + lib/model/manifest.js | 250 +- lib/model/regional-stack-file.js | 98 +- lib/model/resources-config/ask-resources.js | 180 +- lib/model/resources-config/ask-states.js | 194 +- lib/model/resources-config/index.js | 307 +- lib/model/sample-template.ts | 77 + lib/model/skill-status.ts | 143 + lib/model/yaml-parser.js | 35 +- postinstall.js => lib/postinstall.js | 0 lib/utils/ac-util.js | 33 + lib/utils/constants.js | 931 +- lib/utils/dynamic-config.js | 92 +- lib/utils/hash-utils.js | 38 +- lib/utils/local-host-server.js | 36 +- lib/utils/logger-utility.js | 157 +- lib/utils/metrics.js | 2 +- lib/utils/profile-helper.js | 89 +- lib/utils/retry-utility.js | 104 +- lib/utils/stream-utility.js | 134 +- lib/utils/string-utils.js | 122 +- lib/utils/unflatten.js | 25 +- lib/utils/url-utils.js | 68 +- lib/utils/zip-utils.js | 135 +- lib/view/cli-repl-view.js | 135 - lib/view/cli-repl-view.ts | 156 + lib/view/dialog-repl-view.js | 39 - lib/view/dialog-repl-view.ts | 35 + .../import-status-view-events.ts | 22 + .../import-status-view-observable.ts | 109 + lib/view/import-status/import-status-view.ts | 130 + lib/view/json-view.js | 20 +- lib/view/messenger.js | 467 +- lib/view/multi-tasks-view.js | 235 +- lib/view/prompt-view.js | 37 - lib/view/prompt-view.ts | 38 + lib/view/spinner-view.js | 70 +- package-lock.json | 12203 ++++++++++++++++ package.json | 193 +- scripts/ask-clean-up.js | 23 +- scripts/aws-clean-up.js | 2 +- scripts/smapi-docs.js | 5 +- test/fixture/ask-devtools-metrics.schema.json | 164 +- .../test-project-1/.ask/ask-states.json | 8 + .../test-project-1/ask-resources.json | 10 + .../conversations/dialogEight.acdl | 71 + .../conversations/dialogEleven.acdl | 109 + .../conversations/dialogFive.acdl | 87 + .../conversations/dialogFour.acdl | 84 + .../conversations/dialogNine.acdl | 38 + .../conversations/dialogOne.acdl | 72 + .../conversations/dialogSeven.acdl | 56 + .../conversations/dialogSix.acdl | 64 + .../conversations/dialogTen.acdl | 59 + .../conversations/dialogThree.acdl | 56 + .../conversations/dialogTwo.acdl | 80 + .../interactionModels/custom/en-US.json | 180 + .../confirm_city_apl_display/document.json | 331 + .../confirm_date_apl_display/document.json | 331 + .../document.json | 379 + .../request_city_apl_display/document.json | 331 + .../request_date_apl_display/document.json | 331 + .../weather_success_apl_display/document.json | 379 + .../AlexaConversationsBye/document.json | 19 + .../document.json | 19 + .../document.json | 19 + .../document.json | 19 + .../document.json | 19 + .../AlexaConversationsThankYou/document.json | 19 + .../AlexaConversationsWelcome/document.json | 19 + .../document.json | 19 + .../document.json | 19 + .../document.json | 19 + .../confirm_colorName_apla/document.json | 19 + .../document.json | 19 + .../prompts/notused_apla/document.json | 19 + .../numericfeedback_apla/document.json | 19 + .../prompts/rating_apla/document.json | 19 + .../prompts/request_city_apla/document.json | 19 + .../request_city_date_apla/document.json | 19 + .../request_colorName_apla/document.json | 19 + .../prompts/request_date_apla/document.json | 19 + .../request_fruitName_apla/document.json | 25 + .../request_listAddOns_apla/document.json | 19 + .../request_mainFoodName_apla/document.json | 19 + .../prompts/request_name_apla/document.json | 19 + .../success_colorFruitAPI_apla/document.json | 19 + .../success_cookingAPI_apla/document.json | 19 + .../document.json | 19 + .../success_fruitNameAPI_apla/document.json | 19 + .../success_weather_apla/document.json | 19 + .../test-project-1/skill-package/skill.json | 92 + .../commands/high-level-commands-test.js | 298 +- test/functional/run-test.js | 10 +- .../code-builder/code-builder-test.js | 234 +- .../commands/smapi-commands-test.js | 2634 ++-- .../fixtures/account-linking-request.json | 32 +- test/integration/fixtures/annotation-set.json | 160 +- test/integration/fixtures/catalog-upload.json | 2 +- .../code-builder/custom/lambda/index.js | 2 +- .../code-builder/custom/lambda/package.json | 24 +- .../code-builder/nodejs-npm/lambda/index.js | 2 +- .../create-in-skill-product-request.json | 90 +- .../fixtures/interaction-model.json | 156 +- test/integration/fixtures/job-definition.json | 22 +- test/integration/fixtures/lwa-swagger.json | 14 +- test/integration/fixtures/skill-manifest.json | 34 +- test/integration/run-test.js | 12 +- test/temp/abstract-build-flow/build.zip | Bin 0 -> 135 bytes test/temp/abstract-build-flow/some-file.txt | 1 + test/test-utils.js | 176 +- test/tsconfig.json | 8 + .../build-flows/abstract-build-flow-test.js | 166 +- test/unit/builtins/build-flows/custom-test.js | 156 +- .../builtins/build-flows/java-mvn-test.js | 150 +- .../builtins/build-flows/nodejs-npm-test.js | 126 +- .../builtins/build-flows/python-pip-test.js | 162 +- .../builtins/build-flows/zip-only-test.js | 58 +- .../unit/builtins/cfn-deployer/helper-test.js | 413 +- test/unit/builtins/cfn-deployer/index-test.js | 604 +- .../builtins/lambda-deployer/helper-test.js | 1157 +- .../builtins/lambda-deployer/index-test.js | 529 +- .../aws-client/abstract-aws-client-test.js | 82 +- .../aws-client/cloudformation-client-test.js | 703 +- .../clients/aws-client/iam-client-test.js | 260 +- .../clients/aws-client/lambda-client-test.js | 440 +- .../unit/clients/aws-client/s3-client-test.js | 1127 +- test/unit/clients/git-client-test.js | 870 +- test/unit/clients/http-client-test.js | 488 +- .../unit/clients/lwa-auth-code-client-test.js | 624 +- test/unit/clients/metric-client-test.js | 267 - test/unit/clients/metric-client-test.ts | 457 + test/unit/clients/smapi-client-test/index.js | 312 - .../clients/smapi-client-test/index.test.ts | 260 + test/unit/clients/smapi-client-test/index.ts | 262 + .../resources/account-linking.js | 150 +- .../resources/alexa-hosted.js | 222 +- .../smapi-client-test/resources/beta-test.js | 356 +- .../smapi-client-test/resources/catalog.js | 549 +- .../resources/evaluations.js | 136 +- .../smapi-client-test/resources/history.js | 130 +- .../resources/interaction-model.js | 437 +- .../smapi-client-test/resources/isp.js | 683 +- .../smapi-client-test/resources/manifest.js | 154 +- .../resources/private-skill.js | 210 +- .../smapi-client-test/resources/publishing.js | 312 +- .../resources/skill-package.js | 238 +- .../smapi-client-test/resources/skill.js | 1216 +- .../smapi-client-test/resources/task.js | 235 +- .../smapi-client-test/resources/test.js | 245 +- .../smapi-client-test/resources/vendor.js | 88 +- test/unit/commands/abstract-command-test.js | 523 - test/unit/commands/abstract-command-test.ts | 531 + .../ask-profile-setup-helper-test.js | 533 +- .../aws-profile-setup-helper-test.js | 576 +- test/unit/commands/configure/helper-test.js | 306 +- test/unit/commands/configure/index-test.js | 217 - test/unit/commands/configure/index-test.ts | 198 + .../unit/commands/configure/questions-test.js | 114 +- test/unit/commands/configure/ui-test.js | 906 +- test/unit/commands/deploy/helper-test.js | 399 +- test/unit/commands/deploy/index-test.js | 479 - test/unit/commands/deploy/index-test.ts | 514 + test/unit/commands/deploy/ui-test.js | 130 + test/unit/commands/dialog/helper-test.js | 263 - test/unit/commands/dialog/helper.spec.ts | 239 + test/unit/commands/dialog/index-test.js | 414 - test/unit/commands/dialog/index.spec.ts | 371 + .../commands/dialog/interactive-mode-test.js | 41 - .../commands/dialog/interactive-mode.spec.ts | 35 + test/unit/commands/dialog/replay-mode-test.js | 101 - test/unit/commands/dialog/replay-mode.spec.ts | 96 + test/unit/commands/init/helper-test.js | 783 +- test/unit/commands/init/index-test.js | 620 - test/unit/commands/init/index-test.ts | 568 + test/unit/commands/init/ui-test.js | 619 +- test/unit/commands/new/helper-test.js | 288 - test/unit/commands/new/helper-test.ts | 318 + .../commands/new/hosted-skill-helper-test.js | 484 - .../commands/new/hosted-skill-helper-test.ts | 497 + test/unit/commands/new/index-test.js | 321 - test/unit/commands/new/index-test.ts | 292 + .../unit/commands/new/template-helper-test.ts | 153 + test/unit/commands/new/ui-test.js | 415 - test/unit/commands/new/ui-test.ts | 477 + test/unit/commands/new/wizard-helper-test.js | 283 - test/unit/commands/new/wizard-helper-test.ts | 294 + test/unit/commands/option-validator-test.js | 448 +- test/unit/commands/run/helper-test.js | 273 +- test/unit/commands/run/index-test.js | 261 - test/unit/commands/run/index-test.ts | 287 + .../commands/run/run-flow/java-run-test.js | 86 +- .../commands/run/run-flow/nodejs-run-test.js | 170 +- .../commands/run/run-flow/python-run-test.js | 209 +- .../commands/skill/add-locales/helper-test.js | 365 +- .../commands/skill/add-locales/index-test.js | 155 - .../commands/skill/add-locales/index-test.ts | 140 + .../commands/skill/add-locales/ui-test.js | 202 +- .../commands/skill/skill-commander-test.ts | 36 + .../export-package/helper-test.js | 134 +- .../export-package/index-test.js | 203 - .../export-package/index-test.ts | 195 + .../appended-commands/get-task/index-test.js | 76 - .../appended-commands/get-task/index-test.ts | 67 + .../search-task/index-test.js | 93 - .../search-task/index-test.ts | 84 + .../smapi/before-send-processor-test.js | 185 +- .../smapi/cli-customization-processor-test.js | 485 +- .../smapi/smapi-command-handler-test.js | 526 +- .../commands/smapi/smapi-commander-test.js | 90 +- test/unit/commands/smapi/smapi-docs-test.js | 109 +- .../util/generate-lwa-tokens/index-test.js | 171 - .../util/generate-lwa-tokens/index-test.ts | 158 + .../util/git-credentials-helper/index-test.js | 207 - .../util/git-credentials-helper/index-test.ts | 204 + .../util/upgrade-project/helper-test.js | 1291 +- .../hosted-skill-helper-test.js | 505 +- .../util/upgrade-project/index-test.js | 495 - .../util/upgrade-project/index-test.ts | 468 + .../commands/util/upgrade-project/ui-test.js | 264 +- .../unit/commands/util/util-commander-test.ts | 36 + .../authorization-controller/index-test.js | 918 +- test/unit/controller/code-builder-test.js | 146 +- test/unit/controller/deploy-delegate-test.js | 474 +- .../dialog-controller/index-test.js | 454 - .../dialog-controller/index.spec.ts | 442 + .../dialog-controller/index.test.ts | 442 + .../simulation-response-parser-test.js | 319 - .../clone-flow-test.js | 423 +- .../hosted-skill-controller/helper-test.js | 239 +- .../hosted-skill-controller/index-test.js | 1235 +- .../controller/skill-code-controller-test.js | 316 +- .../skill-infrastructure-controller-test.js | 1622 +- .../skill-metadata-controller-test.js | 2523 ++-- .../skill-simulation-controller-test.js | 191 - .../skill-simulation-controller.spec.ts | 183 + .../skill-simulation-controller.test.ts | 183 + .../valid-deploy-delegate-instance.js | 4 +- .../test-project-1/.ask/ask-states.json | 8 + .../test-project-1/ask-resources.json | 10 + .../conversations/ALexaPrize.acdl | 203 + .../conversations/Dialog_NonDeployable.acdl | 81 + ...ableDialogsUsage_NonDeployableDialogs.acdl | 45 + .../skill-package/conversations/Weather.acdl | 137 + .../skill-package/conversations/apis.acdl | 15 + .../conversations/apisNamepaceLambda.acdl | 22 + .../conversations/conversation_empty.acdl | 114 + .../conversations/fruitNameApi.acdl | 34 + .../conversations/soaDialog.acdl | 123 + .../skill-package/conversations/types.acdl | 43 + .../conversations/utteracesets.acdl | 82 + .../interactionModels/custom/en-US.json | 919 ++ .../confirm_city_apl_display/document.json | 331 + .../confirm_date_apl_display/document.json | 331 + .../document.json | 379 + .../request_city_apl_display/document.json | 331 + .../request_date_apl_display/document.json | 331 + .../weather_success_apl_display/document.json | 379 + .../AlexaConversationsBye/document.json | 19 + .../document.json | 19 + .../document.json | 19 + .../document.json | 19 + .../document.json | 19 + .../AlexaConversationsThankYou/document.json | 19 + .../AlexaConversationsWelcome/document.json | 19 + .../document.json | 19 + .../document.json | 89 + .../document.json | 19 + .../confirm_fruitName_apla/document.json | 19 + .../document.json | 19 + .../response/prompts/no_apla/document.json | 19 + .../prompts/nothing2_apla/document.json | 19 + .../prompts/nothing_apla/document.json | 19 + .../numericfeedback_apla/document.json | 19 + .../prompts/rating_apla/document.json | 19 + .../document.json | 25 + .../prompts/request_city_apla/document.json | 19 + .../request_city_date_apla/document.json | 19 + .../document.json | 19 + .../prompts/request_date_apla/document.json | 19 + .../request_dob_getDate_apla/document.json | 19 + .../request_getEmploeeID_apla/document.json | 19 + .../prompts/request_name_apla/document.json | 19 + .../success_colorFruitAPI_apla/document.json | 19 + .../success_fruitPriceAPI_apla/document.json | 19 + .../prompts/weather_apla/document.json | 27 + .../response/prompts/yes_apla/document.json | 19 + .../prompts/yesnofeedback_apla/document.json | 19 + .../test-project-1/skill-package/skill.json | 92 + .../test-project-2/.ask/ask-states.json | 8 + .../test-project-2/ask-resources.json | 10 + .../conversations/Samenamespace.acdl | 7 + .../skill-package/conversations/apis.acdl | 51 + .../conversations/basicOfferDialog.acdl | 65 + .../skill-package/conversations/conditions | 71 + .../conversations/conversation_empty | 147 + .../conversations/delegateToSkill.acdl | 33 + .../conversations/dialogWeather.acdl | 9 + .../listDialogWithConditions.acdl | 243 + .../conversations/optionalDelegate.acdl | 118 + .../skill-package/conversations/pizza.acdl | 189 + .../conversations/soaDialog.acdl | 50 + .../skill-package/conversations/types.acdl | 248 + .../conversations/utteracesets.acdl | 435 + .../conversations/welcomeAPI.acdl | 38 + .../interactionModels/custom/en-US.json | 527 + .../confirm_city_apl_display/document.json | 331 + .../confirm_date_apl_display/document.json | 331 + .../document.json | 379 + .../request_city_apl_display/document.json | 331 + .../request_date_apl_display/document.json | 331 + .../weather_success_apl_display/document.json | 379 + .../AlexaConversationsBye/document.json | 19 + .../document.json | 19 + .../document.json | 19 + .../document.json | 19 + .../document.json | 19 + .../AlexaConversationsThankYou/document.json | 19 + .../AlexaConversationsWelcome/document.json | 19 + .../document.json | 19 + .../document.json | 20 + .../document.json | 20 + .../datasources/default.json | 1 + .../prompts/askForCrustPrompts/document.json | 26 + .../datasources/default.json | 1 + .../prompts/askForSizePrompts/document.json | 26 + .../datasources/default.json | 1 + .../askForToppingOnePrompt/document.json | 20 + .../datasources/default.json | 1 + .../askForToppingTwoPrompt/document.json | 20 + .../datasources/default.json | 1 + .../askForToppingsPrompts/document.json | 20 + .../datasources/default.json | 1 + .../askForTwoToppingsPrompts/document.json | 20 + .../datasources/default.json | 1 + .../document.json | 20 + .../document.json | 19 + .../document.json | 19 + .../datasources/default.json | 1 + .../prompts/confirmSizePrompt/document.json | 20 + .../datasources/default.json | 1 + .../document.json | 20 + .../datasources/default.json | 1 + .../document.json | 20 + .../datasources/default.json | 1 + .../confirmTwoToppingsPrompt/document.json | 20 + .../document.json | 19 + .../confirm_fruitName_apla/document.json | 19 + .../document.json | 19 + .../confirm_weather_apla/document.json | 19 + .../confirm_weather_city_apla/document.json | 19 + .../confirm_weather_date_apla/document.json | 19 + .../response/prompts/no_apla/document.json | 19 + .../prompts/nothing2_apla/document.json | 19 + .../prompts/nothing_apla/document.json | 19 + .../numericfeedback_apla/document.json | 19 + .../prompts/rating_apla/document.json | 19 + .../document.json | 25 + .../requestFromBookFlight_apla/document.json | 20 + .../document.json | 20 + .../requestToBookFlight_apla/document.json | 20 + .../prompts/request_city_apla/document.json | 19 + .../request_city_cityName_apla/document.json | 25 + .../document.json | 19 + .../document.json | 19 + .../document.json | 19 + .../prompts/request_date_apla/document.json | 19 + .../request_listAddOns_apla/document.json | 19 + .../request_mainFoodName_apla/document.json | 19 + .../prompts/request_name_apla/document.json | 19 + .../prompts/request_sign_apla/document.json | 19 + .../requestdropToBookCab_apla/document.json | 20 + .../prompts/secondEarthAPI_apla/document.json | 19 + .../prompts/seq_offer_apla/document.json | 19 + .../successBookCabAPI_apla/document.json | 20 + .../successBookFlightAPI_apla/document.json | 20 + .../success_cookingAPI_apla/document.json | 19 + .../document.json | 19 + .../success_fruitPriceAPI_apla/document.json | 19 + .../datasources/default.json | 1 + .../document.json | 20 + .../weather_success_apla/document.json | 27 + .../prompts/welcome_apla_custom/document.json | 19 + .../test-project-2/skill-package/skill.json | 93 + .../test-project-3/.ask/ask-states.json | 8 + .../test-project-3/ask-resources.json | 10 + .../TestDataACDLi18n/deBye/document.json | 18 + .../TestDataACDLi18n/deHelp/document.json | 19 + .../deOutOfDomain/datasources/default.json | 1 + .../deOutOfDomain/document.json | 18 + .../deRequireMore/document.json | 19 + .../TestDataACDLi18n/deWelcome/document.json | 18 + .../conversations/ALexaPrize.acdl | 203 + .../conversations/Dialog_NonDeployable.acdl | 81 + ...ableDialogsUsage_NonDeployableDialogs.acdl | 50 + .../skill-package/conversations/Weather.acdl | 152 + .../skill-package/conversations/apis.acdl | 17 + .../conversations/apisNamepaceLambda.acdl | 23 + .../conversations/conversation_empty.acdl | 114 + .../conversations/fruitNameApi.acdl | 34 + .../conversations/separateConfig.acdl | 98 + .../conversations/soaDialog.acdl | 132 + .../skill-package/conversations/types.acdl | 43 + .../conversations/utteracesets.acdl | 82 + .../interactionModels/custom/de-DE.json | 919 ++ .../interactionModels/custom/en-US.json | 919 ++ .../confirm_city_apl_display/document.json | 331 + .../confirm_date_apl_display/document.json | 331 + .../document.json | 379 + .../display/display_de_apl/document.json | 331 + .../request_city_apl_display/document.json | 331 + .../request_date_apl_display/document.json | 331 + .../weather_success_apl_display/document.json | 379 + .../AlexaConversationsBye/document.json | 19 + .../document.json | 19 + .../document.json | 19 + .../document.json | 19 + .../document.json | 19 + .../AlexaConversationsThankYou/document.json | 19 + .../AlexaConversationsWelcome/document.json | 19 + .../document.json | 19 + .../document.json | 89 + .../document.json | 19 + .../confirm_fruitName_apla/document.json | 19 + .../document.json | 19 + .../response/prompts/no_apla/document.json | 19 + .../prompts/nothing2_apla/document.json | 19 + .../prompts/nothing_apla/document.json | 19 + .../numericfeedback_apla/document.json | 19 + .../prompts/rating_apla/document.json | 19 + .../document.json | 25 + .../prompts/request_city_apla/document.json | 19 + .../request_city_date_apla/document.json | 19 + .../document.json | 19 + .../prompts/request_date_apla/document.json | 19 + .../request_dob_getDate_apla/document.json | 19 + .../request_getEmploeeID_apla/document.json | 19 + .../prompts/request_name_apla/document.json | 19 + .../success_colorFruitAPI_apla/document.json | 19 + .../success_fruitPriceAPI_apla/document.json | 19 + .../prompts/weather_apla/document.json | 27 + .../weather_apla_de_apla/document.json | 27 + .../response/prompts/yes_apla/document.json | 19 + .../prompts/yesnofeedback_apla/document.json | 19 + .../test-project-3/skill-package/skill.json | 105 + .../test-project-5/.ask/ask-states.json | 8 + .../test-project-5/ask-resources.json | 10 + .../conversations/Samenamespace.acdl | 7 + .../skill-package/conversations/apisMine.acdl | 50 + .../conversations/basicOfferDialog.acdl | 134 + .../conversations/conditions.acdl | 172 + .../conversations/conversation_empty.acdl | 109 + .../conversations/delegateToSkill.acdl | 29 + .../conversations/dialogWeather.acdl | 9 + .../listDialogWithConditions.acdl | 250 + .../conversations/optionalDelegate.acdl | 162 + .../skill-package/conversations/pizza.acdl | 196 + .../conversations/soaDialog.acdl | 89 + .../conversations/typesMine.acdl | 248 + .../conversations/utteracesetsMine.acdl | 455 + .../conversations/welcomeAPI.acdl | 34 + .../interactionModels/custom/en-US.json | 564 + .../confirm_city_apl_display/document.json | 358 + .../confirm_date_apl_display/document.json | 358 + .../document.json | 412 + .../request_city_apl_display/document.json | 358 + .../request_date_apl_display/document.json | 358 + .../weather_success_apl_display/document.json | 412 + .../AlexaConversationsBye/document.json | 21 + .../document.json | 21 + .../document.json | 21 + .../document.json | 21 + .../document.json | 21 + .../AlexaConversationsThankYou/document.json | 21 + .../AlexaConversationsWelcome/document.json | 21 + .../document.json | 21 + .../document.json | 22 + .../document.json | 22 + .../datasources/default.json | 1 + .../prompts/askForCrustPrompts/document.json | 1 + .../datasources/default.json | 1 + .../prompts/askForSizePrompts/document.json | 1 + .../datasources/default.json | 1 + .../askForToppingOnePrompt/document.json | 1 + .../datasources/default.json | 1 + .../askForToppingTwoPrompt/document.json | 1 + .../datasources/default.json | 1 + .../askForToppingsPrompts/document.json | 1 + .../datasources/default.json | 1 + .../askForTwoToppingsPrompts/document.json | 1 + .../datasources/default.json | 1 + .../document.json | 1 + .../document.json | 28 + .../document.json | 21 + .../datasources/default.json | 1 + .../prompts/confirmSizePrompt/document.json | 1 + .../datasources/default.json | 1 + .../document.json | 22 + .../datasources/default.json | 1 + .../document.json | 22 + .../datasources/default.json | 1 + .../confirmTwoToppingsPrompt/document.json | 1 + .../document.json | 21 + .../confirm_fruitName_apla/document.json | 21 + .../document.json | 21 + .../confirm_weather_apla/document.json | 21 + .../confirm_weather_city_apla/document.json | 21 + .../confirm_weather_date_apla/document.json | 21 + .../response/prompts/no_apla/document.json | 21 + .../prompts/nothing2_apla/document.json | 21 + .../prompts/nothing_apla/document.json | 21 + .../numericfeedback_apla/document.json | 19 + .../prompts/rating_apla/document.json | 21 + .../document.json | 27 + .../requestFromBookFlight_apla/document.json | 22 + .../document.json | 22 + .../requestToBookFlight_apla/document.json | 22 + .../prompts/request_city_apla/document.json | 21 + .../request_city_cityName_apla/document.json | 27 + .../document.json | 21 + .../document.json | 21 + .../document.json | 21 + .../prompts/request_date_apla/document.json | 21 + .../request_listAddOns_apla/document.json | 21 + .../request_mainFoodName_apla/document.json | 21 + .../prompts/request_name_apla/document.json | 21 + .../prompts/request_sign_apla/document.json | 21 + .../requestdropToBookCab_apla/document.json | 22 + .../prompts/secondEarthAPI_apla/document.json | 21 + .../prompts/seq_offer_apla/document.json | 21 + .../successBookCabAPI_apla/document.json | 22 + .../successBookFlightAPI_apla/document.json | 22 + .../success_cookingAPI_apla/document.json | 21 + .../document.json | 22 + .../success_fruitPriceAPI_apla/document.json | 21 + .../datasources/default.json | 1 + .../document.json | 22 + .../weather_success_apla/document.json | 29 + .../prompts/welcome_apla_custom/document.json | 21 + .../test-project-5/skill-package/skill.json | 96 + .../test-project-6/.ask/ask-states.json | 8 + .../test-project-6/ask-resources.json | 10 + .../conversations/ALexaPrize.acdl | 213 + .../conversations/Dialog_NonDeployable.acdl | 90 + ...ableDialogsUsage_NonDeployableDialogs.acdl | 47 + .../skill-package/conversations/Weather.acdl | 139 + .../conversations/apisNamepaceLambda.acdl | 22 + .../conversations/apis_mine.acdl | 15 + .../conversations/conversation_empty.acdl | 115 + .../conversations/soaDialog.acdl | 89 + .../conversations/types_mine.acdl | 43 + .../conversations/utteracesets_mine.acdl | 82 + .../interactionModels/custom/en-US.json | 923 ++ .../confirm_city_apl_display/document.json | 358 + .../confirm_date_apl_display/document.json | 358 + .../document.json | 412 + .../request_city_apl_display/document.json | 358 + .../request_date_apl_display/document.json | 358 + .../weather_success_apl_display/document.json | 412 + .../AlexaConversationsBye/document.json | 21 + .../document.json | 21 + .../document.json | 21 + .../document.json | 21 + .../document.json | 21 + .../AlexaConversationsThankYou/document.json | 21 + .../AlexaConversationsWelcome/document.json | 21 + .../document.json | 21 + .../document.json | 91 + .../document.json | 21 + .../confirm_fruitName_apla/document.json | 21 + .../document.json | 21 + .../response/prompts/no_apla/document.json | 21 + .../prompts/nothing2_apla/document.json | 21 + .../prompts/nothing_apla/document.json | 21 + .../numericfeedback_apla/document.json | 19 + .../prompts/rating_apla/document.json | 21 + .../document.json | 27 + .../prompts/request_city_apla/document.json | 21 + .../request_city_date_apla/document.json | 21 + .../document.json | 21 + .../prompts/request_date_apla/document.json | 21 + .../request_dob_getDate_apla/document.json | 21 + .../request_getEmploeeID_apla/document.json | 21 + .../prompts/request_name_apla/document.json | 21 + .../success_colorFruitAPI_apla/document.json | 21 + .../success_fruitPriceAPI_apla/document.json | 21 + .../prompts/weather_apla/document.json | 29 + .../response/prompts/yes_apla/document.json | 21 + .../prompts/yesnofeedback_apla/document.json | 21 + .../test-project-6/skill-package/skill.json | 97 + .../test-project-7/.ask/ask-states.json | 8 + .../test-project-7/ask-resources.json | 10 + .../TestDataACDLi18n/deBye/document.json | 20 + .../TestDataACDLi18n/deHelp/document.json | 21 + .../deOutOfDomain/datasources/default.json | 1 + .../deOutOfDomain/document.json | 20 + .../deRequireMore/document.json | 21 + .../TestDataACDLi18n/deWelcome/document.json | 20 + .../conversations/ALexaPrize.acdl | 203 + .../conversations/Dialog_NonDeployable.acdl | 79 + ...ableDialogsUsage_NonDeployableDialogs.acdl | 50 + .../conversations/MoreDialogs.acdl | 174 + .../skill-package/conversations/Weather.acdl | 154 + .../skill-package/conversations/apis.acdl | 36 + .../conversations/apisNamepaceLambda | 23 + .../conversations/conversation_empty.acdl | 114 + .../conversations/delegateToSkill.acdl | 33 + .../conversations/fruitNameApi.acdl | 34 + .../conversations/separateConfig.acdl | 83 + .../conversations/soaDialog.acdl | 132 + .../skill-package/conversations/test | 4 + .../skill-package/conversations/types.acdl | 43 + .../conversations/utteracesets.acdl | 82 + .../interactionModels/custom/de-DE.json | 963 ++ .../interactionModels/custom/en-GB.json | 963 ++ .../interactionModels/custom/en-US.json | 976 ++ .../confirm_city_apl_display/document.json | 358 + .../confirm_date_apl_display/document.json | 358 + .../document.json | 412 + .../display/display_de_apl/document.json | 358 + .../dummyLastScreen/datasources/default.json | 1 + .../display/dummyLastScreen/document.json | 1 + .../dummyLastScreen/sources/default.json | 1 + .../request_city_apl_display/document.json | 358 + .../request_date_apl_display/document.json | 358 + .../weather_success_apl_display/document.json | 412 + .../AlexaConversationsBye/document.json | 21 + .../document.json | 21 + .../document.json | 21 + .../document.json | 21 + .../document.json | 21 + .../AlexaConversationsThankYou/document.json | 21 + .../AlexaConversationsWelcome/document.json | 21 + .../document.json | 21 + .../document.json | 91 + .../document.json | 21 + .../confirm_fruitName_apla/document.json | 21 + .../document.json | 21 + .../response/prompts/no_apla/document.json | 21 + .../prompts/nothing2_apla/document.json | 21 + .../prompts/nothing_apla/document.json | 21 + .../numericfeedback_apla/document.json | 21 + .../prompts/rating_apla/document.json | 21 + .../document.json | 27 + .../prompts/request_city_apla/document.json | 21 + .../request_city_date_apla/document.json | 21 + .../document.json | 21 + .../prompts/request_date_apla/document.json | 21 + .../request_dob_getDate_apla/document.json | 21 + .../request_getEmploeeID_apla/document.json | 21 + .../prompts/request_name_apla/document.json | 21 + .../prompts/response0Prompt16/document.json | 1 + .../prompts/secondEarthAPI_apla/document.json | 21 + .../success_colorFruitAPI_apla/document.json | 21 + .../success_fruitPriceAPI_apla/document.json | 21 + .../prompts/weather_apla/document.json | 29 + .../weather_apla_de_apla/document.json | 29 + .../whoAmiSuccess/datasources/default.json | 7 + .../prompts/whoAmiSuccess/document.json | 22 + .../response/prompts/yes_apla/document.json | 21 + .../prompts/yesnofeedback_apla/document.json | 21 + .../test-project-7/skill-package/skill.json | 119 + .../fixture/model/app-config-no-profiles.json | 2 +- test/unit/fixture/model/app-config.yaml | 2 +- .../model/dialog/dialog-replay-file.json | 13 +- .../dialog/invalid-dialog-replay-file.json | 13 +- .../fixture/model/regional-stack-file.json | 12 +- .../fixture/model/regional-stack-file.yaml | 42 +- .../model/regular-proj/.ask/ask-states.json | 3 +- .../regular-proj/random-json-config.json | 28 +- test/unit/fixture/model/resources-config.yaml | 28 +- test/unit/model/abstract-config-file-test.js | 602 +- test/unit/model/app-config-test.js | 473 +- .../model/build-status-local-cache-test.ts | 158 + .../model/build-status-local-cache.test.ts | 158 + test/unit/model/dialog-replay-file-test.js | 431 +- .../model/dialog-save-skill-io-file-test.js | 106 +- test/unit/model/dialog/input.test.ts | 18 + test/unit/model/import-status-test.ts | 69 + test/unit/model/import-status.test.ts | 69 + test/unit/model/manifest-test.js | 420 +- test/unit/model/regional-stack-file-test.js | 238 +- .../resources-config/ask-resources-test.js | 188 +- .../model/resources-config/ask-states-test.js | 188 +- .../resources-config/resources-config-test.js | 453 +- test/unit/model/sample-template-test.ts | 84 + test/unit/model/skill-status-test.ts | 77 + test/unit/model/skill-status.test.ts | 77 + test/unit/model/yaml-parser-test.js | 104 +- test/unit/run-test.js | 142 +- test/unit/utils/hash-utils-test.js | 88 +- test/unit/utils/local-host-server-test.js | 76 +- test/unit/utils/retry-utility-test.js | 384 +- test/unit/utils/string-utils-test.js | 892 +- test/unit/utils/url-utils-test.js | 571 +- test/unit/utils/zip-utils-test.js | 457 +- test/unit/view/cli-repl-view-test.js | 297 - test/unit/view/cli-repl-view.spec.ts | 298 + test/unit/view/cli-repl-view.test.ts | 298 + test/unit/view/dialog-repl-view-test.js | 82 - test/unit/view/dialog-repl-view.spec.ts | 86 + test/unit/view/dialog-repl-view.test.ts | 86 + .../import-status-view-observable-test.ts | 181 + .../import-status/import-status-view-test.ts | 69 + test/unit/view/json-view-test.js | 70 +- test/unit/view/messenger-test.js | 733 +- test/unit/view/multi-tasks-view-test.js | 559 +- test/unit/view/prompt-view-test.js | 116 - test/unit/view/prompt-view-test.ts | 119 + test/unit/view/spinner-view-test.js | 399 +- tsconfig.json | 49 + 888 files changed, 99678 insertions(+), 42689 deletions(-) delete mode 100644 .babelrc.js delete mode 100644 .eslintrc.json create mode 100644 .prettierignore create mode 100644 .prettierrc create mode 100644 .prettierrc.json delete mode 100644 bin/ask-skill.js create mode 100644 bin/ask-skill.ts delete mode 100644 bin/ask-smapi.js create mode 100644 bin/ask-smapi.ts delete mode 100644 bin/ask-util.js create mode 100644 bin/ask-util.ts delete mode 100755 bin/ask.js create mode 100755 bin/ask.ts create mode 100644 bin/askx-skill.ts create mode 100644 bin/askx-smapi.ts create mode 100644 bin/askx-util.ts delete mode 100644 lib/clients/metric-client/index.js create mode 100644 lib/clients/metric-client/index.ts delete mode 100644 lib/clients/smapi-client/index.js create mode 100644 lib/clients/smapi-client/index.ts delete mode 100644 lib/clients/smapi-client/resources/manifest.js create mode 100644 lib/clients/smapi-client/resources/manifest.ts delete mode 100644 lib/clients/smapi-client/resources/skill.js create mode 100644 lib/clients/smapi-client/resources/skill.ts delete mode 100644 lib/clients/smapi-client/resources/test.js create mode 100644 lib/clients/smapi-client/resources/test.ts delete mode 100644 lib/commands/abstract-command.js create mode 100644 lib/commands/abstract-command.ts delete mode 100644 lib/commands/configure/index.js create mode 100644 lib/commands/configure/index.ts delete mode 100644 lib/commands/deploy/index.js create mode 100644 lib/commands/deploy/index.ts delete mode 100644 lib/commands/dialog/helper.js create mode 100644 lib/commands/dialog/helper.ts delete mode 100644 lib/commands/dialog/index.js create mode 100644 lib/commands/dialog/index.ts delete mode 100644 lib/commands/dialog/interactive-mode.js create mode 100644 lib/commands/dialog/interactive-mode.ts delete mode 100644 lib/commands/dialog/replay-mode.js create mode 100644 lib/commands/dialog/replay-mode.ts delete mode 100644 lib/commands/init/index.js create mode 100644 lib/commands/init/index.ts delete mode 100644 lib/commands/new/helper.js create mode 100644 lib/commands/new/helper.ts delete mode 100644 lib/commands/new/hosted-skill-helper.js create mode 100644 lib/commands/new/hosted-skill-helper.ts delete mode 100644 lib/commands/new/index.js create mode 100644 lib/commands/new/index.ts create mode 100644 lib/commands/new/template-helper.ts delete mode 100644 lib/commands/new/ui.js create mode 100644 lib/commands/new/ui.ts delete mode 100644 lib/commands/new/wizard-helper.js create mode 100644 lib/commands/new/wizard-helper.ts delete mode 100644 lib/commands/option-validator.js create mode 100644 lib/commands/option-validator.ts delete mode 100644 lib/commands/run/index.js create mode 100644 lib/commands/run/index.ts delete mode 100644 lib/commands/skill/add-locales/index.js create mode 100644 lib/commands/skill/add-locales/index.ts delete mode 100644 lib/commands/skill/skill-commander.js create mode 100644 lib/commands/skill/skill-commander.ts delete mode 100644 lib/commands/smapi/appended-commands/export-package/index.js create mode 100644 lib/commands/smapi/appended-commands/export-package/index.ts delete mode 100644 lib/commands/smapi/appended-commands/get-task/index.js create mode 100644 lib/commands/smapi/appended-commands/get-task/index.ts delete mode 100644 lib/commands/smapi/appended-commands/search-task/index.js create mode 100644 lib/commands/smapi/appended-commands/search-task/index.ts delete mode 100644 lib/commands/smapi/appended-commands/upload-catalog/index.js create mode 100644 lib/commands/smapi/appended-commands/upload-catalog/index.ts delete mode 100644 lib/commands/smapi/smapi-commander.js create mode 100644 lib/commands/smapi/smapi-commander.ts delete mode 100644 lib/commands/util/generate-lwa-tokens/index.js create mode 100644 lib/commands/util/generate-lwa-tokens/index.ts delete mode 100644 lib/commands/util/git-credentials-helper/index.js create mode 100644 lib/commands/util/git-credentials-helper/index.ts delete mode 100644 lib/commands/util/upgrade-project/index.js create mode 100644 lib/commands/util/upgrade-project/index.ts delete mode 100644 lib/commands/util/util-commander.js create mode 100644 lib/commands/util/util-commander.ts delete mode 100644 lib/controllers/dialog-controller/index.js create mode 100644 lib/controllers/dialog-controller/index.ts delete mode 100644 lib/controllers/dialog-controller/simulation-response-parser.js delete mode 100644 lib/controllers/skill-simulation-controller/index.js create mode 100644 lib/controllers/skill-simulation-controller/index.ts create mode 100644 lib/exceptions/cli-data-format-error.ts create mode 100644 lib/exceptions/cli-retriable-error.ts create mode 100644 lib/model/build-status-local-cache.ts create mode 100644 lib/model/callback.ts create mode 100644 lib/model/dialog/inputs.ts create mode 100644 lib/model/import-status.ts create mode 100644 lib/model/sample-template.ts create mode 100644 lib/model/skill-status.ts rename postinstall.js => lib/postinstall.js (100%) create mode 100644 lib/utils/ac-util.js delete mode 100644 lib/view/cli-repl-view.js create mode 100644 lib/view/cli-repl-view.ts delete mode 100644 lib/view/dialog-repl-view.js create mode 100644 lib/view/dialog-repl-view.ts create mode 100644 lib/view/import-status/import-status-view-events.ts create mode 100644 lib/view/import-status/import-status-view-observable.ts create mode 100644 lib/view/import-status/import-status-view.ts delete mode 100644 lib/view/prompt-view.js create mode 100644 lib/view/prompt-view.ts create mode 100644 package-lock.json create mode 100644 test/fixture/dialog-evaluate/test-project-1/.ask/ask-states.json create mode 100644 test/fixture/dialog-evaluate/test-project-1/ask-resources.json create mode 100644 test/fixture/dialog-evaluate/test-project-1/skill-package/conversations/dialogEight.acdl create mode 100644 test/fixture/dialog-evaluate/test-project-1/skill-package/conversations/dialogEleven.acdl create mode 100644 test/fixture/dialog-evaluate/test-project-1/skill-package/conversations/dialogFive.acdl create mode 100644 test/fixture/dialog-evaluate/test-project-1/skill-package/conversations/dialogFour.acdl create mode 100644 test/fixture/dialog-evaluate/test-project-1/skill-package/conversations/dialogNine.acdl create mode 100644 test/fixture/dialog-evaluate/test-project-1/skill-package/conversations/dialogOne.acdl create mode 100644 test/fixture/dialog-evaluate/test-project-1/skill-package/conversations/dialogSeven.acdl create mode 100644 test/fixture/dialog-evaluate/test-project-1/skill-package/conversations/dialogSix.acdl create mode 100644 test/fixture/dialog-evaluate/test-project-1/skill-package/conversations/dialogTen.acdl create mode 100644 test/fixture/dialog-evaluate/test-project-1/skill-package/conversations/dialogThree.acdl create mode 100644 test/fixture/dialog-evaluate/test-project-1/skill-package/conversations/dialogTwo.acdl create mode 100644 test/fixture/dialog-evaluate/test-project-1/skill-package/interactionModels/custom/en-US.json create mode 100644 test/fixture/dialog-evaluate/test-project-1/skill-package/response/display/confirm_city_apl_display/document.json create mode 100644 test/fixture/dialog-evaluate/test-project-1/skill-package/response/display/confirm_date_apl_display/document.json create mode 100644 test/fixture/dialog-evaluate/test-project-1/skill-package/response/display/confirm_weather_apla_display/document.json create mode 100644 test/fixture/dialog-evaluate/test-project-1/skill-package/response/display/request_city_apl_display/document.json create mode 100644 test/fixture/dialog-evaluate/test-project-1/skill-package/response/display/request_date_apl_display/document.json create mode 100644 test/fixture/dialog-evaluate/test-project-1/skill-package/response/display/weather_success_apl_display/document.json create mode 100644 test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/AlexaConversationsBye/document.json create mode 100644 test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/AlexaConversationsNotifyFailure/document.json create mode 100644 test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/AlexaConversationsOutOfDomain/document.json create mode 100644 test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/AlexaConversationsProvideHelp/document.json create mode 100644 test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/AlexaConversationsRequestMore/document.json create mode 100644 test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/AlexaConversationsThankYou/document.json create mode 100644 test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/AlexaConversationsWelcome/document.json create mode 100644 test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/AlexaConversationsYouAreWelcome/document.json create mode 100644 test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/confirmAction_complexNames_apla/document.json create mode 100644 test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/confirmArgs_complexNames_apla/document.json create mode 100644 test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/confirm_colorName_apla/document.json create mode 100644 test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/confirm_main_addon_list_apla/document.json create mode 100644 test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/notused_apla/document.json create mode 100644 test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/numericfeedback_apla/document.json create mode 100644 test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/rating_apla/document.json create mode 100644 test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/request_city_apla/document.json create mode 100644 test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/request_city_date_apla/document.json create mode 100644 test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/request_colorName_apla/document.json create mode 100644 test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/request_date_apla/document.json create mode 100644 test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/request_fruitName_apla/document.json create mode 100644 test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/request_listAddOns_apla/document.json create mode 100644 test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/request_mainFoodName_apla/document.json create mode 100644 test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/request_name_apla/document.json create mode 100644 test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/success_colorFruitAPI_apla/document.json create mode 100644 test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/success_cookingAPI_apla/document.json create mode 100644 test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/success_favColorSign_Name_apla/document.json create mode 100644 test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/success_fruitNameAPI_apla/document.json create mode 100644 test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/success_weather_apla/document.json create mode 100644 test/fixture/dialog-evaluate/test-project-1/skill-package/skill.json create mode 100644 test/temp/abstract-build-flow/build.zip create mode 100644 test/temp/abstract-build-flow/some-file.txt create mode 100644 test/tsconfig.json delete mode 100644 test/unit/clients/metric-client-test.js create mode 100644 test/unit/clients/metric-client-test.ts delete mode 100644 test/unit/clients/smapi-client-test/index.js create mode 100644 test/unit/clients/smapi-client-test/index.test.ts create mode 100644 test/unit/clients/smapi-client-test/index.ts delete mode 100644 test/unit/commands/abstract-command-test.js create mode 100644 test/unit/commands/abstract-command-test.ts delete mode 100644 test/unit/commands/configure/index-test.js create mode 100644 test/unit/commands/configure/index-test.ts delete mode 100644 test/unit/commands/deploy/index-test.js create mode 100644 test/unit/commands/deploy/index-test.ts create mode 100644 test/unit/commands/deploy/ui-test.js delete mode 100644 test/unit/commands/dialog/helper-test.js create mode 100644 test/unit/commands/dialog/helper.spec.ts delete mode 100644 test/unit/commands/dialog/index-test.js create mode 100644 test/unit/commands/dialog/index.spec.ts delete mode 100644 test/unit/commands/dialog/interactive-mode-test.js create mode 100644 test/unit/commands/dialog/interactive-mode.spec.ts delete mode 100644 test/unit/commands/dialog/replay-mode-test.js create mode 100644 test/unit/commands/dialog/replay-mode.spec.ts delete mode 100644 test/unit/commands/init/index-test.js create mode 100644 test/unit/commands/init/index-test.ts delete mode 100644 test/unit/commands/new/helper-test.js create mode 100644 test/unit/commands/new/helper-test.ts delete mode 100644 test/unit/commands/new/hosted-skill-helper-test.js create mode 100644 test/unit/commands/new/hosted-skill-helper-test.ts delete mode 100644 test/unit/commands/new/index-test.js create mode 100644 test/unit/commands/new/index-test.ts create mode 100644 test/unit/commands/new/template-helper-test.ts delete mode 100644 test/unit/commands/new/ui-test.js create mode 100644 test/unit/commands/new/ui-test.ts delete mode 100644 test/unit/commands/new/wizard-helper-test.js create mode 100644 test/unit/commands/new/wizard-helper-test.ts delete mode 100644 test/unit/commands/run/index-test.js create mode 100644 test/unit/commands/run/index-test.ts delete mode 100644 test/unit/commands/skill/add-locales/index-test.js create mode 100644 test/unit/commands/skill/add-locales/index-test.ts create mode 100644 test/unit/commands/skill/skill-commander-test.ts delete mode 100644 test/unit/commands/smapi/appended-commands/export-package/index-test.js create mode 100644 test/unit/commands/smapi/appended-commands/export-package/index-test.ts delete mode 100644 test/unit/commands/smapi/appended-commands/get-task/index-test.js create mode 100644 test/unit/commands/smapi/appended-commands/get-task/index-test.ts delete mode 100644 test/unit/commands/smapi/appended-commands/search-task/index-test.js create mode 100644 test/unit/commands/smapi/appended-commands/search-task/index-test.ts delete mode 100644 test/unit/commands/util/generate-lwa-tokens/index-test.js create mode 100644 test/unit/commands/util/generate-lwa-tokens/index-test.ts delete mode 100644 test/unit/commands/util/git-credentials-helper/index-test.js create mode 100644 test/unit/commands/util/git-credentials-helper/index-test.ts delete mode 100644 test/unit/commands/util/upgrade-project/index-test.js create mode 100644 test/unit/commands/util/upgrade-project/index-test.ts create mode 100644 test/unit/commands/util/util-commander-test.ts delete mode 100644 test/unit/controller/dialog-controller/index-test.js create mode 100644 test/unit/controller/dialog-controller/index.spec.ts create mode 100644 test/unit/controller/dialog-controller/index.test.ts delete mode 100644 test/unit/controller/dialog-controller/simulation-response-parser-test.js delete mode 100644 test/unit/controller/skill-simulation-controller-test.js create mode 100644 test/unit/controller/skill-simulation-controller.spec.ts create mode 100644 test/unit/controller/skill-simulation-controller.test.ts create mode 100644 test/unit/fixture/dialog-evaluate/test-project-1/.ask/ask-states.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-1/ask-resources.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-1/skill-package/conversations/ALexaPrize.acdl create mode 100644 test/unit/fixture/dialog-evaluate/test-project-1/skill-package/conversations/Dialog_NonDeployable.acdl create mode 100644 test/unit/fixture/dialog-evaluate/test-project-1/skill-package/conversations/Dialogs_reusableDialogsUsage_NonDeployableDialogs.acdl create mode 100644 test/unit/fixture/dialog-evaluate/test-project-1/skill-package/conversations/Weather.acdl create mode 100644 test/unit/fixture/dialog-evaluate/test-project-1/skill-package/conversations/apis.acdl create mode 100644 test/unit/fixture/dialog-evaluate/test-project-1/skill-package/conversations/apisNamepaceLambda.acdl create mode 100644 test/unit/fixture/dialog-evaluate/test-project-1/skill-package/conversations/conversation_empty.acdl create mode 100644 test/unit/fixture/dialog-evaluate/test-project-1/skill-package/conversations/fruitNameApi.acdl create mode 100644 test/unit/fixture/dialog-evaluate/test-project-1/skill-package/conversations/soaDialog.acdl create mode 100644 test/unit/fixture/dialog-evaluate/test-project-1/skill-package/conversations/types.acdl create mode 100644 test/unit/fixture/dialog-evaluate/test-project-1/skill-package/conversations/utteracesets.acdl create mode 100644 test/unit/fixture/dialog-evaluate/test-project-1/skill-package/interactionModels/custom/en-US.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/display/confirm_city_apl_display/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/display/confirm_date_apl_display/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/display/confirm_weather_apla_display/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/display/request_city_apl_display/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/display/request_date_apl_display/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/display/weather_success_apl_display/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/AlexaConversationsBye/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/AlexaConversationsNotifyFailure/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/AlexaConversationsOutOfDomain/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/AlexaConversationsProvideHelp/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/AlexaConversationsRequestMore/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/AlexaConversationsThankYou/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/AlexaConversationsWelcome/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/AlexaConversationsYouAreWelcome/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/alexa_prize_preconditions_apla/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/confirm_color_for_fruit_apla/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/confirm_fruitName_apla/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/getEmployeePosition_success_apla/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/no_apla/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/nothing2_apla/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/nothing_apla/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/numericfeedback_apla/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/rating_apla/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/requestArgs_request_fruitName_apla/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/request_city_apla/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/request_city_date_apla/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/request_colorName_multiple_apla/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/request_date_apla/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/request_dob_getDate_apla/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/request_getEmploeeID_apla/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/request_name_apla/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/success_colorFruitAPI_apla/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/success_fruitPriceAPI_apla/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/weather_apla/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/yes_apla/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/yesnofeedback_apla/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-1/skill-package/skill.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/.ask/ask-states.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/ask-resources.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/conversations/Samenamespace.acdl create mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/conversations/apis.acdl create mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/conversations/basicOfferDialog.acdl create mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/conversations/conditions create mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/conversations/conversation_empty create mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/conversations/delegateToSkill.acdl create mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/conversations/dialogWeather.acdl create mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/conversations/listDialogWithConditions.acdl create mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/conversations/optionalDelegate.acdl create mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/conversations/pizza.acdl create mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/conversations/soaDialog.acdl create mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/conversations/types.acdl create mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/conversations/utteracesets.acdl create mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/conversations/welcomeAPI.acdl create mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/interactionModels/custom/en-US.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/display/confirm_city_apl_display/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/display/confirm_date_apl_display/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/display/confirm_weather_apla_display/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/display/request_city_apl_display/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/display/request_date_apl_display/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/display/weather_success_apl_display/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/AlexaConversationsBye/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/AlexaConversationsNotifyFailure/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/AlexaConversationsOutOfDomain/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/AlexaConversationsProvideHelp/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/AlexaConversationsRequestMore/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/AlexaConversationsThankYou/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/AlexaConversationsWelcome/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/AlexaConversationsYouAreWelcome/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/SuccessGiveMeTodaySpecialsEvent_apla/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/SuccessGiveMeTodaySpecialsEvent_apla_failure/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/askForCrustPrompts/datasources/default.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/askForCrustPrompts/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/askForSizePrompts/datasources/default.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/askForSizePrompts/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/askForToppingOnePrompt/datasources/default.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/askForToppingOnePrompt/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/askForToppingTwoPrompt/datasources/default.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/askForToppingTwoPrompt/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/askForToppingsPrompts/datasources/default.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/askForToppingsPrompts/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/askForTwoToppingsPrompts/datasources/default.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/askForTwoToppingsPrompts/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/askForTwoToppingsPrompts_copy/datasources/default.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/askForTwoToppingsPrompts_copy/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/confirmAction_complexNames_apla/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/confirmArgs_complexNames_apla/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/confirmSizePrompt/datasources/default.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/confirmSizePrompt/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/confirmTwoToppingOrderPrompt/datasources/default.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/confirmTwoToppingOrderPrompt/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/confirmTwoToppingOrderPromptcopy/datasources/default.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/confirmTwoToppingOrderPromptcopy/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/confirmTwoToppingsPrompt/datasources/default.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/confirmTwoToppingsPrompt/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/confirm_color_for_fruit_apla/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/confirm_fruitName_apla/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/confirm_main_addon_list_apla/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/confirm_weather_apla/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/confirm_weather_city_apla/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/confirm_weather_date_apla/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/no_apla/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/nothing2_apla/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/nothing_apla/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/numericfeedback_apla/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/rating_apla/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/requestArgs_request_fruitName_apla/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/requestFromBookFlight_apla/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/requestPickUpFromBookCab_apla/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/requestToBookFlight_apla/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/request_city_apla/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/request_city_cityName_apla/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/request_city_cityName_date_AMAZON_DATE_apla/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/request_colorName_multiple_apla/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/request_date_AMAZON_DATE_apla/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/request_date_apla/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/request_listAddOns_apla/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/request_mainFoodName_apla/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/request_name_apla/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/request_sign_apla/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/requestdropToBookCab_apla/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/secondEarthAPI_apla/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/seq_offer_apla/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/successBookCabAPI_apla/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/successBookFlightAPI_apla/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/success_cookingAPI_apla/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/success_favColorSign_Name_apla/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/success_fruitPriceAPI_apla/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/twoToppingOrderSuccessPrompt/datasources/default.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/twoToppingOrderSuccessPrompt/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/weather_success_apla/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/welcome_apla_custom/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/skill.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-3/.ask/ask-states.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-3/ask-resources.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-3/skill-package/TestDataACDLi18n/deBye/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-3/skill-package/TestDataACDLi18n/deHelp/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-3/skill-package/TestDataACDLi18n/deOutOfDomain/datasources/default.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-3/skill-package/TestDataACDLi18n/deOutOfDomain/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-3/skill-package/TestDataACDLi18n/deRequireMore/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-3/skill-package/TestDataACDLi18n/deWelcome/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-3/skill-package/conversations/ALexaPrize.acdl create mode 100644 test/unit/fixture/dialog-evaluate/test-project-3/skill-package/conversations/Dialog_NonDeployable.acdl create mode 100644 test/unit/fixture/dialog-evaluate/test-project-3/skill-package/conversations/Dialogs_reusableDialogsUsage_NonDeployableDialogs.acdl create mode 100644 test/unit/fixture/dialog-evaluate/test-project-3/skill-package/conversations/Weather.acdl create mode 100644 test/unit/fixture/dialog-evaluate/test-project-3/skill-package/conversations/apis.acdl create mode 100644 test/unit/fixture/dialog-evaluate/test-project-3/skill-package/conversations/apisNamepaceLambda.acdl create mode 100644 test/unit/fixture/dialog-evaluate/test-project-3/skill-package/conversations/conversation_empty.acdl create mode 100644 test/unit/fixture/dialog-evaluate/test-project-3/skill-package/conversations/fruitNameApi.acdl create mode 100644 test/unit/fixture/dialog-evaluate/test-project-3/skill-package/conversations/separateConfig.acdl create mode 100644 test/unit/fixture/dialog-evaluate/test-project-3/skill-package/conversations/soaDialog.acdl create mode 100644 test/unit/fixture/dialog-evaluate/test-project-3/skill-package/conversations/types.acdl create mode 100644 test/unit/fixture/dialog-evaluate/test-project-3/skill-package/conversations/utteracesets.acdl create mode 100644 test/unit/fixture/dialog-evaluate/test-project-3/skill-package/interactionModels/custom/de-DE.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-3/skill-package/interactionModels/custom/en-US.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/display/confirm_city_apl_display/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/display/confirm_date_apl_display/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/display/confirm_weather_apla_display/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/display/display_de_apl/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/display/request_city_apl_display/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/display/request_date_apl_display/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/display/weather_success_apl_display/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/AlexaConversationsBye/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/AlexaConversationsNotifyFailure/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/AlexaConversationsOutOfDomain/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/AlexaConversationsProvideHelp/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/AlexaConversationsRequestMore/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/AlexaConversationsThankYou/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/AlexaConversationsWelcome/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/AlexaConversationsYouAreWelcome/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/alexa_prize_preconditions_apla/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/confirm_color_for_fruit_apla/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/confirm_fruitName_apla/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/getEmployeePosition_success_apla/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/no_apla/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/nothing2_apla/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/nothing_apla/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/numericfeedback_apla/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/rating_apla/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/requestArgs_request_fruitName_apla/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/request_city_apla/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/request_city_date_apla/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/request_colorName_multiple_apla/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/request_date_apla/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/request_dob_getDate_apla/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/request_getEmploeeID_apla/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/request_name_apla/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/success_colorFruitAPI_apla/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/success_fruitPriceAPI_apla/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/weather_apla/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/weather_apla_de_apla/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/yes_apla/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/yesnofeedback_apla/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-3/skill-package/skill.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/.ask/ask-states.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/ask-resources.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/conversations/Samenamespace.acdl create mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/conversations/apisMine.acdl create mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/conversations/basicOfferDialog.acdl create mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/conversations/conditions.acdl create mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/conversations/conversation_empty.acdl create mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/conversations/delegateToSkill.acdl create mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/conversations/dialogWeather.acdl create mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/conversations/listDialogWithConditions.acdl create mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/conversations/optionalDelegate.acdl create mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/conversations/pizza.acdl create mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/conversations/soaDialog.acdl create mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/conversations/typesMine.acdl create mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/conversations/utteracesetsMine.acdl create mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/conversations/welcomeAPI.acdl create mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/interactionModels/custom/en-US.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/display/confirm_city_apl_display/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/display/confirm_date_apl_display/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/display/confirm_weather_apla_display/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/display/request_city_apl_display/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/display/request_date_apl_display/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/display/weather_success_apl_display/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/AlexaConversationsBye/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/AlexaConversationsNotifyFailure/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/AlexaConversationsOutOfDomain/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/AlexaConversationsProvideHelp/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/AlexaConversationsRequestMore/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/AlexaConversationsThankYou/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/AlexaConversationsWelcome/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/AlexaConversationsYouAreWelcome/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/SuccessGiveMeTodaySpecialsEvent_apla/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/SuccessGiveMeTodaySpecialsEvent_apla_failure/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/askForCrustPrompts/datasources/default.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/askForCrustPrompts/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/askForSizePrompts/datasources/default.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/askForSizePrompts/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/askForToppingOnePrompt/datasources/default.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/askForToppingOnePrompt/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/askForToppingTwoPrompt/datasources/default.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/askForToppingTwoPrompt/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/askForToppingsPrompts/datasources/default.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/askForToppingsPrompts/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/askForTwoToppingsPrompts/datasources/default.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/askForTwoToppingsPrompts/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/askForTwoToppingsPrompts_copy/datasources/default.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/askForTwoToppingsPrompts_copy/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/confirmAction_complexNames_apla/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/confirmArgs_complexNames_apla/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/confirmSizePrompt/datasources/default.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/confirmSizePrompt/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/confirmTwoToppingOrderPrompt/datasources/default.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/confirmTwoToppingOrderPrompt/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/confirmTwoToppingOrderPromptcopy/datasources/default.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/confirmTwoToppingOrderPromptcopy/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/confirmTwoToppingsPrompt/datasources/default.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/confirmTwoToppingsPrompt/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/confirm_color_for_fruit_apla/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/confirm_fruitName_apla/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/confirm_main_addon_list_apla/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/confirm_weather_apla/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/confirm_weather_city_apla/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/confirm_weather_date_apla/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/no_apla/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/nothing2_apla/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/nothing_apla/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/numericfeedback_apla/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/rating_apla/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/requestArgs_request_fruitName_apla/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/requestFromBookFlight_apla/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/requestPickUpFromBookCab_apla/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/requestToBookFlight_apla/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/request_city_apla/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/request_city_cityName_apla/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/request_city_cityName_date_AMAZON_DATE_apla/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/request_colorName_multiple_apla/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/request_date_AMAZON_DATE_apla/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/request_date_apla/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/request_listAddOns_apla/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/request_mainFoodName_apla/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/request_name_apla/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/request_sign_apla/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/requestdropToBookCab_apla/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/secondEarthAPI_apla/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/seq_offer_apla/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/successBookCabAPI_apla/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/successBookFlightAPI_apla/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/success_cookingAPI_apla/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/success_favColorSign_Name_apla/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/success_fruitPriceAPI_apla/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/twoToppingOrderSuccessPrompt/datasources/default.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/twoToppingOrderSuccessPrompt/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/weather_success_apla/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/welcome_apla_custom/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/skill.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-6/.ask/ask-states.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-6/ask-resources.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-6/skill-package/conversations/ALexaPrize.acdl create mode 100644 test/unit/fixture/dialog-evaluate/test-project-6/skill-package/conversations/Dialog_NonDeployable.acdl create mode 100644 test/unit/fixture/dialog-evaluate/test-project-6/skill-package/conversations/Dialogs_reusableDialogsUsage_NonDeployableDialogs.acdl create mode 100644 test/unit/fixture/dialog-evaluate/test-project-6/skill-package/conversations/Weather.acdl create mode 100644 test/unit/fixture/dialog-evaluate/test-project-6/skill-package/conversations/apisNamepaceLambda.acdl create mode 100644 test/unit/fixture/dialog-evaluate/test-project-6/skill-package/conversations/apis_mine.acdl create mode 100644 test/unit/fixture/dialog-evaluate/test-project-6/skill-package/conversations/conversation_empty.acdl create mode 100644 test/unit/fixture/dialog-evaluate/test-project-6/skill-package/conversations/soaDialog.acdl create mode 100644 test/unit/fixture/dialog-evaluate/test-project-6/skill-package/conversations/types_mine.acdl create mode 100644 test/unit/fixture/dialog-evaluate/test-project-6/skill-package/conversations/utteracesets_mine.acdl create mode 100644 test/unit/fixture/dialog-evaluate/test-project-6/skill-package/interactionModels/custom/en-US.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/display/confirm_city_apl_display/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/display/confirm_date_apl_display/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/display/confirm_weather_apla_display/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/display/request_city_apl_display/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/display/request_date_apl_display/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/display/weather_success_apl_display/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/AlexaConversationsBye/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/AlexaConversationsNotifyFailure/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/AlexaConversationsOutOfDomain/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/AlexaConversationsProvideHelp/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/AlexaConversationsRequestMore/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/AlexaConversationsThankYou/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/AlexaConversationsWelcome/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/AlexaConversationsYouAreWelcome/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/alexa_prize_preconditions_apla/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/confirm_color_for_fruit_apla/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/confirm_fruitName_apla/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/getEmployeePosition_success_apla/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/no_apla/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/nothing2_apla/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/nothing_apla/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/numericfeedback_apla/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/rating_apla/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/requestArgs_request_fruitName_apla/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/request_city_apla/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/request_city_date_apla/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/request_colorName_multiple_apla/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/request_date_apla/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/request_dob_getDate_apla/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/request_getEmploeeID_apla/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/request_name_apla/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/success_colorFruitAPI_apla/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/success_fruitPriceAPI_apla/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/weather_apla/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/yes_apla/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/yesnofeedback_apla/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-6/skill-package/skill.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-7/.ask/ask-states.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-7/ask-resources.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-7/skill-package/TestDataACDLi18n/deBye/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-7/skill-package/TestDataACDLi18n/deHelp/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-7/skill-package/TestDataACDLi18n/deOutOfDomain/datasources/default.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-7/skill-package/TestDataACDLi18n/deOutOfDomain/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-7/skill-package/TestDataACDLi18n/deRequireMore/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-7/skill-package/TestDataACDLi18n/deWelcome/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-7/skill-package/conversations/ALexaPrize.acdl create mode 100644 test/unit/fixture/dialog-evaluate/test-project-7/skill-package/conversations/Dialog_NonDeployable.acdl create mode 100644 test/unit/fixture/dialog-evaluate/test-project-7/skill-package/conversations/Dialogs_reusableDialogsUsage_NonDeployableDialogs.acdl create mode 100644 test/unit/fixture/dialog-evaluate/test-project-7/skill-package/conversations/MoreDialogs.acdl create mode 100644 test/unit/fixture/dialog-evaluate/test-project-7/skill-package/conversations/Weather.acdl create mode 100644 test/unit/fixture/dialog-evaluate/test-project-7/skill-package/conversations/apis.acdl create mode 100644 test/unit/fixture/dialog-evaluate/test-project-7/skill-package/conversations/apisNamepaceLambda create mode 100644 test/unit/fixture/dialog-evaluate/test-project-7/skill-package/conversations/conversation_empty.acdl create mode 100644 test/unit/fixture/dialog-evaluate/test-project-7/skill-package/conversations/delegateToSkill.acdl create mode 100644 test/unit/fixture/dialog-evaluate/test-project-7/skill-package/conversations/fruitNameApi.acdl create mode 100644 test/unit/fixture/dialog-evaluate/test-project-7/skill-package/conversations/separateConfig.acdl create mode 100644 test/unit/fixture/dialog-evaluate/test-project-7/skill-package/conversations/soaDialog.acdl create mode 100644 test/unit/fixture/dialog-evaluate/test-project-7/skill-package/conversations/test create mode 100644 test/unit/fixture/dialog-evaluate/test-project-7/skill-package/conversations/types.acdl create mode 100644 test/unit/fixture/dialog-evaluate/test-project-7/skill-package/conversations/utteracesets.acdl create mode 100644 test/unit/fixture/dialog-evaluate/test-project-7/skill-package/interactionModels/custom/de-DE.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-7/skill-package/interactionModels/custom/en-GB.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-7/skill-package/interactionModels/custom/en-US.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/display/confirm_city_apl_display/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/display/confirm_date_apl_display/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/display/confirm_weather_apla_display/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/display/display_de_apl/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/display/dummyLastScreen/datasources/default.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/display/dummyLastScreen/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/display/dummyLastScreen/sources/default.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/display/request_city_apl_display/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/display/request_date_apl_display/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/display/weather_success_apl_display/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/AlexaConversationsBye/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/AlexaConversationsNotifyFailure/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/AlexaConversationsOutOfDomain/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/AlexaConversationsProvideHelp/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/AlexaConversationsRequestMore/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/AlexaConversationsThankYou/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/AlexaConversationsWelcome/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/AlexaConversationsYouAreWelcome/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/alexa_prize_preconditions_apla/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/confirm_color_for_fruit_apla/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/confirm_fruitName_apla/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/getEmployeePosition_success_apla/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/no_apla/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/nothing2_apla/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/nothing_apla/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/numericfeedback_apla/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/rating_apla/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/requestArgs_request_fruitName_apla/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/request_city_apla/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/request_city_date_apla/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/request_colorName_multiple_apla/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/request_date_apla/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/request_dob_getDate_apla/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/request_getEmploeeID_apla/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/request_name_apla/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/response0Prompt16/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/secondEarthAPI_apla/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/success_colorFruitAPI_apla/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/success_fruitPriceAPI_apla/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/weather_apla/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/weather_apla_de_apla/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/whoAmiSuccess/datasources/default.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/whoAmiSuccess/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/yes_apla/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/yesnofeedback_apla/document.json create mode 100644 test/unit/fixture/dialog-evaluate/test-project-7/skill-package/skill.json create mode 100644 test/unit/model/build-status-local-cache-test.ts create mode 100644 test/unit/model/build-status-local-cache.test.ts create mode 100644 test/unit/model/dialog/input.test.ts create mode 100644 test/unit/model/import-status-test.ts create mode 100644 test/unit/model/import-status.test.ts create mode 100644 test/unit/model/sample-template-test.ts create mode 100644 test/unit/model/skill-status-test.ts create mode 100644 test/unit/model/skill-status.test.ts delete mode 100644 test/unit/view/cli-repl-view-test.js create mode 100644 test/unit/view/cli-repl-view.spec.ts create mode 100644 test/unit/view/cli-repl-view.test.ts delete mode 100644 test/unit/view/dialog-repl-view-test.js create mode 100644 test/unit/view/dialog-repl-view.spec.ts create mode 100644 test/unit/view/dialog-repl-view.test.ts create mode 100644 test/unit/view/import-status/import-status-view-observable-test.ts create mode 100644 test/unit/view/import-status/import-status-view-test.ts delete mode 100644 test/unit/view/prompt-view-test.js create mode 100644 test/unit/view/prompt-view-test.ts create mode 100644 tsconfig.json diff --git a/.babelrc.js b/.babelrc.js deleted file mode 100644 index 5db549ad..00000000 --- a/.babelrc.js +++ /dev/null @@ -1,7 +0,0 @@ -const pck = require('./package.json'); - -const plugins = [ - [ require.resolve('babel-plugin-module-resolver'), { alias: pck._moduleAliases } ] -]; - -module.exports = { plugins, retainLines: true }; diff --git a/.commitlintrc.json b/.commitlintrc.json index ff825635..ab6a75fa 100644 --- a/.commitlintrc.json +++ b/.commitlintrc.json @@ -4,28 +4,10 @@ "footer-leading-blank": [1, "always"], "subject-empty": [2, "never"], "subject-full-stop": [2, "never", "."], - "subject-case": [ - 2, - "never", - ["sentence-case", "pascal-case", "start-case", "upper-case"] - ], + "subject-case": [2, "never", ["sentence-case", "pascal-case", "start-case", "upper-case"]], "scope-case": [2, "always", "lower-case"], "type-case": [2, "always", "lower-case"], "type-empty": [2, "never"], - "type-enum": [ - 2, - "always", - [ - "chore", - "docs", - "feat", - "fix", - "perf", - "refactor", - "revert", - "style", - "test" - ] - ] + "type-enum": [2, "always", ["chore", "docs", "feat", "fix", "perf", "refactor", "revert", "style", "test"]] } } diff --git a/.eslintrc.json b/.eslintrc.json deleted file mode 100644 index a7c92751..00000000 --- a/.eslintrc.json +++ /dev/null @@ -1,51 +0,0 @@ -{ - "extends": "airbnb-base", - "env": { - "commonjs": true, - "node": true, - "mocha": true - }, - "rules": { - "class-methods-use-this" : "off", - "indent": ["error", 4], - "max-len": ["error", 150, 4], - "import/no-unresolved":"off", - "no-plusplus":"off", - "no-underscore-dangle": 0, - "no-lonely-if":"off", - "no-console": "off", - "no-bitwise": ["error", { "allow": ["|"] }], - "no-restricted-syntax": ["error", "ForInStatement"], - "no-param-reassign":"off", - "no-continue":"off", - "no-new":"off", - "no-throw-literal":"off", - "consistent-return":"off", - "object-curly-newline": ["error", { - "ImportDeclaration": "never", - "ExportDeclaration": { - "multiline": true, - "minProperties": 3 - } - }], - "import/no-dynamic-require":"off", - "comma-dangle": ["error", { - "arrays": "only-multiline", - "objects": "only-multiline", - "imports": "never", - "exports": "never", - "functions": "ignore" - }], - "no-use-before-define": ["error", { - "functions": false, - "classes": true, - "variables": true - }], - "no-restricted-properties": "off", - "linebreak-style": "off", - "arrow-parens": "off", - "max-classes-per-file": "off", - "one-var": "off", - "one-var-declaration-per-line": "off" - } -} diff --git a/.gitignore b/.gitignore index e43f823a..be317d49 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,8 @@ # Dependency directories node_modules/ -package-lock.json +build +dist/ +package/ # Logs logs @@ -23,3 +25,5 @@ test/temp .vagrant +# distribution files +*.tgz diff --git a/.npmignore b/.npmignore index 0bcf846d..9c727013 100644 --- a/.npmignore +++ b/.npmignore @@ -9,3 +9,13 @@ docs jsconfig.json scripts test +package-lock.json +build +*.tgz +lib +bin +!dist/** +dist/test +.husky +.prettierrc +.prettierignore diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 00000000..945997df --- /dev/null +++ b/.prettierignore @@ -0,0 +1,7 @@ +.github +dist +build +node_modules +docs +scripts +*.md diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 00000000..0959df2b --- /dev/null +++ b/.prettierrc @@ -0,0 +1,12 @@ +{ + "arrowParens": "always", + "bracketSpacing": false, + "embeddedLanguageFormatting": "auto", + "printWidth": 140, + "proseWrap": "never", + "semi": true, + "singleQuote": false, + "tabWidth": 2, + "trailingComma": "all", + "useTabs": false +} diff --git a/.prettierrc.json b/.prettierrc.json new file mode 100644 index 00000000..62251992 --- /dev/null +++ b/.prettierrc.json @@ -0,0 +1,8 @@ +{ + "printWidth": 140, + "semi": true, + "singleQuote": true, + "tabWidth": 2, + "trailingComma": "all", + "useTabs": false +} diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 347102a7..59d4c39f 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -9,13 +9,14 @@ Below are typical steps to follow if you want to contribute: git clone git@github.com:/ask-cli.git ``` 3. Run `npm install` at the root of the repo -4. Run `npm test` to verify that the tests are passing -5. Make your code change(s) -3. Run `npm test` to verify that the tests are still passing. If you added a new functionality, add tests to ensure that we have adequate test coverage. +4. Run `npm run build` to compile the Typescript part of the source code and tests +5. Run `npm test` to verify that the tests are passing +6. Make your code change(s) +7. Run `npm test` to verify that the tests are still passing. If you added a new functionality, add tests to ensure that we have adequate test coverage. You can check test coverage by running `npm run test:report` -4. Commit your work. Your commit message should follow [conventional commit](https://www.conventionalcommits.org/en/v1.0.0/). We have a pre commit hook to validate the commit message. -5. Send us a pull request, answering any default questions in the pull request interface. The pull request should be going to `develop` branch. -6. Pay attention to any automated CI failures reported in the pull request, and stay involved in the conversation. +8. Commit your work. Your commit message should follow [conventional commit](https://www.conventionalcommits.org/en/v1.0.0/). We have a pre commit hook to validate the commit message. +9. Send us a pull request, answering any default questions in the pull request interface. The pull request should be going to `develop` branch. +10. Pay attention to any automated CI failures reported in the pull request, and stay involved in the conversation. ## Branch Organization diff --git a/bin/ask-skill.js b/bin/ask-skill.js deleted file mode 100644 index 6334457e..00000000 --- a/bin/ask-skill.js +++ /dev/null @@ -1,13 +0,0 @@ -#!/usr/bin/env node - -require('module-alias/register'); -const skillCommander = require('@src/commands/skill/skill-commander'); - -skillCommander.commander.parse(process.argv); - -if (!process.argv.slice(2).length) { - skillCommander.commander.outputHelp(); -} else if (Object.keys(skillCommander.SKILL_COMMAND_MAP).indexOf(process.argv[2]) === -1) { - console.error('Command not recognized. Please run "ask skill" to check the user instructions.'); - process.exit(1); -} diff --git a/bin/ask-skill.ts b/bin/ask-skill.ts new file mode 100644 index 00000000..7a3eb98c --- /dev/null +++ b/bin/ask-skill.ts @@ -0,0 +1,12 @@ +#!/usr/bin/env node + +import {commander, SKILL_COMMAND_MAP} from "../lib/commands/skill/skill-commander"; + +commander.parse(process.argv); + +if (!process.argv.slice(2).length) { + commander.outputHelp(); +} else if (SKILL_COMMAND_MAP[process.argv[2]] === undefined) { + console.error('Command not recognized. Please run "ask skill" to check the user instructions.'); + process.exit(1); +} diff --git a/bin/ask-smapi.js b/bin/ask-smapi.js deleted file mode 100644 index 73a10a9d..00000000 --- a/bin/ask-smapi.js +++ /dev/null @@ -1,19 +0,0 @@ -#!/usr/bin/env node - -require('module-alias/register'); -const Messenger = require('@src/view/messenger'); -const jsonView = require('@src/view/json-view'); -const { makeSmapiCommander } = require('@src/commands/smapi/smapi-commander'); - -const commander = makeSmapiCommander(); - -if (!process.argv.slice(2).length) { - commander.outputHelp(); -} else { - commander.parseAsync(process.argv) - .then(result => Messenger.getInstance().info(result)) - .catch(err => { - Messenger.getInstance().error(jsonView.toString(err)); - process.exit(1); - }); -} diff --git a/bin/ask-smapi.ts b/bin/ask-smapi.ts new file mode 100644 index 00000000..a8c69f36 --- /dev/null +++ b/bin/ask-smapi.ts @@ -0,0 +1,19 @@ +#!/usr/bin/env node + +import Messenger from "../lib/view/messenger"; +import jsonView from "../lib/view/json-view"; +import {makeSmapiCommander} from "../lib/commands/smapi/smapi-commander"; + +const commander = makeSmapiCommander(); + +if (!process.argv.slice(2).length) { + commander.outputHelp(); +} else { + commander + .parseAsync(process.argv) + .then((result) => Messenger.getInstance().info(result)) + .catch((err) => { + Messenger.getInstance().error(jsonView.toString(err)); + process.exit(1); + }); +} diff --git a/bin/ask-util.js b/bin/ask-util.js deleted file mode 100644 index fa3fcdd1..00000000 --- a/bin/ask-util.js +++ /dev/null @@ -1,13 +0,0 @@ -#!/usr/bin/env node - -require('module-alias/register'); -const utilCommander = require('@src/commands/util/util-commander'); - -utilCommander.commander.parse(process.argv); - -if (!process.argv.slice(2).length) { - utilCommander.commander.outputHelp(); -} else if (Object.keys(utilCommander.UTIL_COMMAND_MAP).indexOf(process.argv[2]) === -1) { - console.error('Command not recognized. Please run "ask util" to check the user instructions.'); - process.exit(1); -} diff --git a/bin/ask-util.ts b/bin/ask-util.ts new file mode 100644 index 00000000..e0fcd518 --- /dev/null +++ b/bin/ask-util.ts @@ -0,0 +1,11 @@ +#!/usr/bin/env node +import {commander, UTIL_COMMAND_MAP} from "../lib/commands/util/util-commander"; + +commander.parse(process.argv); + +if (!process.argv.slice(2).length) { + commander.outputHelp(); +} else if (UTIL_COMMAND_MAP[process.argv[2]] === undefined) { + console.error('Command not recognized. Please run "ask util" to check the user instructions.'); + process.exit(1); +} diff --git a/bin/ask.js b/bin/ask.js deleted file mode 100755 index 411e5942..00000000 --- a/bin/ask.js +++ /dev/null @@ -1,33 +0,0 @@ -#!/usr/bin/env node -/* eslint-disable global-require */ - -if (!require('semver').gte(process.version, '8.3.0')) { - console.log('Version of node.js doesn\'t meet minimum requirement.'); - console.log('Please ensure system has node.js version 8.3.0 or higher.'); - process.exit(1); -} - -require('module-alias/register'); -const commander = require('commander'); - -require('@src/commands/configure').createCommand(commander); -require('@src/commands/deploy').createCommand(commander); -require('@src/commands/new').createCommand(commander); -require('@src/commands/init').createCommand(commander); -require('@src/commands/dialog').createCommand(commander); -require('@src/commands/run').createCommand(commander); - -commander - .description('Command Line Interface for Alexa Skill Kit') - .command('smapi', 'list of Alexa Skill Management API commands') - .command('skill', 'increase the productivity when managing skill metadata') - .command('util', 'tooling functions when using ask-cli to manage Alexa Skill') - .version(require('../package.json').version) - .parse(process.argv); - -const ALLOWED_ASK_ARGV_2 = ['configure', 'deploy', 'new', 'init', 'dialog', 'smapi', 'skill', 'util', 'help', '-v', - '--version', '-h', '--help', 'run']; -if (process.argv[2] && ALLOWED_ASK_ARGV_2.indexOf(process.argv[2]) === -1) { - console.log('Command not recognized. Please run "ask" to check the user instructions.'); - process.exit(1); -} diff --git a/bin/ask.ts b/bin/ask.ts new file mode 100755 index 00000000..cc1e8024 --- /dev/null +++ b/bin/ask.ts @@ -0,0 +1,51 @@ +#!/usr/bin/env node +import semver from "semver"; + +if (!semver.gte(process.version, "8.3.0")) { + console.log("Version of node.js doesn't meet minimum requirement."); + console.log("Please ensure system has node.js version 8.3.0 or higher."); + process.exit(1); +} + +import { Command } from 'commander'; +const commander = new Command(); + +import {createCommand as configureCommand} from "../lib/commands/configure"; +import {createCommand as deployCommand} from "../lib/commands/deploy"; +import {createCommand as newCommand} from "../lib/commands/new"; +import {createCommand as initCommand} from "../lib/commands/init"; +import {createCommand as dialogCommand} from "../lib/commands/dialog"; +import {createCommand as runCommand} from "../lib/commands/run"; + +[configureCommand, deployCommand, newCommand, initCommand, dialogCommand, runCommand].forEach( + (command) => command(commander), +); + +commander + .description("Command Line Interface for Alexa Skill Kit") + .command("smapi", "list of Alexa Skill Management API commands") + .command("skill", "increase the productivity when managing skill metadata") + .command("util", "tooling functions when using ask-cli to manage Alexa Skill") + .version(require("../package.json").version) + .parse(process.argv); + +const ALLOWED_ASK_ARGV_2 = [ + "configure", + "deploy", + "new", + "init", + "dialog", + "smapi", + "skill", + "util", + "help", + "-v", + "--version", + "-h", + "--help", + "run", +]; +if (process.argv[2] && ALLOWED_ASK_ARGV_2.indexOf(process.argv[2]) === -1) { + console.log('Command not recognized. Please run "ask" to check the user instructions.'); + process.exit(1); +} diff --git a/bin/askx-skill.ts b/bin/askx-skill.ts new file mode 100644 index 00000000..7a3eb98c --- /dev/null +++ b/bin/askx-skill.ts @@ -0,0 +1,12 @@ +#!/usr/bin/env node + +import {commander, SKILL_COMMAND_MAP} from "../lib/commands/skill/skill-commander"; + +commander.parse(process.argv); + +if (!process.argv.slice(2).length) { + commander.outputHelp(); +} else if (SKILL_COMMAND_MAP[process.argv[2]] === undefined) { + console.error('Command not recognized. Please run "ask skill" to check the user instructions.'); + process.exit(1); +} diff --git a/bin/askx-smapi.ts b/bin/askx-smapi.ts new file mode 100644 index 00000000..a8c69f36 --- /dev/null +++ b/bin/askx-smapi.ts @@ -0,0 +1,19 @@ +#!/usr/bin/env node + +import Messenger from "../lib/view/messenger"; +import jsonView from "../lib/view/json-view"; +import {makeSmapiCommander} from "../lib/commands/smapi/smapi-commander"; + +const commander = makeSmapiCommander(); + +if (!process.argv.slice(2).length) { + commander.outputHelp(); +} else { + commander + .parseAsync(process.argv) + .then((result) => Messenger.getInstance().info(result)) + .catch((err) => { + Messenger.getInstance().error(jsonView.toString(err)); + process.exit(1); + }); +} diff --git a/bin/askx-util.ts b/bin/askx-util.ts new file mode 100644 index 00000000..e0fcd518 --- /dev/null +++ b/bin/askx-util.ts @@ -0,0 +1,11 @@ +#!/usr/bin/env node +import {commander, UTIL_COMMAND_MAP} from "../lib/commands/util/util-commander"; + +commander.parse(process.argv); + +if (!process.argv.slice(2).length) { + commander.outputHelp(); +} else if (UTIL_COMMAND_MAP[process.argv[2]] === undefined) { + console.error('Command not recognized. Please run "ask util" to check the user instructions.'); + process.exit(1); +} diff --git a/docs/FAQ.md b/docs/FAQ.md index 9943e775..56f6db86 100644 --- a/docs/FAQ.md +++ b/docs/FAQ.md @@ -27,9 +27,3 @@ Related issues: https://github.com/alexa/ask-cli/issues/38, https://github.com/a ### Q: How to deploy only skill package and ignore skillInfrastructure? ASK CLI v1 had option '--target' to deploy only skill package and not the infrastructure. Similar behavior can be achieved in ASK CLI v2 by removing "skillInfrastructure" property from ask-resources.json. - - ---- - -### Q: For users of ask-cli-x, if you encounter issue when using the CLI: -We have upgraded to v2 ask-cli. If you are still using ask-cli-x, we suggest you installing/updating the ask-cli. Please check the detailed solution in https://github.com/alexa/ask-cli/issues/74. diff --git a/docs/concepts/Alexa-Skill-Project-Definition.md b/docs/concepts/Alexa-Skill-Project-Definition.md index 64021e8c..291246e1 100644 --- a/docs/concepts/Alexa-Skill-Project-Definition.md +++ b/docs/concepts/Alexa-Skill-Project-Definition.md @@ -31,7 +31,7 @@ Below shows the example how CLI tracks user's config and the deployment states, ### ask-resources.json (this file is up to configure!) ```jsonc { - "profiles": { + "profiles": { "{profileName}": { // profile name-specific config "skillMetadata": { // Alexa skill metadata to deploy diff --git a/jsconfig.json b/jsconfig.json index 908ecb4e..d33f277b 100644 --- a/jsconfig.json +++ b/jsconfig.json @@ -1,13 +1,6 @@ { - "compilerOptions": { - "baseUrl": ".", - "paths": { - "@src/*": ["./lib/*"], - "@test/*": ["./test/*"] - } - }, - "include": [ - "lib", - "test" - ], + "compilerOptions": { + "baseUrl": "." + }, + "include": ["lib", "test"] } diff --git a/lib/builtins/build-flows/abstract-build-flow.js b/lib/builtins/build-flows/abstract-build-flow.js index 2056ba47..d11aab23 100644 --- a/lib/builtins/build-flows/abstract-build-flow.js +++ b/lib/builtins/build-flows/abstract-build-flow.js @@ -1,94 +1,94 @@ -const AdmZip = require('adm-zip'); -const childProcess = require('child_process'); -const path = require('path'); +const AdmZip = require("adm-zip"); +const childProcess = require("child_process"); +const path = require("path"); -const Messenger = require('@src/view/messenger'); +const Messenger = require("../../../lib/view/messenger"); class AbstractBuildFlow { - /** - * Constructor - * @param {Object} options - * @param {String} options.cwd working directory for build - * @param {String} options.src source directory - * @param {String} options.buildFile full path for zip file to generate - * @param {Boolean} options.doDebug debug flag - */ - constructor({ cwd, src, buildFile, doDebug }) { - this.cwd = cwd; - this.src = src; - this.buildFile = buildFile; - this.env = process.env; - this.stdio = 'inherit'; - this.doDebug = !!doDebug; - this.isWindows = process.platform === 'win32'; - this.defaultZipFileDate = new Date(1990, 1, 1); + /** + * Constructor + * @param {Object} options + * @param {String} options.cwd working directory for build + * @param {String} options.src source directory + * @param {String} options.buildFile full path for zip file to generate + * @param {Boolean} options.doDebug debug flag + */ + constructor({ cwd, src, buildFile, doDebug }) { + this.cwd = cwd; + this.src = src; + this.buildFile = buildFile; + this.env = process.env; + this.stdio = "inherit"; + this.doDebug = !!doDebug; + this.isWindows = process.platform === "win32"; + this.defaultZipFileDate = new Date(1990, 1, 1); + } + + /** + * Creates build zip file + * @param {Object} options + * @param {Object} options.filter filter to apply to exclude files from zip + * @param {Function} callback + */ + createZip(options, callback) { + if (typeof options === "function") { + callback = options; + options = {}; } + const filter = options.filter || (() => false); - /** - * Creates build zip file - * @param {Object} options - * @param {Object} options.filter filter to apply to exclude files from zip - * @param {Function} callback - */ - createZip(options, callback) { - if (typeof options === 'function') { - callback = options; - options = {}; - } - const filter = options.filter || (() => false); + this.debug(`Zipping source files and dependencies to ${this.buildFile}.`); + const zip = new AdmZip(); + const zipFileName = path.basename(this.buildFile); - this.debug(`Zipping source files and dependencies to ${this.buildFile}.`); - const zip = new AdmZip(); - const zipFileName = path.basename(this.buildFile); + // adding files + zip.addLocalFolder(this.cwd, "", (entry) => entry !== zipFileName && !filter(entry)); + // setting create timestamp to the same value to allow consistent hash + zip.getEntries().forEach(e => { e.header.time = this.defaultZipFileDate; }); - // adding files - zip.addLocalFolder(this.cwd, '', (entry) => entry !== zipFileName && !filter(entry)); - // setting create timestamp to the same value to allow consistent hash - zip.getEntries().forEach(e => { e.header.time = this.defaultZipFileDate; }); + zip.writeZip(this.buildFile, callback); + } - zip.writeZip(this.buildFile, callback); + /** + * Modifies build zip file + * @param {Object} options + * @param {Object} options.entryProcessor function to apply to each zip file entry + * @param {Function} callback + */ + modifyZip(options, callback) { + if (typeof options === "function") { + callback = options; + options = {}; } + const zip = new AdmZip(this.buildFile); - /** - * Modifies build zip file - * @param {Object} options - * @param {Object} options.entryProcessor function to apply to each zip file entry - * @param {Function} callback - */ - modifyZip(options, callback) { - if (typeof options === 'function') { - callback = options; - options = {}; - } - const zip = new AdmZip(this.buildFile); - - const entryProcessor = options.entryProcessor || (() => {}); + const entryProcessor = options.entryProcessor || (() => { }); - zip.getEntries().forEach(e => { - // setting create timestamp to the same value to allow consistent hash - e.header.time = this.defaultZipFileDate; - entryProcessor(e); - }); - zip.writeZip(this.buildFile, callback); - } + zip.getEntries().forEach(e => { + // setting create timestamp to the same value to allow consistent hash + e.header.time = this.defaultZipFileDate; + entryProcessor(e); + }); + zip.writeZip(this.buildFile, callback); + } - /** - * Executes shell command - * @param {String} cmd command - */ - execCommand(cmd) { - childProcess.execSync(cmd, { cwd: this.cwd, env: this.env, stdio: this.stdio }); - } + /** + * Executes shell command + * @param {String} cmd command + */ + execCommand(cmd) { + childProcess.execSync(cmd, { cwd: this.cwd, env: this.env, stdio: this.stdio }); + } - /** - * Outputs debug message - * @param {String} message message - */ - debug(message) { - if (this.doDebug) { - Messenger.getInstance().debug(message); - } + /** + * Outputs debug message + * @param {String} message message + */ + debug(message) { + if (this.doDebug) { + Messenger.getInstance().debug(message); } + } } module.exports = AbstractBuildFlow; diff --git a/lib/builtins/build-flows/custom.js b/lib/builtins/build-flows/custom.js index 0d1baf13..390e1316 100644 --- a/lib/builtins/build-flows/custom.js +++ b/lib/builtins/build-flows/custom.js @@ -1,50 +1,54 @@ -const fs = require('fs-extra'); -const path = require('path'); +const fs = require("fs-extra"); +const path = require("path"); -const AbstractBuildFlow = require('./abstract-build-flow'); +const AbstractBuildFlow = require("./abstract-build-flow"); class CustomBuildFlow extends AbstractBuildFlow { - /** - * If this file exists than the build flow can handle build - */ - static get manifest() { return process.platform === 'win32' ? 'build.ps1' : 'build.sh'; } + /** + * If this file exists than the build flow can handle build + */ + static get manifest() { + return process.platform === "win32" ? "build.ps1" : "build.sh"; + } - static get _customScriptPath() { return path.join(process.cwd(), 'hooks', CustomBuildFlow.manifest); } + static get _customScriptPath() { + return path.join(process.cwd(), "hooks", CustomBuildFlow.manifest); + } - /** - * Returns true if the build flow can handle the build - */ - static canHandle() { - return fs.existsSync(CustomBuildFlow._customScriptPath); - } + /** + * Returns true if the build flow can handle the build + */ + static canHandle() { + return fs.existsSync(CustomBuildFlow._customScriptPath); + } - /** - * Constructor - * @param {Object} options - * @param {String} options.cwd working directory for build - * @param {String} options.src source directory - * @param {String} options.buildFile full path for zip file to generate - * @param {Boolean} options.doDebug debug flag - */ - constructor({ cwd, src, buildFile, doDebug }) { - super({ cwd, src, buildFile, doDebug }); - } + /** + * Constructor + * @param {Object} options + * @param {String} options.cwd working directory for build + * @param {String} options.src source directory + * @param {String} options.buildFile full path for zip file to generate + * @param {Boolean} options.doDebug debug flag + */ + constructor({cwd, src, buildFile, doDebug}) { + super({cwd, src, buildFile, doDebug}); + } - /** - * Executes build - * @param {Function} callback - */ - execute(callback) { - this.debug(`Executing custom hook script ${CustomBuildFlow._customScriptPath}.`); - let command = `${CustomBuildFlow._customScriptPath} "${this.buildFile}" ${this.doDebug}`; - if (this.isWindows) { - const powerShellPrefix = 'PowerShell.exe -Command'; - const doDebug = this.doDebug ? '$True' : '$False'; - command = `${powerShellPrefix} "& {& '${CustomBuildFlow._customScriptPath}' '${this.buildFile}' ${doDebug} }"`; - } - this.execCommand(command); - callback(); + /** + * Executes build + * @param {Function} callback + */ + execute(callback) { + this.debug(`Executing custom hook script ${CustomBuildFlow._customScriptPath}.`); + let command = `${CustomBuildFlow._customScriptPath} "${this.buildFile}" ${this.doDebug}`; + if (this.isWindows) { + const powerShellPrefix = "PowerShell.exe -Command"; + const doDebug = this.doDebug ? "$True" : "$False"; + command = `${powerShellPrefix} "& {& '${CustomBuildFlow._customScriptPath}' '${this.buildFile}' ${doDebug} }"`; } + this.execCommand(command); + callback(); + } } module.exports = CustomBuildFlow; diff --git a/lib/builtins/build-flows/java-mvn.js b/lib/builtins/build-flows/java-mvn.js index 5fd3cc32..cf42b548 100644 --- a/lib/builtins/build-flows/java-mvn.js +++ b/lib/builtins/build-flows/java-mvn.js @@ -1,57 +1,63 @@ -const fs = require('fs-extra'); -const path = require('path'); +const fs = require("fs-extra"); +const path = require("path"); -const AbstractBuildFlow = require('./abstract-build-flow'); +const AbstractBuildFlow = require("./abstract-build-flow"); class JavaMvnBuildFlow extends AbstractBuildFlow { - /** - * If this file exists than the build flow can handle build - */ - static get manifest() { return 'pom.xml'; } - - /** - * Returns true if the build flow can handle the build - */ - static canHandle({ src }) { - return fs.existsSync(path.join(src, JavaMvnBuildFlow.manifest)); - } - - /** - * Constructor - * @param {Object} options - * @param {String} options.cwd working directory for build - * @param {String} options.src source directory - * @param {String} options.buildFile full path for zip file to generate - * @param {Boolean} options.doDebug debug flag - */ - constructor({ cwd, src, buildFile, doDebug }) { - super({ cwd, src, buildFile, doDebug }); - } - - /** - * Executes build - * @param {Function} callback - */ - execute(callback) { - this.debug(`Building skill artifacts based on the ${JavaMvnBuildFlow.manifest}.`); - this.execCommand('mvn clean org.apache.maven.plugins:maven-assembly-plugin:2.6:assembly ' - + '-DdescriptorId=jar-with-dependencies package'); - const targetFolderPath = path.join(this.cwd, 'target'); - const jarFileName = fs.readdirSync(targetFolderPath).find(fileName => fileName.endsWith('jar-with-dependencies.jar')); - const jarFilePath = path.join(targetFolderPath, jarFileName); - this.debug(`Renaming the jar file ${jarFilePath} to ${this.buildFile}.`); - fs.moveSync(jarFilePath, this.buildFile, { overwrite: true }); - - this.modifyZip({ entryProcessor: this._removeCommentsFromPomProperties }, callback); - } - - _removeCommentsFromPomProperties(entry) { - // removing comment to allow consistent hashing - if (entry.entryName.includes('pom.properties')) { - const data = entry.getData().toString().replace(/^#.*\n?/mg, ''); - entry.setData(data); - } + /** + * If this file exists than the build flow can handle build + */ + static get manifest() { + return "pom.xml"; + } + + /** + * Returns true if the build flow can handle the build + */ + static canHandle({src}) { + return fs.existsSync(path.join(src, JavaMvnBuildFlow.manifest)); + } + + /** + * Constructor + * @param {Object} options + * @param {String} options.cwd working directory for build + * @param {String} options.src source directory + * @param {String} options.buildFile full path for zip file to generate + * @param {Boolean} options.doDebug debug flag + */ + constructor({cwd, src, buildFile, doDebug}) { + super({cwd, src, buildFile, doDebug}); + } + + /** + * Executes build + * @param {Function} callback + */ + execute(callback) { + this.debug(`Building skill artifacts based on the ${JavaMvnBuildFlow.manifest}.`); + this.execCommand( + "mvn clean org.apache.maven.plugins:maven-assembly-plugin:2.6:assembly " + "-DdescriptorId=jar-with-dependencies package", + ); + const targetFolderPath = path.join(this.cwd, "target"); + const jarFileName = fs.readdirSync(targetFolderPath).find((fileName) => fileName.endsWith("jar-with-dependencies.jar")); + const jarFilePath = path.join(targetFolderPath, jarFileName); + this.debug(`Renaming the jar file ${jarFilePath} to ${this.buildFile}.`); + fs.moveSync(jarFilePath, this.buildFile, {overwrite: true}); + + this.modifyZip({entryProcessor: this._removeCommentsFromPomProperties}, callback); + } + + _removeCommentsFromPomProperties(entry) { + // removing comment to allow consistent hashing + if (entry.entryName.includes("pom.properties")) { + const data = entry + .getData() + .toString() + .replace(/^#.*\n?/gm, ""); + entry.setData(data); } + } } module.exports = JavaMvnBuildFlow; diff --git a/lib/builtins/build-flows/nodejs-npm.js b/lib/builtins/build-flows/nodejs-npm.js index d7715170..a0d956b6 100644 --- a/lib/builtins/build-flows/nodejs-npm.js +++ b/lib/builtins/build-flows/nodejs-npm.js @@ -1,51 +1,53 @@ -const fs = require('fs-extra'); -const path = require('path'); +const fs = require("fs-extra"); +const path = require("path"); -const AbstractBuildFlow = require('./abstract-build-flow'); +const AbstractBuildFlow = require("./abstract-build-flow"); class NodeJsNpmBuildFlow extends AbstractBuildFlow { - /** - * If this file exists than the build flow can handle build - */ - static get manifest() { return 'package.json'; } - - static get _lockFiles() { return ['package-lock.json', 'npm-shrinkwrap.json']; } - - /** - * Returns true if the build flow can handle the build - */ - static canHandle({ src }) { - return fs.existsSync(path.join(src, NodeJsNpmBuildFlow.manifest)); - } - - /** - * Constructor - * @param {Object} options - * @param {String} options.cwd working directory for build - * @param {String} options.src source directory - * @param {String} options.buildFile full path for zip file to generate - * @param {Boolean} options.doDebug debug flag - */ - constructor({ cwd, src, buildFile, doDebug }) { - super({ cwd, src, buildFile, doDebug }); - } - - /** - * Executes build - * @param {Function} callback - */ - execute(callback) { - const installCmd = this._hasLockFile() ? 'ci' : 'install'; - const quietFlag = this.doDebug ? '' : ' --quiet'; - this.env.NODE_ENV = 'production'; - this.debug(`Installing NodeJS dependencies based on the ${NodeJsNpmBuildFlow.manifest}.`); - this.execCommand(`npm ${installCmd}${quietFlag}`); - this.createZip(callback); - } - - _hasLockFile() { - return NodeJsNpmBuildFlow._lockFiles.some(file => fs.existsSync(path.join(this.src, file))); - } + /** + * If this file exists than the build flow can handle build + */ + static get manifest() { + return "package.json"; + } + + static get _lockFiles() { return ["package-lock.json", "npm-shrinkwrap.json"]; } + + /** + * Returns true if the build flow can handle the build + */ + static canHandle({ src }) { + return fs.existsSync(path.join(src, NodeJsNpmBuildFlow.manifest)); + } + + /** + * Constructor + * @param {Object} options + * @param {String} options.cwd working directory for build + * @param {String} options.src source directory + * @param {String} options.buildFile full path for zip file to generate + * @param {Boolean} options.doDebug debug flag + */ + constructor({ cwd, src, buildFile, doDebug }) { + super({ cwd, src, buildFile, doDebug }); + } + + /** + * Executes build + * @param {Function} callback + */ + execute(callback) { + const installCmd = this._hasLockFile() ? "ci" : "install"; + const quietFlag = this.doDebug ? "" : " --quiet"; + this.env.NODE_ENV = "production"; + this.debug(`Installing NodeJS dependencies based on the ${NodeJsNpmBuildFlow.manifest}.`); + this.execCommand(`npm ${installCmd}${quietFlag}`); + this.createZip(callback); + } + + _hasLockFile() { + return NodeJsNpmBuildFlow._lockFiles.some(file => fs.existsSync(path.join(this.src, file))); + } } module.exports = NodeJsNpmBuildFlow; diff --git a/lib/builtins/build-flows/python-pip.js b/lib/builtins/build-flows/python-pip.js index c2243a8d..effe3860 100644 --- a/lib/builtins/build-flows/python-pip.js +++ b/lib/builtins/build-flows/python-pip.js @@ -1,64 +1,70 @@ -const childProcess = require('child_process'); -const fs = require('fs-extra'); -const path = require('path'); +const childProcess = require("child_process"); +const fs = require("fs-extra"); +const path = require("path"); -const CliError = require('@src/exceptions/cli-error'); -const AbstractBuildFlow = require('./abstract-build-flow'); +const CliError = require("../../exceptions/cli-error"); +const AbstractBuildFlow = require("./abstract-build-flow"); class PythonPipBuildFlow extends AbstractBuildFlow { - /** - * If this file exists than the build flow can handle build - */ - static get manifest() { return 'requirements.txt'; } + /** + * If this file exists than the build flow can handle build + */ + static get manifest() { + return "requirements.txt"; + } - /** - * Returns true if the build flow can handle the build - */ - static canHandle({ src }) { - return fs.existsSync(path.join(src, PythonPipBuildFlow.manifest)); - } + /** + * Returns true if the build flow can handle the build + */ + static canHandle({src}) { + return fs.existsSync(path.join(src, PythonPipBuildFlow.manifest)); + } - /** - * Constructor - * @param {Object} options - * @param {String} options.cwd working directory for build - * @param {String} options.src source directory - * @param {String} options.buildFile full path for zip file to generate - * @param {Boolean} options.doDebug debug flag - */ - constructor({ cwd, src, buildFile, doDebug }) { - super({ cwd, src, buildFile, doDebug }); - } + /** + * Constructor + * @param {Object} options + * @param {String} options.cwd working directory for build + * @param {String} options.src source directory + * @param {String} options.buildFile full path for zip file to generate + * @param {Boolean} options.doDebug debug flag + */ + constructor({cwd, src, buildFile, doDebug}) { + super({cwd, src, buildFile, doDebug}); + } - /** - * Executes build - * @param {Function} callback - */ - execute(callback) { - const python = this.isWindows ? 'python' : 'python3'; - const pipCmdPrefix = this.isWindows ? '"venv/Scripts/pip3"' : 'venv/bin/python -m pip'; + /** + * Executes build + * @param {Function} callback + */ + execute(callback) { + const python = this.isWindows ? "python" : "python3"; + const pipCmdPrefix = this.isWindows ? '"venv/Scripts/pip3"' : "venv/bin/python -m pip"; - const { isPython2, version } = this._checkPythonVersion(python); - if (isPython2) { - return callback(new CliError(`Current python (${version}) is not supported. ` - + 'Please make sure you are using python3, or use your custom script to build the code.')); - } - this.debug('Setting up virtual environment.'); - this.execCommand(`${python} -m venv venv`); - this.debug(`Installing Python dependencies based on the ${PythonPipBuildFlow.manifest}.`); - this.execCommand(`${pipCmdPrefix} --disable-pip-version-check install -r requirements.txt -t ./`); - fs.removeSync(path.join(this.cwd, 'venv')); - // filtering out to allow consistent hashing - const filter = (entry) => entry.includes('__pycache__'); - this.createZip({ filter }, (error) => callback(error)); + const {isPython2, version} = this._checkPythonVersion(python); + if (isPython2) { + return callback( + new CliError( + `Current python (${version}) is not supported. ` + + "Please make sure you are using python3, or use your custom script to build the code.", + ), + ); } + this.debug("Setting up virtual environment."); + this.execCommand(`${python} -m venv venv`); + this.debug(`Installing Python dependencies based on the ${PythonPipBuildFlow.manifest}.`); + this.execCommand(`${pipCmdPrefix} --disable-pip-version-check install -r requirements.txt -t ./`); + fs.removeSync(path.join(this.cwd, "venv")); + // filtering out to allow consistent hashing + const filter = (entry) => entry.includes("__pycache__"); + this.createZip({filter}, (error) => callback(error)); + } - _checkPythonVersion(python) { - const versionStr = childProcess.spawnSync(python, ['--version']).output.toString().trim(); - const [version] = versionStr.match(/\d\.\d+\.\d+/gm); - const isPython2 = version.startsWith('2.'); - return { isPython2, version }; - } + _checkPythonVersion(python) { + const versionStr = childProcess.spawnSync(python, ["--version"]).output.toString().trim(); + const [version] = versionStr.match(/\d\.\d+\.\d+/gm); + const isPython2 = version.startsWith("2."); + return {isPython2, version}; + } } module.exports = PythonPipBuildFlow; diff --git a/lib/builtins/build-flows/zip-only.js b/lib/builtins/build-flows/zip-only.js index 22a8d580..8fea831b 100644 --- a/lib/builtins/build-flows/zip-only.js +++ b/lib/builtins/build-flows/zip-only.js @@ -1,32 +1,32 @@ -const AbstractBuildFlow = require('./abstract-build-flow'); +const AbstractBuildFlow = require("./abstract-build-flow"); class ZipOnlyBuildFlow extends AbstractBuildFlow { - /** - * Returns true if the build flow can handle the build - */ - static canHandle() { - return true; - } + /** + * Returns true if the build flow can handle the build + */ + static canHandle() { + return true; + } - /** - * Constructor - * @param {Object} options - * @param {String} options.cwd working directory for build - * @param {String} options.src source directory - * @param {String} options.buildFile full path for zip file to generate - * @param {Boolean} options.doDebug debug flag - */ - constructor({ cwd, src, buildFile, doDebug }) { - super({ cwd, src, buildFile, doDebug }); - } + /** + * Constructor + * @param {Object} options + * @param {String} options.cwd working directory for build + * @param {String} options.src source directory + * @param {String} options.buildFile full path for zip file to generate + * @param {Boolean} options.doDebug debug flag + */ + constructor({cwd, src, buildFile, doDebug}) { + super({cwd, src, buildFile, doDebug}); + } - /** - * Executes build - * @param {Function} callback - */ - execute(callback) { - this.createZip(callback); - } + /** + * Executes build + * @param {Function} callback + */ + execute(callback) { + this.createZip(callback); + } } module.exports = ZipOnlyBuildFlow; diff --git a/lib/builtins/deploy-delegates/cfn-deployer/assets/basic-lambda.yaml b/lib/builtins/deploy-delegates/cfn-deployer/assets/basic-lambda.yaml index 13804ee4..35f35bbf 100644 --- a/lib/builtins/deploy-delegates/cfn-deployer/assets/basic-lambda.yaml +++ b/lib/builtins/deploy-delegates/cfn-deployer/assets/basic-lambda.yaml @@ -14,27 +14,27 @@ Parameters: Type: String Resources: AlexaSkillIAMRole: - Type: AWS::IAM::Role - Properties: - AssumeRolePolicyDocument: - Version: 2012-10-17 - Statement: - - Effect: Allow - Principal: - Service: - - lambda.amazonaws.com - Action: - - sts:AssumeRole - Path: / - Policies: - - PolicyName: alexaSkillExecutionPolicy - PolicyDocument: - Version: 2012-10-17 - Statement: - - Effect: Allow - Action: - - logs:* - Resource: arn:aws:logs:*:*:* + Type: AWS::IAM::Role + Properties: + AssumeRolePolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Principal: + Service: + - lambda.amazonaws.com + Action: + - sts:AssumeRole + Path: / + Policies: + - PolicyName: alexaSkillExecutionPolicy + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: + - logs:* + Resource: arn:aws:logs:*:*:* AlexaSkillFunction: Type: AWS::Lambda::Function Properties: diff --git a/lib/builtins/deploy-delegates/cfn-deployer/helper.js b/lib/builtins/deploy-delegates/cfn-deployer/helper.js index bcce3291..e9f71aab 100644 --- a/lib/builtins/deploy-delegates/cfn-deployer/helper.js +++ b/lib/builtins/deploy-delegates/cfn-deployer/helper.js @@ -1,197 +1,199 @@ /* eslint-disable no-await-in-loop */ -const fs = require('fs'); -const sleep = require('util').promisify(setTimeout); +const fs = require("fs"); +const sleep = require("util").promisify(setTimeout); -const CliCFNDeployerError = require('@src/exceptions/cli-cfn-deployer-error'); -const CloudformationClient = require('@src/clients/aws-client/cloudformation-client'); -const S3Client = require('@src/clients/aws-client/s3-client'); -const SmapiClient = require('@src/clients/smapi-client'); +const CliCFNDeployerError = require("../../../exceptions/cli-cfn-deployer-error"); +const CloudformationClient = require("../../../clients/aws-client/cloudformation-client"); +const S3Client = require("../../../clients/aws-client/s3-client"); +const SmapiClient = require("../../../clients/smapi-client").default; module.exports = class Helper { - constructor(profile, doDebug, awsProfile, awsRegion, reporter) { - this.awsProfile = awsProfile; - this.awsRegion = awsRegion; - this.reporter = reporter; - this.sleep = sleep; - this.s3Client = (new S3Client({ awsProfile, awsRegion })).client; - this.cloudformationClient = (new CloudformationClient({ awsProfile, awsRegion })).client; - this.smapiClient = new SmapiClient({ profile, doDebug }); - } + constructor(profile, doDebug, awsProfile, awsRegion, reporter) { + this.awsProfile = awsProfile; + this.awsRegion = awsRegion; + this.reporter = reporter; + this.sleep = sleep; + this.s3Client = new S3Client({awsProfile, awsRegion}).client; + this.cloudformationClient = new CloudformationClient({awsProfile, awsRegion}).client; + this.smapiClient = new SmapiClient({profile, doDebug}); + } - async _s3BucketExists(bucketName) { - try { - await this.s3Client.headBucket({ Bucket: bucketName }).promise(); - return true; - } catch (err) { - return false; - } + async _s3BucketExists(bucketName) { + try { + await this.s3Client.headBucket({Bucket: bucketName}).promise(); + return true; + } catch (err) { + return false; } + } - async _createS3Bucket(bucketName) { - const params = { - Bucket: bucketName - }; - if (this.awsRegion !== 'us-east-1') { - params.CreateBucketConfiguration = { - LocationConstraint: this.awsRegion - }; - } - await this.s3Client.createBucket(params).promise(); - return this.s3Client.waitFor('bucketExists', { Bucket: bucketName }).promise(); + async _createS3Bucket(bucketName) { + const params = { + Bucket: bucketName, + }; + if (this.awsRegion !== "us-east-1") { + params.CreateBucketConfiguration = { + LocationConstraint: this.awsRegion, + }; } + await this.s3Client.createBucket(params).promise(); + return this.s3Client.waitFor("bucketExists", {Bucket: bucketName}).promise(); + } - /** - * Creates new S3 bucket if it does not exist - * @param {string} bucketName Bucket Name - * @returns {Promise{<{}> | void}} - */ - async createS3BucketIfNotExists(bucketName) { - const exists = await this._s3BucketExists(bucketName); - if (!exists) { - return this._createS3Bucket(bucketName); - } + /** + * Creates new S3 bucket if it does not exist + * @param {string} bucketName Bucket Name + * @returns {Promise{<{}> | void}} + */ + async createS3BucketIfNotExists(bucketName) { + const exists = await this._s3BucketExists(bucketName); + if (!exists) { + return this._createS3Bucket(bucketName); } + } - /** - * Enables S3 bucket versioning if it is not enabled - * @param {string} bucketName Bucket Name - * @returns {Promise{<{}> | void}} - */ - async enableS3BucketVersioningIfNotEnabled(bucketName) { - const response = await this.s3Client.getBucketVersioning({ Bucket: bucketName }).promise(); - if (typeof response === 'object' && Object.keys(response).length === 0) { - const params = { - Bucket: bucketName, - VersioningConfiguration: { - MFADelete: 'Disabled', - Status: 'Enabled' - } - }; - return this.s3Client.putBucketVersioning(params).promise(); - } + /** + * Enables S3 bucket versioning if it is not enabled + * @param {string} bucketName Bucket Name + * @returns {Promise{<{}> | void}} + */ + async enableS3BucketVersioningIfNotEnabled(bucketName) { + const response = await this.s3Client.getBucketVersioning({Bucket: bucketName}).promise(); + if (typeof response === "object" && Object.keys(response).length === 0) { + const params = { + Bucket: bucketName, + VersioningConfiguration: { + MFADelete: "Disabled", + Status: "Enabled", + }, + }; + return this.s3Client.putBucketVersioning(params).promise(); } + } - /** Uploads object to S3 - * @param {string} bucketName Bucket name - * @param {string} bucketKey Bucket key - * @param {} filePath File path for file to upload - * @returns {Promise{<{ETag: string, VersionId: string}>}} - */ - async uploadToS3(bucketName, bucketKey, filePath) { - const params = { - Bucket: bucketName, - Key: bucketKey, - Body: fs.readFileSync(filePath) - }; - // TODO: add caching when is code modified is fixed in the code builder - this.reporter.updateStatus(`Uploading code artifact to s3://${bucketName}/${bucketKey}`); - return this.s3Client.putObject(params).promise(); - } + /** Uploads object to S3 + * @param {string} bucketName Bucket name + * @param {string} bucketKey Bucket key + * @param {} filePath File path for file to upload + * @returns {Promise{<{ETag: string, VersionId: string}>}} + */ + async uploadToS3(bucketName, bucketKey, filePath) { + const params = { + Bucket: bucketName, + Key: bucketKey, + Body: fs.readFileSync(filePath), + }; + // TODO: add caching when is code modified is fixed in the code builder + this.reporter.updateStatus(`Uploading code artifact to s3://${bucketName}/${bucketKey}`); + return this.s3Client.putObject(params).promise(); + } + + _stackExists(stackId) { + if (!stackId) return false; + return this.cloudformationClient + .describeStacks({StackName: stackId}) + .promise() + .then((data) => !data.Stacks[0].StackStatus.startsWith("DELETE_")) + .catch(() => false); + } - _stackExists(stackId) { - if (!stackId) return false; - return this.cloudformationClient.describeStacks({ StackName: stackId }).promise() - .then(data => !data.Stacks[0].StackStatus.startsWith('DELETE_')) - .catch(() => false); + /** + * Triggers stack deploy - update or create + * @param {string | undefined} stackId stack id + * @param {string | undefined} stackName stack name + * @param {Buffer} templateBody cloud formation template body + * @param {Array<{ParameterKey: string, ParameterValue: string}>} parameters cloud formation parameters + * @param {Array} capabilities cloud formation capabilities + * @returns {Promise{<{StackId: string}>}} + */ + async deployStack(stackId, stackName, templateBody, parameters, capabilities) { + const stackExists = await this._stackExists(stackId); + if (stackExists) { + this.reporter.updateStatus(`Updating stack (${stackId})...`); + } else { + this.reporter.updateStatus(`No stack exists or stack has been deleted. Creating cloudformation stack "${stackName}"...`); } + const params = { + StackName: stackExists ? stackId : stackName, + TemplateBody: templateBody, + Parameters: parameters, + Capabilities: capabilities, + }; - /** - * Triggers stack deploy - update or create - * @param {string | undefined} stackId stack id - * @param {string | undefined} stackName stack name - * @param {Buffer} templateBody cloud formation template body - * @param {Array<{ParameterKey: string, ParameterValue: string}>} parameters cloud formation parameters - * @param {Array} capabilities cloud formation capabilities - * @returns {Promise{<{StackId: string}>}} - */ - async deployStack(stackId, stackName, templateBody, parameters, capabilities) { - const stackExists = await this._stackExists(stackId); - if (stackExists) { - this.reporter.updateStatus(`Updating stack (${stackId})...`); - } else { - this.reporter.updateStatus(`No stack exists or stack has been deleted. Creating cloudformation stack "${stackName}"...`); - } - const params = { - StackName: stackExists ? stackId : stackName, - TemplateBody: templateBody, - Parameters: parameters, - Capabilities: capabilities, - }; + if (stackExists) { + return this.cloudformationClient.updateStack(params).promise(); + } + return this.cloudformationClient.createStack(params).promise(); + } - if (stackExists) { - return this.cloudformationClient.updateStack(params).promise(); - } - return this.cloudformationClient.createStack(params).promise(); + /** + * Waits for stack to be created or updated + * @param {string} stackId stack id + * @returns {Promise{<{ + * stackInfo: { + * StackId: string, + * StackName: string, + * Parameters: Array<{ParameterKey: string, ParameterValue: string}>}}>, + * CreationTime: timestamp, + * RollbackConfiguration: {}, + * StackStatus: string, + * DisableRollback: boolean, + * NotificationARNs: Array, + * Capabilities: Array, + * Outputs: Array<{OutputKey: string, OutputValue: string, Description: string}>, + * Tags: Array, + * EnableTerminationProtection: boolean, + * DriftInformation: {} + * } + * endpointUri: string + * } + */ + async waitForStackDeploy(stackId) { + let pooling = true; + let stackInfo; + while (pooling) { + const response = await this.cloudformationClient.describeStacks({StackName: stackId}).promise(); + [stackInfo] = response.Stacks; + const stackStatus = stackInfo.StackStatus; + const statusReason = stackInfo.StackStatusReason; + const reasonMsg = statusReason ? `Status reason: ${statusReason}.` : ""; + this.reporter.updateStatus(`Current stack status: ${stackStatus}... ${reasonMsg}`); + await this.sleep(2000); + pooling = !stackStatus.endsWith("_COMPLETE"); } - /** - * Waits for stack to be created or updated - * @param {string} stackId stack id - * @returns {Promise{<{ - * stackInfo: { - * StackId: string, - * StackName: string, - * Parameters: Array<{ParameterKey: string, ParameterValue: string}>}}>, - * CreationTime: timestamp, - * RollbackConfiguration: {}, - * StackStatus: string, - * DisableRollback: boolean, - * NotificationARNs: Array, - * Capabilities: Array, - * Outputs: Array<{OutputKey: string, OutputValue: string, Description: string}>, - * Tags: Array, - * EnableTerminationProtection: boolean, - * DriftInformation: {} - * } - * endpointUri: string - * } - */ - async waitForStackDeploy(stackId) { - let pooling = true; - let stackInfo; - while (pooling) { - const response = await this.cloudformationClient.describeStacks({ StackName: stackId }).promise(); - [stackInfo] = response.Stacks; - const stackStatus = stackInfo.StackStatus; - const statusReason = stackInfo.StackStatusReason; - const reasonMsg = statusReason ? `Status reason: ${statusReason}.` : ''; - this.reporter.updateStatus(`Current stack status: ${stackStatus}... ${reasonMsg}`); - await this.sleep(2000); - pooling = !stackStatus.endsWith('_COMPLETE'); - } + if (["CREATE_COMPLETE", "UPDATE_COMPLETE"].includes(stackInfo.StackStatus)) { + const skillEndpointOutput = stackInfo.Outputs.find((o) => o.OutputKey === "SkillEndpoint"); + const endpointUri = skillEndpointOutput.OutputValue; + return {stackInfo, endpointUri}; + } + // default fallback error message + let message = + "Cloud Formation deploy failed. We could not find details for deploy error. " + "Please check AWS Console for more details."; + // finding the last error + const events = await this.cloudformationClient.describeStackEvents({StackName: stackId}).promise(); + const error = events.StackEvents.find((e) => e.ResourceStatus.endsWith("_FAILED")); + if (error) { + const {LogicalResourceId, ResourceType, ResourceStatus, ResourceStatusReason} = error; + message = `${LogicalResourceId}[${ResourceType}] ${ResourceStatus} (${ResourceStatusReason})`; + } + throw new CliCFNDeployerError(message); + } - if (['CREATE_COMPLETE', 'UPDATE_COMPLETE'].includes(stackInfo.StackStatus)) { - const skillEndpointOutput = stackInfo.Outputs.find(o => o.OutputKey === 'SkillEndpoint'); - const endpointUri = skillEndpointOutput.OutputValue; - return { stackInfo, endpointUri }; - } - // default fallback error message - let message = 'Cloud Formation deploy failed. We could not find details for deploy error. ' - + 'Please check AWS Console for more details.'; - // finding the last error - const events = await this.cloudformationClient.describeStackEvents({ StackName: stackId }).promise(); - const error = events.StackEvents.find(e => e.ResourceStatus.endsWith('_FAILED')); + /** + * Gets skill credentials + * @param {string} skillId skill id + * @return {Promise{<{clientId: string, clientSecret: string}>}} + */ + async getSkillCredentials(skillId) { + return new Promise((resolve, reject) => { + this.smapiClient.skill.getSkillCredentials(skillId, (error, response) => { if (error) { - const { LogicalResourceId, ResourceType, ResourceStatus, ResourceStatusReason } = error; - message = `${LogicalResourceId}[${ResourceType}] ${ResourceStatus} (${ResourceStatusReason})`; + reject(error); + } else { + resolve(response.body.skillMessagingCredentials); } - throw new CliCFNDeployerError(message); - } - - /** - * Gets skill credentials - * @param {string} skillId skill id - * @return {Promise{<{clientId: string, clientSecret: string}>}} - */ - async getSkillCredentials(skillId) { - return new Promise((resolve, reject) => { - this.smapiClient.skill.getSkillCredentials(skillId, (error, response) => { - if (error) { - reject(error); - } else { - resolve(response.body.skillMessagingCredentials); - } - }); - }); - } + }); + }); + } }; diff --git a/lib/builtins/deploy-delegates/cfn-deployer/index.js b/lib/builtins/deploy-delegates/cfn-deployer/index.js index acb52cba..06c37ed4 100644 --- a/lib/builtins/deploy-delegates/cfn-deployer/index.js +++ b/lib/builtins/deploy-delegates/cfn-deployer/index.js @@ -1,18 +1,18 @@ -const path = require('path'); -const fs = require('fs'); -const R = require('ramda'); +const path = require("path"); +const fs = require("fs"); +const R = require("ramda"); -const awsUtil = require('@src/clients/aws-client/aws-util'); -const stringUtils = require('@src/utils/string-utils'); -const CliCFNDeployerError = require('@src/exceptions/cli-cfn-deployer-error'); -const Helper = require('./helper'); +const awsUtil = require("../../../clients/aws-client/aws-util"); +const stringUtils = require("../../../utils/string-utils"); +const CliCFNDeployerError = require("../../../exceptions/cli-cfn-deployer-error"); +const Helper = require("./helper"); -const SKILL_STACK_PUBLIC_FILE_NAME = 'skill-stack.yaml'; -const SKILL_STACK_ASSET_FILE_NAME = 'basic-lambda.yaml'; +const SKILL_STACK_PUBLIC_FILE_NAME = "skill-stack.yaml"; +const SKILL_STACK_ASSET_FILE_NAME = "basic-lambda.yaml"; module.exports = { - bootstrap, - invoke + bootstrap, + invoke, }; /** @@ -21,20 +21,21 @@ module.exports = { * @param {Function} callback */ function bootstrap(options, callback) { - const { profile, userConfig, workspacePath } = options; - const templateLocation = path.join(workspacePath, SKILL_STACK_PUBLIC_FILE_NAME); - let updatedUserConfig; - try { - const templateContent = fs.readFileSync(path.join(__dirname, 'assets', SKILL_STACK_ASSET_FILE_NAME), 'utf-8'); - const awsProfile = awsUtil.getAWSProfile(profile); - const awsDefaultRegion = awsUtil.getCLICompatibleDefaultRegion(awsProfile); - fs.writeFileSync(templateLocation, templateContent); - userConfig.templatePath = `./${path.posix.join('infrastructure', path.basename(workspacePath), SKILL_STACK_PUBLIC_FILE_NAME)}`; - updatedUserConfig = R.set(R.lensPath(['awsRegion']), awsDefaultRegion, userConfig); - } catch (e) { - return callback(e.message); - } - callback(null, { userConfig: updatedUserConfig }); + const {profile, workspacePath} = options; + const userConfig = options.userConfig || {}; + const templateLocation = path.join(workspacePath, SKILL_STACK_PUBLIC_FILE_NAME); + let updatedUserConfig; + try { + const templateContent = fs.readFileSync(path.join(__dirname, "assets", SKILL_STACK_ASSET_FILE_NAME), "utf-8"); + const awsProfile = awsUtil.getAWSProfile(profile); + const awsDefaultRegion = awsUtil.getCLICompatibleDefaultRegion(awsProfile); + fs.writeFileSync(templateLocation, templateContent); + userConfig.templatePath = `./${path.posix.join("infrastructure", path.basename(workspacePath), SKILL_STACK_PUBLIC_FILE_NAME)}`; + updatedUserConfig = R.set(R.lensPath(["awsRegion"]), awsDefaultRegion, userConfig); + } catch (e) { + return callback(e.message); + } + callback(null, {userConfig: updatedUserConfig}); } /** @@ -51,245 +52,246 @@ function bootstrap(options, callback) { * .responseObject.resultMessage the message to summarize current situation */ async function invoke(reporter, options, callback) { - const { alexaRegion, deployState = {} } = options; - const deployProgress = { - isAllStepSuccess: false, - isCodeDeployed: false, - deployState: deployState[alexaRegion] || {} - }; - - try { - await _deploy(reporter, options, deployProgress); - deployProgress.resultMessage = deployProgress.isDeploySkipped - ? _makeSkippedMessage(deployProgress.deployRegion, alexaRegion) - : _makeSuccessMessage(deployProgress.endpoint.uri, alexaRegion); - callback(null, deployProgress); - } catch (err) { - deployProgress.resultMessage = _makeErrorMessage(err, alexaRegion); - callback(null, deployProgress); - } + const {alexaRegion, deployState = {}} = options; + const deployProgress = { + isAllStepSuccess: false, + isCodeDeployed: false, + deployState: deployState[alexaRegion] || {}, + }; + + try { + await _deploy(reporter, options, deployProgress); + deployProgress.resultMessage = deployProgress.isDeploySkipped + ? _makeSkippedMessage(deployProgress.deployRegion, alexaRegion) + : _makeSuccessMessage(deployProgress.endpoint.uri, alexaRegion); + callback(null, deployProgress); + } catch (err) { + deployProgress.resultMessage = _makeErrorMessage(err, alexaRegion); + callback(null, deployProgress); + } } async function _deploy(reporter, options, deployProgress) { - const { profile, doDebug, alexaRegion, skillId, skillName, code, userConfig, deployState = {}, deployRegions } = options; - - let { stackId } = deployProgress.deployState; - const awsProfile = _getAwsProfile(profile); - const awsRegion = _getAwsRegion(alexaRegion, deployRegions); - const templateBody = _getTemplateBody(alexaRegion, userConfig); - const userDefinedParameters = _getUserDefinedParameters(alexaRegion, userConfig); - const bucketName = _getS3BucketName(alexaRegion, userConfig, deployProgress.deployState, awsProfile, awsRegion); - const bucketKey = _getS3BucketKey(alexaRegion, userConfig, code.codeBuild); - const stackName = _getStackName(skillName, alexaRegion); - const deployRegion = R.keys(deployRegions).find((region) => deployRegions[region] === awsRegion); - - if (deployRegion !== alexaRegion && R.equals(deployState[deployRegion], deployState[alexaRegion])) { - deployProgress.isDeploySkipped = true; - deployProgress.deployRegion = deployRegion; - return; - } - - const helper = new Helper(profile, doDebug, awsProfile, awsRegion, reporter); - - // skill credentials - const skillCredentials = templateBody.includes('SkillClientId') && templateBody.includes('SkillClientSecret') - ? await helper.getSkillCredentials(skillId) - : {}; - - // s3 upload - await helper.createS3BucketIfNotExists(bucketName); - await helper.enableS3BucketVersioningIfNotEnabled(bucketName); - const uploadResult = await helper.uploadToS3(bucketName, bucketKey, code.codeBuild); - - deployProgress.deployState.s3 = { - bucket: bucketName, - key: bucketKey - }; - - deployProgress.isCodeDeployed = true; - - // cf deploy - const codeVersion = uploadResult.VersionId; - const s3Artifact = { bucketName, bucketKey, codeVersion }; - const stackParameters = _mapStackParameters(skillId, skillCredentials, userConfig, s3Artifact, userDefinedParameters); - const capabilities = _getCapabilities(alexaRegion, userConfig); - - const deployRequest = await helper.deployStack(stackId, stackName, templateBody, stackParameters, capabilities); - stackId = deployRequest.StackId; - const deployResult = await helper.waitForStackDeploy(stackId, reporter); - - deployProgress.deployState.stackId = stackId; - deployProgress.deployState.outputs = deployResult.stackInfo.Outputs; - deployProgress.endpoint = { uri: deployResult.endpointUri }; - deployProgress.isAllStepSuccess = true; - return deployResult; + const {profile, doDebug, alexaRegion, skillId, skillName, code, userConfig, deployState = {}, deployRegions} = options; + + let {stackId} = deployProgress.deployState; + const awsProfile = _getAwsProfile(profile); + const awsRegion = _getAwsRegion(alexaRegion, deployRegions); + const templateBody = _getTemplateBody(alexaRegion, userConfig); + const userDefinedParameters = _getUserDefinedParameters(alexaRegion, userConfig); + const bucketName = _getS3BucketName(alexaRegion, userConfig, deployProgress.deployState, awsProfile, awsRegion); + const bucketKey = _getS3BucketKey(alexaRegion, userConfig, code.codeBuild); + const stackName = _getStackName(skillName, alexaRegion); + const deployRegion = R.keys(deployRegions).find((region) => deployRegions[region] === awsRegion); + + if (deployRegion !== alexaRegion && R.equals(deployState[deployRegion], deployState[alexaRegion])) { + deployProgress.isDeploySkipped = true; + deployProgress.deployRegion = deployRegion; + return; + } + + const helper = new Helper(profile, doDebug, awsProfile, awsRegion, reporter); + + // skill credentials + const skillCredentials = + templateBody.includes("SkillClientId") && templateBody.includes("SkillClientSecret") ? await helper.getSkillCredentials(skillId) : {}; + + // s3 upload + await helper.createS3BucketIfNotExists(bucketName); + await helper.enableS3BucketVersioningIfNotEnabled(bucketName); + const uploadResult = await helper.uploadToS3(bucketName, bucketKey, code.codeBuild); + + deployProgress.deployState.s3 = { + bucket: bucketName, + key: bucketKey, + }; + + deployProgress.isCodeDeployed = true; + + // cf deploy + const codeVersion = uploadResult.VersionId; + const s3Artifact = {bucketName, bucketKey, codeVersion}; + const stackParameters = _mapStackParameters(skillId, skillCredentials, userConfig, s3Artifact, userDefinedParameters); + const capabilities = _getCapabilities(alexaRegion, userConfig); + + const deployRequest = await helper.deployStack(stackId, stackName, templateBody, stackParameters, capabilities); + stackId = deployRequest.StackId; + const deployResult = await helper.waitForStackDeploy(stackId, reporter); + + deployProgress.deployState.stackId = stackId; + deployProgress.deployState.outputs = deployResult.stackInfo.Outputs; + deployProgress.endpoint = {uri: deployResult.endpointUri}; + deployProgress.isAllStepSuccess = true; + return deployResult; } function _getAwsProfile(profile) { - const awsProfile = awsUtil.getAWSProfile(profile); - if (!awsProfile) { - throw new CliCFNDeployerError(`Profile [${profile}] doesn't have AWS profile linked to it. ` - + 'Please run "ask configure" to re-configure your profile.'); - } - return awsProfile; + const awsProfile = awsUtil.getAWSProfile(profile); + if (!awsProfile) { + throw new CliCFNDeployerError( + `Profile [${profile}] doesn't have AWS profile linked to it. ` + 'Please run "ask configure" to re-configure your profile.', + ); + } + return awsProfile; } function _getAwsRegion(alexaRegion, deployRegions) { - const awsRegion = deployRegions[alexaRegion]; - if (!awsRegion) { - throw new CliCFNDeployerError(`Unsupported Alexa region: ${alexaRegion}. ` - + 'Please check your region name or use "regionalOverrides" to specify AWS region.'); - } - return awsRegion; + const awsRegion = deployRegions[alexaRegion]; + if (!awsRegion) { + throw new CliCFNDeployerError( + `Unsupported Alexa region: ${alexaRegion}. ` + 'Please check your region name or use "regionalOverrides" to specify AWS region.', + ); + } + return awsRegion; } function _getS3BucketName(alexaRegion, userConfig, currentRegionDeployState, awsProfile, awsRegion) { - const customValue = R.path(['regionalOverrides', alexaRegion, 'artifactsS3', 'bucketName'], userConfig) - || R.path(['artifactsS3', 'bucketName'], userConfig); - - if (customValue) return customValue; - - // Generates a valid S3 bucket name. - // a bucket name should follow the pattern: ask-projectName-profileName-awsRegion-timeStamp - // a valid bucket name cannot longer than 63 characters, so cli fixes the project name no longer than 22 characters - const generateBucketName = () => { - const projectName = path.basename(process.cwd()); - const validProjectName = stringUtils.filterNonAlphanumeric(projectName.toLowerCase()).substring(0, 22); - const validProfile = stringUtils.filterNonAlphanumeric(awsProfile.toLowerCase()).substring(0, 9); - const shortRegionName = awsRegion.replace(/-/g, ''); - return `ask-${validProjectName}-${validProfile}-${shortRegionName}-${Date.now()}`; - }; - - return R.path(['s3', 'bucket'], currentRegionDeployState) || generateBucketName(); + const customValue = + R.path(["regionalOverrides", alexaRegion, "artifactsS3", "bucketName"], userConfig) || + R.path(["artifactsS3", "bucketName"], userConfig); + + if (customValue) return customValue; + + // Generates a valid S3 bucket name. + // a bucket name should follow the pattern: ask-projectName-profileName-awsRegion-timeStamp + // a valid bucket name cannot longer than 63 characters, so cli fixes the project name no longer than 22 characters + const generateBucketName = () => { + const projectName = path.basename(process.cwd()); + const validProjectName = stringUtils.filterNonAlphanumeric(projectName.toLowerCase()).substring(0, 22); + const validProfile = stringUtils.filterNonAlphanumeric(awsProfile.toLowerCase()).substring(0, 9); + const shortRegionName = awsRegion.replace(/-/g, ""); + return `ask-${validProjectName}-${validProfile}-${shortRegionName}-${Date.now()}`; + }; + + return R.path(["s3", "bucket"], currentRegionDeployState) || generateBucketName(); } function _getS3BucketKey(alexaRegion, userConfig, codeBuild) { - const customValue = R.path(['regionalOverrides', alexaRegion, 'artifactsS3', 'bucketKey'], userConfig) - || R.path(['artifactsS3', 'bucketKey'], userConfig); + const customValue = + R.path(["regionalOverrides", alexaRegion, "artifactsS3", "bucketKey"], userConfig) || R.path(["artifactsS3", "bucketKey"], userConfig); - if (customValue) return customValue; + if (customValue) return customValue; - return `endpoint/${path.basename(codeBuild)}`; + return `endpoint/${path.basename(codeBuild)}`; } function _getStackName(skillName, alexaRegion) { - // Generates a valid CloudFormation stack name. - // a stack name should follow the pattern: ask-skillName-alexaRegion-skillStack-timeStamp - // a valid stack name cannot longer than 128 characters, so cli fixes the skill name no longer than 64 characters - const generateStackName = () => { - const validSkillName = stringUtils.filterNonAlphanumeric(skillName).substring(0, 64); - const shortRegionName = alexaRegion.replace(/-/g, ''); - return `ask-${validSkillName}-${shortRegionName}-skillStack-${Date.now()}`; - }; - - return generateStackName(); + // Generates a valid CloudFormation stack name. + // a stack name should follow the pattern: ask-skillName-alexaRegion-skillStack-timeStamp + // a valid stack name cannot longer than 128 characters, so cli fixes the skill name no longer than 64 characters + const generateStackName = () => { + const validSkillName = stringUtils.filterNonAlphanumeric(skillName).substring(0, 64); + const shortRegionName = alexaRegion.replace(/-/g, ""); + return `ask-${validSkillName}-${shortRegionName}-skillStack-${Date.now()}`; + }; + + return generateStackName(); } function _getCapabilities(alexaRegion, userConfig) { - let capabilities = R.path(['regionalOverrides', alexaRegion, 'cfn', 'capabilities'], userConfig) - || R.path(['cfn', 'capabilities'], userConfig); - capabilities = new Set(capabilities || []); - capabilities.add('CAPABILITY_IAM'); + let capabilities = + R.path(["regionalOverrides", alexaRegion, "cfn", "capabilities"], userConfig) || R.path(["cfn", "capabilities"], userConfig); + capabilities = new Set(capabilities || []); + capabilities.add("CAPABILITY_IAM"); - return Array.from(capabilities); + return Array.from(capabilities); } function _getUserDefinedParameters(alexaRegion, userConfig) { - const reservedParameters = { - SkillId: 'Please use a different name.', - SkillClientId: 'Please use a different name.', - SkillClientSecret: 'Please use a different name.', - LambdaRuntime: 'Please specify under skillInfrastructure.userConfig.runtime.', - LambdaHandler: 'Please specify under skillInfrastructure.userConfig.handler.', - CodeBucket: 'Please specify under skillInfrastructure.userConfig.artifactsS3.bucketName.', - CodeKey: 'Please specify under skillInfrastructure.userConfig.artifactsS3.bucketKey.', - CodeVersion: 'Please use a different name.' - }; - - const reservedParametersKeys = new Set(Object.keys(reservedParameters)); - - let parameters = R.path(['regionalOverrides', alexaRegion, 'cfn', 'parameters'], userConfig) - || R.path(['cfn', 'parameters'], userConfig); - - parameters = parameters || []; - - Object.keys(parameters).forEach(key => { - if (reservedParametersKeys.has(key)) { - const message = reservedParameters[key]; - throw new CliCFNDeployerError(`Cloud Formation parameter "${key}" is reserved. ${message}`); - } - }); + const reservedParameters = { + SkillId: "Please use a different name.", + SkillClientId: "Please use a different name.", + SkillClientSecret: "Please use a different name.", + LambdaRuntime: "Please specify under skillInfrastructure.userConfig.runtime.", + LambdaHandler: "Please specify under skillInfrastructure.userConfig.handler.", + CodeBucket: "Please specify under skillInfrastructure.userConfig.artifactsS3.bucketName.", + CodeKey: "Please specify under skillInfrastructure.userConfig.artifactsS3.bucketKey.", + CodeVersion: "Please use a different name.", + }; + + const reservedParametersKeys = new Set(Object.keys(reservedParameters)); + + let parameters = R.path(["regionalOverrides", alexaRegion, "cfn", "parameters"], userConfig) || R.path(["cfn", "parameters"], userConfig); + + parameters = parameters || []; + + Object.keys(parameters).forEach((key) => { + if (reservedParametersKeys.has(key)) { + const message = reservedParameters[key]; + throw new CliCFNDeployerError(`Cloud Formation parameter "${key}" is reserved. ${message}`); + } + }); - return parameters; + return parameters; } function _getTemplateBody(alexaRegion, userConfig) { - const templatePath = R.path(['regionalOverrides', alexaRegion, 'templatePath'], userConfig) || userConfig.templatePath; - if (!templatePath) { - throw new CliCFNDeployerError('The template path in userConfig must be provided.'); - } - return fs.readFileSync(templatePath, 'utf-8'); + const templatePath = R.path(["regionalOverrides", alexaRegion, "templatePath"], userConfig) || userConfig.templatePath; + if (!templatePath) { + throw new CliCFNDeployerError("The template path in userConfig must be provided."); + } + return fs.readFileSync(templatePath, "utf-8"); } function _makeSkippedMessage(deployRegion, alexaRegion) { - return `The CloudFormation deploy for Alexa region "${alexaRegion}" is same as "${deployRegion}".`; + return `The CloudFormation deploy for Alexa region "${alexaRegion}" is same as "${deployRegion}".`; } function _makeSuccessMessage(endpointUri, alexaRegion) { - return `The CloudFormation deploy succeeded for Alexa region "${alexaRegion}" with output Lambda ARN: ${endpointUri}.`; + return `The CloudFormation deploy succeeded for Alexa region "${alexaRegion}" with output Lambda ARN: ${endpointUri}.`; } function _makeErrorMessage(error, alexaRegion) { - return `The CloudFormation deploy failed for Alexa region "${alexaRegion}": ${error.message}`; + return `The CloudFormation deploy failed for Alexa region "${alexaRegion}": ${error.message}`; } function _mapStackParameters(skillId, skillCredentials, userConfig, s3Artifact, userDefinedParameters) { - const parameters = [ - { - ParameterKey: 'SkillId', - ParameterValue: skillId - }, - { - ParameterKey: 'LambdaRuntime', - ParameterValue: userConfig.runtime - }, - { - ParameterKey: 'LambdaHandler', - ParameterValue: userConfig.handler - }, - { - ParameterKey: 'CodeBucket', - ParameterValue: s3Artifact.bucketName - }, - { - ParameterKey: 'CodeKey', - ParameterValue: s3Artifact.bucketKey - }, - { - ParameterKey: 'CodeVersion', - ParameterValue: s3Artifact.codeVersion - } - ]; - - if (skillCredentials.clientId && skillCredentials.clientSecret) { - const clientIdParameter = { - ParameterKey: 'SkillClientId', - ParameterValue: skillCredentials.clientId - }; - const clientSecretParameter = { - ParameterKey: 'SkillClientSecret', - ParameterValue: skillCredentials.clientSecret - }; - parameters.push(clientIdParameter, clientSecretParameter); - } + const parameters = [ + { + ParameterKey: "SkillId", + ParameterValue: skillId, + }, + { + ParameterKey: "LambdaRuntime", + ParameterValue: userConfig.runtime, + }, + { + ParameterKey: "LambdaHandler", + ParameterValue: userConfig.handler, + }, + { + ParameterKey: "CodeBucket", + ParameterValue: s3Artifact.bucketName, + }, + { + ParameterKey: "CodeKey", + ParameterValue: s3Artifact.bucketKey, + }, + { + ParameterKey: "CodeVersion", + ParameterValue: s3Artifact.codeVersion, + }, + ]; + + if (skillCredentials.clientId && skillCredentials.clientSecret) { + const clientIdParameter = { + ParameterKey: "SkillClientId", + ParameterValue: skillCredentials.clientId, + }; + const clientSecretParameter = { + ParameterKey: "SkillClientSecret", + ParameterValue: skillCredentials.clientSecret, + }; + parameters.push(clientIdParameter, clientSecretParameter); + } - Object.keys(userDefinedParameters).forEach(key => { - const parameter = { - ParameterKey: key, - ParameterValue: userDefinedParameters[key] - }; - parameters.push(parameter); - }); + Object.keys(userDefinedParameters).forEach((key) => { + const parameter = { + ParameterKey: key, + ParameterValue: userDefinedParameters[key], + }; + parameters.push(parameter); + }); - return parameters; + return parameters; } diff --git a/lib/builtins/deploy-delegates/lambda-deployer/helper.js b/lib/builtins/deploy-delegates/lambda-deployer/helper.js index 1ffcedeb..d4aa084d 100644 --- a/lib/builtins/deploy-delegates/lambda-deployer/helper.js +++ b/lib/builtins/deploy-delegates/lambda-deployer/helper.js @@ -1,131 +1,133 @@ -const async = require('async'); -const fs = require('fs'); -const R = require('ramda'); +const async = require("async"); +const fs = require("fs"); +const R = require("ramda"); -const CONSTANTS = require('@src/utils/constants'); -const IAMClient = require('@src/clients/aws-client/iam-client'); -const LambdaClient = require('@src/clients/aws-client/lambda-client'); -const Manifest = require('@src/model/manifest'); -const ResourcesConfig = require('@src/model/resources-config'); -const retryUtils = require('@src/utils/retry-utility'); -const stringUtils = require('@src/utils/string-utils'); +const CONSTANTS = require("../../../utils/constants"); +const IAMClient = require("../../../clients/aws-client/iam-client"); +const LambdaClient = require("../../../clients/aws-client/lambda-client"); +const Manifest = require("../../../model/manifest"); +const ResourcesConfig = require("../../../model/resources-config"); +const retryUtils = require("../../../utils/retry-utility"); +const stringUtils = require("../../../utils/string-utils"); module.exports = { - loadLambdaInformation, - deployIAMRole, - deployLambdaFunction + loadLambdaInformation, + deployIAMRole, + deployLambdaFunction, }; // TODO: use Error class function loadLambdaInformation(reporter, loadLambdaConfig, callback) { - const { awsProfile, awsRegion, alexaRegion, deployState, userConfig, ignoreHash } = loadLambdaConfig; - const lambdaClient = new LambdaClient({ awsProfile, awsRegion }); - // check if user sets userConfig with "sourceLambda" field to reuse existing Lambda - const sourceLambdaArn = alexaRegion === 'default' ? R.path(['sourceLambda', 'arn'], userConfig) - : R.path(['regionalOverrides', alexaRegion, 'sourceLambda', 'arn'], userConfig); - if (stringUtils.isNonBlankString(sourceLambdaArn)) { - return _loadLambdaFromUserConfigSource(reporter, lambdaClient, sourceLambdaArn, (loadErr, sourceLambdaData) => { - callback(loadErr, loadErr ? undefined : sourceLambdaData); - }); - } + const {awsProfile, awsRegion, alexaRegion, deployState, userConfig, ignoreHash} = loadLambdaConfig; + const lambdaClient = new LambdaClient({awsProfile, awsRegion}); + // check if user sets userConfig with "sourceLambda" field to reuse existing Lambda + const sourceLambdaArn = + alexaRegion === "default" + ? R.path(["sourceLambda", "arn"], userConfig) + : R.path(["regionalOverrides", alexaRegion, "sourceLambda", "arn"], userConfig); + if (stringUtils.isNonBlankString(sourceLambdaArn)) { + return _loadLambdaFromUserConfigSource(reporter, lambdaClient, sourceLambdaArn, (loadErr, sourceLambdaData) => { + callback(loadErr, loadErr ? undefined : sourceLambdaData); + }); + } - // Lambda does not exist in deployState - const lambdaArn = R.path(['lambda', 'arn'], deployState); - if (R.isNil(lambdaArn)) { - return callback(null, {}); - } + // Lambda does not exist in deployState + const lambdaArn = R.path(["lambda", "arn"], deployState); + if (R.isNil(lambdaArn)) { + return callback(null, {}); + } - // Lambda exists, validate the deploy states - reporter.updateStatus('Validating the deploy state of existing Lambda function...'); - lambdaClient.getFunction(lambdaArn, (err, data) => { - if (err) { - return callback(err); - } - // 1. check IAM role arn - const localIAMRole = deployState.iamRole; - const remoteIAMRole = data.Configuration.Role; - if (stringUtils.isNonBlankString(localIAMRole) && !R.equals(localIAMRole, remoteIAMRole)) { - return callback(`The IAM role for Lambda ARN (${lambdaArn}) should be "${remoteIAMRole}", but found "${localIAMRole}". \ + // Lambda exists, validate the deploy states + reporter.updateStatus("Validating the deploy state of existing Lambda function..."); + lambdaClient.getFunction(lambdaArn, (err, data) => { + if (err) { + return callback(err); + } + // 1. check IAM role arn + const localIAMRole = deployState.iamRole; + const remoteIAMRole = data.Configuration.Role; + if (stringUtils.isNonBlankString(localIAMRole) && !R.equals(localIAMRole, remoteIAMRole)) { + return callback(`The IAM role for Lambda ARN (${lambdaArn}) should be "${remoteIAMRole}", but found "${localIAMRole}". \ Please solve this IAM role mismatch and re-deploy again. To ignore this error run "ask deploy --ignore-hash".`); - } - // 2. check revision id - const localRevisionId = deployState.lambda.revisionId; - const remoteRevisionId = data.Configuration.RevisionId; - if (stringUtils.isNonBlankString(localRevisionId) && !R.equals(localRevisionId, remoteRevisionId) && !ignoreHash) { - return callback(`The current revisionId (The revision ID for Lambda ARN (${lambdaArn}) should be ${remoteRevisionId}, \ + } + // 2. check revision id + const localRevisionId = deployState.lambda.revisionId; + const remoteRevisionId = data.Configuration.RevisionId; + if (stringUtils.isNonBlankString(localRevisionId) && !R.equals(localRevisionId, remoteRevisionId) && !ignoreHash) { + return callback(`The current revisionId (The revision ID for Lambda ARN (${lambdaArn}) should be ${remoteRevisionId}, \ but found ${localRevisionId}. Please solve this revision mismatch and re-deploy again. \ To ignore this error run "ask deploy --ignore-hash".`); - } - // 3. return the loaded Lambda data - callback(null, { - iamRole: remoteIAMRole, - lambda: { - arn: lambdaArn, - revisionId: remoteRevisionId, - lastModified: data.Configuration.LastModified - } - }); + } + // 3. return the loaded Lambda data + callback(null, { + iamRole: remoteIAMRole, + lambda: { + arn: lambdaArn, + revisionId: remoteRevisionId, + lastModified: data.Configuration.LastModified, + }, }); + }); } function _loadLambdaFromUserConfigSource(reporter, lambdaClient, sourceLambdaArn, callback) { - lambdaClient.getFunction(sourceLambdaArn, (err, data) => { - if (err) { - return callback(`Failed to load the Lambda (${sourceLambdaArn}) specified in "sourceLambda". ${err}`); - } - const iamRole = data.Configuration.Role; - const lambda = { - arn: sourceLambdaArn, - revisionId: data.Configuration.RevisionId, - lastModified: data.Configuration.LastModified - }; - callback(undefined, { iamRole, lambda }); - }); + lambdaClient.getFunction(sourceLambdaArn, (err, data) => { + if (err) { + return callback(`Failed to load the Lambda (${sourceLambdaArn}) specified in "sourceLambda". ${err}`); + } + const iamRole = data.Configuration.Role; + const lambda = { + arn: sourceLambdaArn, + revisionId: data.Configuration.RevisionId, + lastModified: data.Configuration.LastModified, + }; + callback(undefined, {iamRole, lambda}); + }); } function deployIAMRole(reporter, deployIAMConfig, callback) { - const { awsProfile, alexaRegion, skillName, awsRegion, deployState } = deployIAMConfig; - const iamClient = new IAMClient({ awsProfile, awsRegion }); - const roleArn = deployState.iamRole; - if (R.isNil(roleArn) || R.isEmpty(roleArn)) { - reporter.updateStatus('No IAM role exists. Creating an IAM role...'); - _createIAMRole(reporter, iamClient, skillName, (roleErr, iamRoleArn) => { - if (roleErr) { - return callback(`Failed to create IAM role before deploying Lambda. ${roleErr}`); - } - callback(null, iamRoleArn); - }); - } else { - iamClient.getIAMRole(roleArn, (roleErr, roleData) => { - if (roleErr) { - if (roleErr.code === 'NoSuchEntity') { - callback(`The IAM role is not found. Please check if your IAM role from region ${alexaRegion} is valid.`); - } else { - callback(`Failed to retrieve IAM role (${roleArn}) for Lambda. ${roleErr}`); - } - } else { - reporter.updateStatus(`Current IAM role : "${roleArn}"...`); - callback(null, roleData.Role.Arn); - } - }); - } + const {awsProfile, alexaRegion, skillName, awsRegion, deployState} = deployIAMConfig; + const iamClient = new IAMClient({awsProfile, awsRegion}); + const roleArn = deployState.iamRole; + if (R.isNil(roleArn) || R.isEmpty(roleArn)) { + reporter.updateStatus("No IAM role exists. Creating an IAM role..."); + _createIAMRole(reporter, iamClient, skillName, (roleErr, iamRoleArn) => { + if (roleErr) { + return callback(`Failed to create IAM role before deploying Lambda. ${roleErr}`); + } + callback(null, iamRoleArn); + }); + } else { + iamClient.getIAMRole(roleArn, (roleErr, roleData) => { + if (roleErr) { + if (roleErr.code === "NoSuchEntity") { + callback(`The IAM role is not found. Please check if your IAM role from region ${alexaRegion} is valid.`); + } else { + callback(`Failed to retrieve IAM role (${roleArn}) for Lambda. ${roleErr}`); + } + } else { + reporter.updateStatus(`Current IAM role : "${roleArn}"...`); + callback(null, roleData.Role.Arn); + } + }); + } } function _createIAMRole(reporter, iamClient, skillName, callback) { - const roleName = _getIAMRoleName(skillName); - iamClient.createBasicLambdaRole(roleName, (roleErr, roleData) => { - if (roleErr) { - return callback(roleErr); - } - const roleArn = roleData.Role.Arn; - reporter.updateStatus(`Create Role (arn: ${roleArn}) in progress...`); - iamClient.attachBasicLambdaRolePolicy(roleArn, (policyErr) => { - if (policyErr) { - return callback(policyErr); - } - callback(null, roleData.Role.Arn); - }); + const roleName = _getIAMRoleName(skillName); + iamClient.createBasicLambdaRole(roleName, (roleErr, roleData) => { + if (roleErr) { + return callback(roleErr); + } + const roleArn = roleData.Role.Arn; + reporter.updateStatus(`Create Role (arn: ${roleArn}) in progress...`); + iamClient.attachBasicLambdaRolePolicy(roleArn, (policyErr) => { + if (policyErr) { + return callback(policyErr); + } + callback(null, roleData.Role.Arn); }); + }); } /** @@ -134,123 +136,127 @@ function _createIAMRole(reporter, iamClient, skillName, callback) { * @return {String} */ function _getIAMRoleName(skillName) { - // Generates a valid IAM Role function name. - // a IAM Role function name should follow the pattern: ask-lambda-skillName-timeStamp - // a valid role name cannot be longer than 64 characters, so the skillName should be <=39 characters since - // the roleNamePrefix is 11 characters including the trailing '-' and the timeStamp is 14 characters including the '-'. - const generateIAMRoleName = () => { - const roleNamePrefix = process.env.ASK_DEPLOY_ROLE_PREFIX || 'ask-lambda'; - const validSkillName = skillName.replace(/_/g, '-').substr(0, 39 - 1); - return `${roleNamePrefix}-${validSkillName}-${Date.now()}`; - }; + // Generates a valid IAM Role function name. + // a IAM Role function name should follow the pattern: ask-lambda-skillName-timeStamp + // a valid role name cannot be longer than 64 characters, so the skillName should be <=39 characters since + // the roleNamePrefix is 11 characters including the trailing '-' and the timeStamp is 14 characters including the '-'. + const generateIAMRoleName = () => { + const roleNamePrefix = process.env.ASK_DEPLOY_ROLE_PREFIX || "ask-lambda"; + const validSkillName = skillName.replace(/_/g, "-").substr(0, 39 - 1); + return `${roleNamePrefix}-${validSkillName}-${Date.now()}`; + }; - return generateIAMRoleName(); + return generateIAMRoleName(); } function deployLambdaFunction(reporter, options, callback) { - const { profile, awsProfile, alexaRegion, awsRegion, skillId, skillName, code, iamRoleArn, userConfig, deployState } = options; - const lambdaClient = new LambdaClient({ awsProfile, awsRegion }); - const zipFilePath = code.codeBuild; - if (R.isNil(deployState.lambda) || R.isEmpty(deployState.lambda)) { - reporter.updateStatus('No Lambda information exists. Creating a lambda function...'); - const createLambdaOptions = { - profile, - alexaRegion, - skillId, - skillName, - iamRoleArn, - zipFilePath, - userConfig - }; - _createLambdaFunction(reporter, lambdaClient, createLambdaOptions, (lambdaErr, lambdaResources) => { - if (lambdaErr) { - return callback(lambdaErr); - } - callback(null, lambdaResources); - }); - } else { - reporter.updateStatus(`Updating current Lambda function with ARN ${deployState.lambda.arn}...`); - const updateLambdaOptions = { - zipFilePath, - userConfig, - deployState - }; - _updateLambdaFunction(reporter, lambdaClient, updateLambdaOptions, (lambdaErr, lambdaResources) => { - if (lambdaErr) { - return callback(lambdaErr); - } - callback(null, lambdaResources); - }); - } + const {profile, awsProfile, alexaRegion, awsRegion, skillId, skillName, code, iamRoleArn, userConfig, deployState} = options; + const lambdaClient = new LambdaClient({awsProfile, awsRegion}); + const zipFilePath = code.codeBuild; + if (R.isNil(deployState.lambda) || R.isEmpty(deployState.lambda)) { + reporter.updateStatus("No Lambda information exists. Creating a lambda function..."); + const createLambdaOptions = { + profile, + alexaRegion, + skillId, + skillName, + iamRoleArn, + zipFilePath, + userConfig, + }; + _createLambdaFunction(reporter, lambdaClient, createLambdaOptions, (lambdaErr, lambdaResources) => { + if (lambdaErr) { + return callback(lambdaErr); + } + callback(null, lambdaResources); + }); + } else { + reporter.updateStatus(`Updating current Lambda function with ARN ${deployState.lambda.arn}...`); + const updateLambdaOptions = { + zipFilePath, + userConfig, + deployState, + }; + _updateLambdaFunction(reporter, lambdaClient, updateLambdaOptions, (lambdaErr, lambdaResources) => { + if (lambdaErr) { + return callback(lambdaErr); + } + callback(null, lambdaResources); + }); + } } function _createLambdaFunction(reporter, lambdaClient, options, callback) { - const { profile, alexaRegion, skillId, skillName, iamRoleArn, zipFilePath, userConfig } = options; - const functionName = _getLambdaFunctionName(alexaRegion, userConfig, skillName, profile); - const functionConfig = _getLambdaFunctionConfig(alexaRegion, userConfig); - const zipFile = fs.readFileSync(zipFilePath); - const retryConfig = { - base: CONSTANTS.CONFIGURATION.RETRY.CREATE_LAMBDA_FUNCTION.BASE, - factor: CONSTANTS.CONFIGURATION.RETRY.CREATE_LAMBDA_FUNCTION.FACTOR, - maxRetry: CONSTANTS.CONFIGURATION.RETRY.CREATE_LAMBDA_FUNCTION.MAXRETRY - }; - const RETRY_MESSAGE = 'The role defined for the function cannot be assumed by Lambda.'; - const retryCall = (loopCallback) => { - // 1. Create a Lambda function - lambdaClient.createLambdaFunction(functionName, functionConfig, iamRoleArn, zipFile, (lambdaErr, lambdaData) => { - if (lambdaErr) { - // There may be a (small) window of time after creating IAM role and adding policies, the role will trigger the error - // if creating lambda function during this timming. Thus, use retry to bypass this issue. - if (lambdaErr.message === RETRY_MESSAGE) { - return loopCallback(null, RETRY_MESSAGE); - } - return loopCallback(lambdaErr); - } - loopCallback(null, lambdaData); - }); - }; - const shouldRetryCondition = retryResponse => retryResponse === RETRY_MESSAGE; - retryUtils.retry(retryConfig, retryCall, shouldRetryCondition, (retryErr, createData) => { - if (retryErr) { - return callback(retryErr); + const {profile, alexaRegion, skillId, skillName, iamRoleArn, zipFilePath, userConfig} = options; + const functionName = _getLambdaFunctionName(alexaRegion, userConfig, skillName, profile); + const functionConfig = _getLambdaFunctionConfig(alexaRegion, userConfig); + const zipFile = fs.readFileSync(zipFilePath); + const retryConfig = { + base: CONSTANTS.CONFIGURATION.RETRY.CREATE_LAMBDA_FUNCTION.BASE, + factor: CONSTANTS.CONFIGURATION.RETRY.CREATE_LAMBDA_FUNCTION.FACTOR, + maxRetry: CONSTANTS.CONFIGURATION.RETRY.CREATE_LAMBDA_FUNCTION.MAXRETRY, + }; + const RETRY_MESSAGE = "The role defined for the function cannot be assumed by Lambda."; + const retryCall = (loopCallback) => { + // 1. Create a Lambda function + lambdaClient.createLambdaFunction(functionName, functionConfig, iamRoleArn, zipFile, (lambdaErr, lambdaData) => { + if (lambdaErr) { + // There may be a (small) window of time after creating IAM role and adding policies, the role will trigger the error + // if creating lambda function during this timming. Thus, use retry to bypass this issue. + if (lambdaErr.message === RETRY_MESSAGE) { + return loopCallback(null, RETRY_MESSAGE); + } + return loopCallback(lambdaErr); + } + loopCallback(null, lambdaData); + }); + }; + const shouldRetryCondition = (retryResponse) => retryResponse === RETRY_MESSAGE; + retryUtils.retry(retryConfig, retryCall, shouldRetryCondition, (retryErr, createData) => { + if (retryErr) { + return callback(retryErr); + } + const functionArn = createData.FunctionArn; + // 2. Wait for created lambda function to be active + _waitForLambdaFunction(lambdaClient, functionArn, (waitErr) => { + if (waitErr) { + return callback(waitErr); + } + // 3. Grant permissions to use a Lambda function + _addEventPermissions(lambdaClient, skillId, functionArn, profile, (permErr, lambdaData) => { + if (permErr) { + return callback(permErr); } - const functionArn = createData.FunctionArn; - // 2. Wait for created lambda function to be active - _waitForLambdaFunction(lambdaClient, functionArn, (waitErr) => { - if (waitErr) { - return callback(waitErr); - } - // 3. Grant permissions to use a Lambda function - _addEventPermissions(lambdaClient, skillId, functionArn, profile, (permErr, lambdaData) => { - if (permErr) { - return callback(permErr); - } - callback(null, { - isAllStepSuccess: true, - isCodeDeployed: true, - lambdaResponse: { - arn: functionArn, - lastModified: lambdaData.LastModified, - revisionId: lambdaData.RevisionId - } - }); - }); + callback(null, { + isAllStepSuccess: true, + isCodeDeployed: true, + lambdaResponse: { + arn: functionArn, + lastModified: lambdaData.LastModified, + revisionId: lambdaData.RevisionId, + }, }); + }); }); + }); } function _addEventPermissions(lambdaClient, skillId, functionArn, profile, callback) { - const targetEndpoints = ResourcesConfig.getInstance().getTargetEndpoints(profile); - // for backward compatibility, defaulting to api from skill manifest if targetEndpoints is not defined - const domains = targetEndpoints.length ? targetEndpoints : Object.keys(Manifest.getInstance().getApis()); - async.forEach(domains, (domain, permCallback) => { - lambdaClient.addAlexaPermissionByDomain(domain, skillId, functionArn, permCallback); - }, (permErr) => { - if (permErr) { - return callback(permErr); - } - _waitForLambdaFunction(lambdaClient, functionArn, callback); - }); + const targetEndpoints = ResourcesConfig.getInstance().getTargetEndpoints(profile); + // for backward compatibility, defaulting to api from skill manifest if targetEndpoints is not defined + const domains = targetEndpoints.length ? targetEndpoints : Object.keys(Manifest.getInstance().getApis()); + async.forEach( + domains, + (domain, permCallback) => { + lambdaClient.addAlexaPermissionByDomain(domain, skillId, functionArn, permCallback); + }, + (permErr) => { + if (permErr) { + return callback(permErr); + } + _waitForLambdaFunction(lambdaClient, functionArn, callback); + }, + ); } /** @@ -261,8 +267,7 @@ function _addEventPermissions(lambdaClient, skillId, functionArn, profile, callb * @return {String} */ function _getLambdaConfigParameter(alexaRegion, userConfig, parameter) { - return R.path(['regionalOverrides', alexaRegion, 'lambda', parameter], userConfig) - || R.path(['lambda', parameter], userConfig); + return R.path(["regionalOverrides", alexaRegion, "lambda", parameter], userConfig) || R.path(["lambda", parameter], userConfig); } /** @@ -274,16 +279,16 @@ function _getLambdaConfigParameter(alexaRegion, userConfig, parameter) { * @return {String} */ function _getLambdaFunctionName(alexaRegion, userConfig, skillName, profile) { - // Generates a valid Lambda function name. - // a lambda function name should follow the pattern: ask-skillName-profileName-alexaRegion-timeStamp - // a valid function name cannot longer than 64 characters, so cli fixes the project name no longer than 22 characters - const generateFunctionName = () => { - const validSkillName = stringUtils.filterNonAlphanumeric(skillName.toLowerCase()).substring(0, 22); - const validProfile = stringUtils.filterNonAlphanumeric(profile.toLowerCase()).substring(0, 15); - return `ask-${validSkillName}-${validProfile}-${alexaRegion}-${Date.now()}`; - }; + // Generates a valid Lambda function name. + // a lambda function name should follow the pattern: ask-skillName-profileName-alexaRegion-timeStamp + // a valid function name cannot longer than 64 characters, so cli fixes the project name no longer than 22 characters + const generateFunctionName = () => { + const validSkillName = stringUtils.filterNonAlphanumeric(skillName.toLowerCase()).substring(0, 22); + const validProfile = stringUtils.filterNonAlphanumeric(profile.toLowerCase()).substring(0, 15); + return `ask-${validSkillName}-${validProfile}-${alexaRegion}-${Date.now()}`; + }; - return _getLambdaConfigParameter(alexaRegion, userConfig, 'functionName') || generateFunctionName(); + return _getLambdaConfigParameter(alexaRegion, userConfig, "functionName") || generateFunctionName(); } /** @@ -293,113 +298,114 @@ function _getLambdaFunctionName(alexaRegion, userConfig, skillName, profile) { * @return {Object} */ function _getLambdaFunctionConfig(alexaRegion, userConfig) { - const { runtime, handler } = userConfig; - const description = _getLambdaConfigParameter(alexaRegion, userConfig, 'description'); - const memorySize = _getLambdaConfigParameter(alexaRegion, userConfig, 'memorySize'); - const timeout = _getLambdaConfigParameter(alexaRegion, userConfig, 'timeout'); - const environmentVariables = _getLambdaConfigParameter(alexaRegion, userConfig, 'environmentVariables'); - return { - runtime, - handler, - description, - memorySize: Number.parseInt(memorySize, 10) || CONSTANTS.LAMBDA.DEFAULT_CONFIG.MEMORY_SIZE, - timeout: Number.parseInt(timeout, 10) || CONSTANTS.LAMBDA.DEFAULT_CONFIG.TIMEOUT, - environmentVariables - }; + const {runtime, handler} = userConfig; + const description = _getLambdaConfigParameter(alexaRegion, userConfig, "description"); + const memorySize = _getLambdaConfigParameter(alexaRegion, userConfig, "memorySize"); + const timeout = _getLambdaConfigParameter(alexaRegion, userConfig, "timeout"); + const environmentVariables = _getLambdaConfigParameter(alexaRegion, userConfig, "environmentVariables"); + return { + runtime, + handler, + description, + memorySize: Number.parseInt(memorySize, 10) || CONSTANTS.LAMBDA.DEFAULT_CONFIG.MEMORY_SIZE, + timeout: Number.parseInt(timeout, 10) || CONSTANTS.LAMBDA.DEFAULT_CONFIG.TIMEOUT, + environmentVariables, + }; } function _updateLambdaFunction(reporter, lambdaClient, options, callback) { - _updateLambdaFunctionCode(reporter, lambdaClient, options, (codeErr, codeData) => { - if (codeErr) { - return callback(codeErr); - } + _updateLambdaFunctionCode(reporter, lambdaClient, options, (codeErr, codeData) => { + if (codeErr) { + return callback(codeErr); + } - _updateLambdaFunctionConfig(reporter, lambdaClient, options, codeData.RevisionId, (configErr, configData) => { - if (configErr) { - return callback(null, { - isAllStepSuccess: false, - isCodeDeployed: true, - lambdaResponse: { - arn: codeData.FunctionArn, - lastModified: codeData.LastModified, - revisionId: codeData.RevisionId - }, - resultMessage: configErr - }); - } - callback(null, { - isAllStepSuccess: true, - isCodeDeployed: true, - lambdaResponse: { - arn: configData.FunctionArn, - lastModified: configData.LastModified, - revisionId: configData.RevisionId - } - }); + _updateLambdaFunctionConfig(reporter, lambdaClient, options, codeData.RevisionId, (configErr, configData) => { + if (configErr) { + return callback(null, { + isAllStepSuccess: false, + isCodeDeployed: true, + lambdaResponse: { + arn: codeData.FunctionArn, + lastModified: codeData.LastModified, + revisionId: codeData.RevisionId, + }, + resultMessage: configErr, }); + } + callback(null, { + isAllStepSuccess: true, + isCodeDeployed: true, + lambdaResponse: { + arn: configData.FunctionArn, + lastModified: configData.LastModified, + revisionId: configData.RevisionId, + }, + }); }); + }); } function _updateLambdaFunctionCode(reporter, lambdaClient, options, callback) { - const { zipFilePath, deployState } = options; - const zipFile = fs.readFileSync(zipFilePath); - const functionArn = deployState.lambda.arn; - const { revisionId } = deployState.lambda; + const {zipFilePath, deployState} = options; + const zipFile = fs.readFileSync(zipFilePath); + const functionArn = deployState.lambda.arn; + const {revisionId} = deployState.lambda; - lambdaClient.updateFunctionCode(zipFile, functionArn, revisionId, (err) => { - if (err) { - return callback(err); - } + lambdaClient.updateFunctionCode(zipFile, functionArn, revisionId, (err) => { + if (err) { + return callback(err); + } - reporter.updateStatus(`Update a lambda function code (${functionArn}) in progress...`); + reporter.updateStatus(`Update a lambda function code (${functionArn}) in progress...`); - _waitForLambdaFunction(lambdaClient, functionArn, callback); - }); + _waitForLambdaFunction(lambdaClient, functionArn, callback); + }); } function _updateLambdaFunctionConfig(reporter, lambdaClient, options, revisionId, callback) { - const { alexaRegion, deployState, userConfig } = options; - const functionArn = deployState.lambda.arn; - const functionConfig = _getLambdaFunctionConfig(alexaRegion, userConfig); + const {alexaRegion, deployState, userConfig} = options; + const functionArn = deployState.lambda.arn; + const functionConfig = _getLambdaFunctionConfig(alexaRegion, userConfig); - lambdaClient.updateFunctionConfiguration(functionArn, functionConfig, revisionId, (err) => { - if (err) { - return callback(err); - } + lambdaClient.updateFunctionConfiguration(functionArn, functionConfig, revisionId, (err) => { + if (err) { + return callback(err); + } - reporter.updateStatus(`Update a lambda function configuration (${functionArn}) in progress...`); + reporter.updateStatus(`Update a lambda function configuration (${functionArn}) in progress...`); - _waitForLambdaFunction(lambdaClient, functionArn, callback); - }); + _waitForLambdaFunction(lambdaClient, functionArn, callback); + }); } function _waitForLambdaFunction(lambdaClient, functionArn, callback) { - const retryConfig = { - base: CONSTANTS.CONFIGURATION.RETRY.WAIT_LAMBDA_FUNCTION.BASE, - factor: CONSTANTS.CONFIGURATION.RETRY.WAIT_LAMBDA_FUNCTION.FACTOR, - maxRetry: CONSTANTS.CONFIGURATION.RETRY.WAIT_LAMBDA_FUNCTION.MAXRETRY - }; - const retryCall = (loopCallback) => { - lambdaClient.getFunction(functionArn, (err, data) => { - if (err) { - return loopCallback(err); - } - loopCallback(null, data.Configuration); - }); - }; - const shouldRetryCondition = (retryResponse) => retryResponse.State === CONSTANTS.LAMBDA.FUNCTION_STATE.PENDING - || retryResponse.LastUpdateStatus === CONSTANTS.LAMBDA.LAST_UPDATE_STATUS.IN_PROGRESS; - - retryUtils.retry(retryConfig, retryCall, shouldRetryCondition, (retryErr, lambdaData) => { - if (retryErr) { - return callback(retryErr); - } - if (lambdaData.State !== CONSTANTS.LAMBDA.FUNCTION_STATE.ACTIVE) { - return callback(`Function [${functionArn}] state is ${lambdaData.State}.`); - } - if (lambdaData.LastUpdateStatus !== CONSTANTS.LAMBDA.LAST_UPDATE_STATUS.SUCCESSFUL) { - return callback(`Function [${functionArn}] last update status is ${lambdaData.LastUpdateStatus}.`); - } - callback(null, lambdaData); + const retryConfig = { + base: CONSTANTS.CONFIGURATION.RETRY.WAIT_LAMBDA_FUNCTION.BASE, + factor: CONSTANTS.CONFIGURATION.RETRY.WAIT_LAMBDA_FUNCTION.FACTOR, + maxRetry: CONSTANTS.CONFIGURATION.RETRY.WAIT_LAMBDA_FUNCTION.MAXRETRY, + }; + const retryCall = (loopCallback) => { + lambdaClient.getFunction(functionArn, (err, data) => { + if (err) { + return loopCallback(err); + } + loopCallback(null, data.Configuration); }); + }; + const shouldRetryCondition = (retryResponse) => + retryResponse.State === CONSTANTS.LAMBDA.FUNCTION_STATE.PENDING || + retryResponse.LastUpdateStatus === CONSTANTS.LAMBDA.LAST_UPDATE_STATUS.IN_PROGRESS; + + retryUtils.retry(retryConfig, retryCall, shouldRetryCondition, (retryErr, lambdaData) => { + if (retryErr) { + return callback(retryErr); + } + if (lambdaData.State !== CONSTANTS.LAMBDA.FUNCTION_STATE.ACTIVE) { + return callback(`Function [${functionArn}] state is ${lambdaData.State}.`); + } + if (lambdaData.LastUpdateStatus !== CONSTANTS.LAMBDA.LAST_UPDATE_STATUS.SUCCESSFUL) { + return callback(`Function [${functionArn}] last update status is ${lambdaData.LastUpdateStatus}.`); + } + callback(null, lambdaData); + }); } diff --git a/lib/builtins/deploy-delegates/lambda-deployer/index.js b/lib/builtins/deploy-delegates/lambda-deployer/index.js index 2352e98d..086f3246 100644 --- a/lib/builtins/deploy-delegates/lambda-deployer/index.js +++ b/lib/builtins/deploy-delegates/lambda-deployer/index.js @@ -1,12 +1,12 @@ -const R = require('ramda'); +const R = require("ramda"); -const awsUtil = require('@src/clients/aws-client/aws-util'); -const stringUtils = require('@src/utils/string-utils'); -const helper = require('./helper'); +const awsUtil = require("../../../clients/aws-client/aws-util"); +const stringUtils = require("../../../utils/string-utils"); +const helper = require("./helper"); module.exports = { - bootstrap, - invoke + bootstrap, + invoke, }; /** @@ -15,11 +15,11 @@ module.exports = { * @param {Function} callback */ function bootstrap(options, callback) { - const { profile, userConfig } = options; - const awsProfile = awsUtil.getAWSProfile(profile); - const awsDefaultRegion = awsUtil.getCLICompatibleDefaultRegion(awsProfile); - const updatedUserConfig = R.set(R.lensPath(['awsRegion']), awsDefaultRegion, userConfig); - callback(null, { userConfig: updatedUserConfig }); + const {profile, userConfig} = options; + const awsProfile = awsUtil.getAWSProfile(profile); + const awsDefaultRegion = awsUtil.getCLICompatibleDefaultRegion(awsProfile); + const updatedUserConfig = R.set(R.lensPath(["awsRegion"]), awsDefaultRegion, userConfig); + callback(null, {userConfig: updatedUserConfig}); } /** @@ -29,100 +29,102 @@ function bootstrap(options, callback) { * @param {Function} callback */ function invoke(reporter, options, callback) { - const { profile, ignoreHash, alexaRegion, skillId, skillName, code, userConfig, deployState = {}, deployRegions } = options; - const currentRegionDeployState = deployState[alexaRegion] || {}; - const awsProfile = awsUtil.getAWSProfile(profile); - if (!stringUtils.isNonBlankString(awsProfile)) { - return callback(`Profile [${profile}] doesn't have AWS profile linked to it. Please run "ask configure" to re-configure your porfile.`); - } - const awsRegion = deployRegions[alexaRegion]; - if (!stringUtils.isNonBlankString(awsRegion)) { - return callback(`Unsupported Alexa region: ${alexaRegion}. Please check your region name or use "regionalOverrides" to specify AWS region.`); + const {profile, ignoreHash, alexaRegion, skillId, skillName, code, userConfig, deployState = {}, deployRegions} = options; + const currentRegionDeployState = deployState[alexaRegion] || {}; + const awsProfile = awsUtil.getAWSProfile(profile); + if (!stringUtils.isNonBlankString(awsProfile)) { + return callback(`Profile [${profile}] doesn't have AWS profile linked to it. Please run "ask configure" to re-configure your profile.`); + } + const awsRegion = deployRegions[alexaRegion]; + if (!stringUtils.isNonBlankString(awsRegion)) { + return callback( + `Unsupported Alexa region: ${alexaRegion}. Please check your region name or use "regionalOverrides" to specify AWS region.`, + ); + } + const deployRegion = R.keys(deployRegions).find((region) => deployRegions[region] === awsRegion); + if (deployRegion !== alexaRegion && R.equals(deployState[deployRegion], deployState[alexaRegion])) { + return callback(null, { + isDeploySkipped: true, + deployRegion, + resultMessage: `The lambda deploy for Alexa region "${alexaRegion}" is same as "${deployRegion}"`, + }); + } + + // load Lambda info from either existing deployState or userConfig's sourceLambda + const loadLambdaConfig = {awsProfile, awsRegion, alexaRegion, ignoreHash, deployState: currentRegionDeployState, userConfig}; + helper.loadLambdaInformation(reporter, loadLambdaConfig, (loadLambdaErr, lambdaData) => { + if (loadLambdaErr) { + return callback(null, { + isAllStepSuccess: false, + isCodeDeployed: false, + deployState: currentRegionDeployState, + resultMessage: `The lambda deploy failed for Alexa region "${alexaRegion}": ${loadLambdaErr}`, + }); } - const deployRegion = R.keys(deployRegions).find((region) => deployRegions[region] === awsRegion); - if (deployRegion !== alexaRegion && R.equals(deployState[deployRegion], deployState[alexaRegion])) { + currentRegionDeployState.lambda = lambdaData.lambda; + currentRegionDeployState.iamRole = lambdaData.iamRole; + // create/update deploy for IAM role + const deployIAMConfig = { + awsProfile, + awsRegion, + alexaRegion, + skillName, + deployState: currentRegionDeployState, + }; + helper.deployIAMRole(reporter, deployIAMConfig, (iamErr, iamRoleArn) => { + if (iamErr) { return callback(null, { - isDeploySkipped: true, - deployRegion, - resultMessage: `The lambda deploy for Alexa region "${alexaRegion}" is same as "${deployRegion}"` + isAllStepSuccess: false, + isCodeDeployed: false, + deployState: currentRegionDeployState, + resultMessage: `The lambda deploy failed for Alexa region "${alexaRegion}": ${iamErr}`, }); - } - - // load Lambda info from either existing deployState or userConfig's sourceLambda - const loadLambdaConfig = { awsProfile, awsRegion, alexaRegion, ignoreHash, deployState: currentRegionDeployState, userConfig }; - helper.loadLambdaInformation(reporter, loadLambdaConfig, (loadLambdaErr, lambdaData) => { - if (loadLambdaErr) { - return callback(null, { - isAllStepSuccess: false, - isCodeDeployed: false, - deployState: currentRegionDeployState, - resultMessage: `The lambda deploy failed for Alexa region "${alexaRegion}": ${loadLambdaErr}` - }); + } + currentRegionDeployState.iamRole = iamRoleArn; + // create/update deploy for Lambda + const deployLambdaConfig = { + profile, + awsProfile, + alexaRegion, + awsRegion, + skillId, + skillName, + code, + iamRoleArn, + userConfig, + deployState: currentRegionDeployState, + }; + helper.deployLambdaFunction(reporter, deployLambdaConfig, (lambdaErr, lambdaResult) => { + // 1.fatal error happens in Lambda deployment and nothing need to record additionally + if (lambdaErr) { + return callback(null, { + isAllStepSuccess: false, + isCodeDeployed: false, + deployState: currentRegionDeployState, + resultMessage: `The lambda deploy failed for Alexa region "${alexaRegion}": ${lambdaErr}`, + }); + } + const {isAllStepSuccess, isCodeDeployed, lambdaResponse = {}} = lambdaResult; + currentRegionDeployState.lambda = lambdaResponse; + const {arn} = lambdaResponse; + // 2.full successs in Lambda deploy + if (isAllStepSuccess) { + return callback(null, { + isAllStepSuccess, + isCodeDeployed, + deployState: currentRegionDeployState, + endpoint: {uri: arn}, + resultMessage: `The lambda deploy succeeded for Alexa region "${alexaRegion}" with output Lambda ARN: ${arn}.`, + }); } - currentRegionDeployState.lambda = lambdaData.lambda; - currentRegionDeployState.iamRole = lambdaData.iamRole; - // create/update deploy for IAM role - const deployIAMConfig = { - awsProfile, - awsRegion, - alexaRegion, - skillName, - deployState: currentRegionDeployState - }; - helper.deployIAMRole(reporter, deployIAMConfig, (iamErr, iamRoleArn) => { - if (iamErr) { - return callback(null, { - isAllStepSuccess: false, - isCodeDeployed: false, - deployState: currentRegionDeployState, - resultMessage: `The lambda deploy failed for Alexa region "${alexaRegion}": ${iamErr}` - }); - } - currentRegionDeployState.iamRole = iamRoleArn; - // create/update deploy for Lambda - const deployLambdaConfig = { - profile, - awsProfile, - alexaRegion, - awsRegion, - skillId, - skillName, - code, - iamRoleArn, - userConfig, - deployState: currentRegionDeployState - }; - helper.deployLambdaFunction(reporter, deployLambdaConfig, (lambdaErr, lambdaResult) => { - // 1.fatal error happens in Lambda deployment and nothing need to record additionally - if (lambdaErr) { - return callback(null, { - isAllStepSuccess: false, - isCodeDeployed: false, - deployState: currentRegionDeployState, - resultMessage: `The lambda deploy failed for Alexa region "${alexaRegion}": ${lambdaErr}` - }); - } - const { isAllStepSuccess, isCodeDeployed, lambdaResponse = {} } = lambdaResult; - currentRegionDeployState.lambda = lambdaResponse; - const { arn } = lambdaResponse; - // 2.full successs in Lambda deploy - if (isAllStepSuccess) { - return callback(null, { - isAllStepSuccess, - isCodeDeployed, - deployState: currentRegionDeployState, - endpoint: { uri: arn }, - resultMessage: `The lambda deploy succeeded for Alexa region "${alexaRegion}" with output Lambda ARN: ${arn}.` - }); - } - // 3.partial success in Lambda deploy (like only LambdaCode is deployed) - return callback(null, { - isAllStepSuccess, - isCodeDeployed, - deployState: currentRegionDeployState, - resultMessage: `The lambda deploy failed for Alexa region "${alexaRegion}": ${lambdaResult.resultMessage}` - }); - }); + // 3.partial success in Lambda deploy (like only LambdaCode is deployed) + return callback(null, { + isAllStepSuccess, + isCodeDeployed, + deployState: currentRegionDeployState, + resultMessage: `The lambda deploy failed for Alexa region "${alexaRegion}": ${lambdaResult.resultMessage}`, }); + }); }); + }); } diff --git a/lib/clients/aws-client/abstract-aws-client.js b/lib/clients/aws-client/abstract-aws-client.js index 1f31d9c2..b7cc9432 100644 --- a/lib/clients/aws-client/abstract-aws-client.js +++ b/lib/clients/aws-client/abstract-aws-client.js @@ -1,21 +1,21 @@ -const aws = require('aws-sdk'); +const aws = require("aws-sdk"); -const CONSTANTS = require('@src/utils/constants'); -const stringUtils = require('@src/utils/string-utils'); +const CONSTANTS = require("../../utils/constants"); +const stringUtils = require("../../utils/string-utils"); module.exports = class AbstractAwsClient { - constructor(configuration) { - const { awsProfile, awsRegion } = configuration; - if (!stringUtils.isNonBlankString(awsProfile) || !stringUtils.isNonBlankString(awsRegion)) { - throw new Error('Invalid awsProfile or Invalid awsRegion'); - } - if (awsProfile !== CONSTANTS.PLACEHOLDER.ENVIRONMENT_VAR.AWS_CREDENTIALS) { - aws.config.credentials = new aws.SharedIniFileCredentials({ - profile: awsProfile - }); - } - this.awsRegion = awsRegion; - this.awsProfile = awsProfile; - aws.config.region = this.awsRegion; + constructor(configuration) { + const {awsProfile, awsRegion} = configuration; + if (!stringUtils.isNonBlankString(awsProfile) || !stringUtils.isNonBlankString(awsRegion)) { + throw new Error("Invalid awsProfile or Invalid awsRegion"); } + if (awsProfile !== CONSTANTS.PLACEHOLDER.ENVIRONMENT_VAR.AWS_CREDENTIALS) { + aws.config.credentials = new aws.SharedIniFileCredentials({ + profile: awsProfile, + }); + } + this.awsRegion = awsRegion; + this.awsProfile = awsProfile; + aws.config.region = this.awsRegion; + } }; diff --git a/lib/clients/aws-client/aws-util.js b/lib/clients/aws-client/aws-util.js index 1733c7ab..c9404580 100644 --- a/lib/clients/aws-client/aws-util.js +++ b/lib/clients/aws-client/aws-util.js @@ -1,14 +1,14 @@ -const aws = require('aws-sdk'); -const fs = require('fs-extra'); -const os = require('os'); -const path = require('path'); -const R = require('ramda'); +const aws = require("aws-sdk"); +const fs = require("fs-extra"); +const os = require("os"); +const path = require("path"); +const R = require("ramda"); -const CONSTANT = require('@src/utils/constants'); +const CONSTANT = require("../../utils/constants"); module.exports = { - getAWSProfile, - getCLICompatibleDefaultRegion + getAWSProfile, + getCLICompatibleDefaultRegion, }; /** @@ -16,45 +16,45 @@ module.exports = { * @param {string} askProfile cli profile name */ function getAWSProfile(askProfile) { - if (askProfile === CONSTANT.PLACEHOLDER.ENVIRONMENT_VAR.PROFILE_NAME) { - const awsAccessKeyId = process.env.AWS_ACCESS_KEY_ID; - const awsSecretAccessKey = process.env.AWS_SECRET_ACCESS_KEY; + if (askProfile === CONSTANT.PLACEHOLDER.ENVIRONMENT_VAR.PROFILE_NAME) { + const awsAccessKeyId = process.env.AWS_ACCESS_KEY_ID; + const awsSecretAccessKey = process.env.AWS_SECRET_ACCESS_KEY; - if (awsAccessKeyId && awsSecretAccessKey) { - return CONSTANT.PLACEHOLDER.ENVIRONMENT_VAR.AWS_CREDENTIALS; - } + if (awsAccessKeyId && awsSecretAccessKey) { + return CONSTANT.PLACEHOLDER.ENVIRONMENT_VAR.AWS_CREDENTIALS; } - const askConfig = fs.readJSONSync(path.join(os.homedir(), '.ask', 'cli_config')); - return R.view(R.lensPath(['profiles', askProfile, 'aws_profile']), askConfig); + } + const askConfig = fs.readJSONSync(path.join(os.homedir(), ".ask", "cli_config")); + return R.view(R.lensPath(["profiles", askProfile, "aws_profile"]), askConfig); } // We face the same issue as mentioned in https://github.com/aws/aws-sdk-js/issues/2181 // Issue is about when we instantiate the aws-sdk, the region value is not passed in correctly based on the profile. // Temporary solution is to mimic aws-sdk's credential provider chain and wait for the solution. class SharedIniFile { - constructor(options) { - options = options || {}; - this.isConfig = options.isConfig === true; - this.filename = options.filename || this._getDefaultFilepath(); - } + constructor(options) { + options = options || {}; + this.isConfig = options.isConfig === true; + this.filename = options.filename || this._getDefaultFilepath(); + } - getProfile(profile) { - const profileIndex = profile !== aws.util.defaultProfile && this.isConfig ? `profile ${profile}` : profile; - const configFile = this._ensureFileLoaded(); - return configFile ? configFile[profileIndex] : null; - } + getProfile(profile) { + const profileIndex = profile !== aws.util.defaultProfile && this.isConfig ? `profile ${profile}` : profile; + const configFile = this._ensureFileLoaded(); + return configFile ? configFile[profileIndex] : null; + } - _getDefaultFilepath() { - return path.join(os.homedir(), '.aws', this.isConfig ? 'config' : 'credentials'); - } + _getDefaultFilepath() { + return path.join(os.homedir(), ".aws", this.isConfig ? "config" : "credentials"); + } - _ensureFileLoaded() { - if (fs.existsSync(this.filename)) { - const contents = fs.readFileSync(this.filename, 'utf-8').toString(); - return aws.util.ini.parse(contents); - } - return null; + _ensureFileLoaded() { + if (fs.existsSync(this.filename)) { + const contents = fs.readFileSync(this.filename, "utf-8").toString(); + return aws.util.ini.parse(contents); } + return null; + } } /** @@ -62,21 +62,21 @@ class SharedIniFile { * @param {string} runtimeProfile aws profile name */ function getCLICompatibleDefaultRegion(awsProfile) { - const profile = awsProfile || process.env.AWS_PROFILE || process.env.AWS_DEFAULT_PROFILE || 'default'; - const toCheck = [ - { - filename: process.env.AWS_SHARED_CREDENTIALS_FILE - }, - { - isConfig: true, - filename: process.env.AWS_CONFIG_FILE - } - ]; - let region = process.env.AWS_REGION || process.env.AMAZON_REGION || process.env.AWS_DEFAULT_REGION || process.env.AMAZON_DEFAULT_REGION; - while (!region && toCheck.length > 0) { - const configFile = new SharedIniFile(toCheck.shift()); - const section = configFile.getProfile(profile); - region = section && section.region; - } - return region || CONSTANT.AWS_SKILL_INFRASTRUCTURE_DEFAULT_REGION; + const profile = awsProfile || process.env.AWS_PROFILE || process.env.AWS_DEFAULT_PROFILE || "default"; + const toCheck = [ + { + filename: process.env.AWS_SHARED_CREDENTIALS_FILE, + }, + { + isConfig: true, + filename: process.env.AWS_CONFIG_FILE, + }, + ]; + let region = process.env.AWS_REGION || process.env.AMAZON_REGION || process.env.AWS_DEFAULT_REGION || process.env.AMAZON_DEFAULT_REGION; + while (!region && toCheck.length > 0) { + const configFile = new SharedIniFile(toCheck.shift()); + const section = configFile.getProfile(profile); + region = section && section.region; + } + return region || CONSTANT.AWS_SKILL_INFRASTRUCTURE_DEFAULT_REGION; } diff --git a/lib/clients/aws-client/cloudformation-client.js b/lib/clients/aws-client/cloudformation-client.js index 7774b99a..d0735a85 100644 --- a/lib/clients/aws-client/cloudformation-client.js +++ b/lib/clients/aws-client/cloudformation-client.js @@ -1,127 +1,131 @@ -const aws = require('aws-sdk'); -const R = require('ramda'); -const stringUtils = require('@src/utils/string-utils'); -const AbstractAwsClient = require('./abstract-aws-client'); +const aws = require("aws-sdk"); +const R = require("ramda"); +const stringUtils = require("../../utils/string-utils"); +const AbstractAwsClient = require("./abstract-aws-client"); /** * Class for AWS Cloudformation Client */ module.exports = class CloudformationClient extends AbstractAwsClient { - constructor(configuration) { - super(configuration); - this.client = new aws.CloudFormation(); - } + constructor(configuration) { + super(configuration); + this.client = new aws.CloudFormation(); + } - /** - * Create a stack based on the parameters. - * @param {String} stackName The name for the stack - * @param {String} templateFile Template file's buffer (No bigger then 51200bytes) - * @param {Array} parameters Array of object that contains the input parameters - */ - createStack(stackName, templateFile, parameters) { - const params = { - StackName: stackName, - Capabilities: ['CAPABILITY_IAM'], - TemplateBody: templateFile - }; - if (parameters && !R.isEmpty(parameters)) { - params.Parameters = parameters; - } - return this.client.createStack(params).promise(); + /** + * Create a stack based on the parameters. + * @param {String} stackName The name for the stack + * @param {String} templateFile Template file's buffer (No bigger then 51200bytes) + * @param {Array} parameters Array of object that contains the input parameters + */ + createStack(stackName, templateFile, parameters) { + const params = { + StackName: stackName, + Capabilities: ["CAPABILITY_IAM"], + TemplateBody: templateFile, + }; + if (parameters && !R.isEmpty(parameters)) { + params.Parameters = parameters; } + return this.client.createStack(params).promise(); + } - /** - * Update the stack based on the stackName with input parameters. - * @param {String} stackName The name for the stack - * @param {String} templateFile Template file's buffer (No bigger then 51200bytes) - * @param {Array} parameters Array of object that contains the input parameters - */ - updateStack(stackName, templateFile, parameters) { - const params = { - StackName: stackName, - TemplateBody: templateFile, - Capabilities: ['CAPABILITY_IAM'] - }; - if (parameters && !R.isEmpty(parameters)) { - params.Parameters = parameters; - } - return this.client.updateStack(params).promise() - .then(res => res) - .catch(err => { - const NO_UPDATE_MESSAGE = 'No updates are to be performed.'; - if (err.code === 'ValidationError' && err.message === NO_UPDATE_MESSAGE) { - return NO_UPDATE_MESSAGE; - } - throw err; - }); + /** + * Update the stack based on the stackName with input parameters. + * @param {String} stackName The name for the stack + * @param {String} templateFile Template file's buffer (No bigger then 51200bytes) + * @param {Array} parameters Array of object that contains the input parameters + */ + updateStack(stackName, templateFile, parameters) { + const params = { + StackName: stackName, + TemplateBody: templateFile, + Capabilities: ["CAPABILITY_IAM"], + }; + if (parameters && !R.isEmpty(parameters)) { + params.Parameters = parameters; } + return this.client + .updateStack(params) + .promise() + .then((res) => res) + .catch((err) => { + const NO_UPDATE_MESSAGE = "No updates are to be performed."; + if (err.code === "ValidationError" && err.message === NO_UPDATE_MESSAGE) { + return NO_UPDATE_MESSAGE; + } + throw err; + }); + } - stackExists(stackId) { - if (!stringUtils.isNonBlankString(stackId)) return false; + stackExists(stackId) { + if (!stringUtils.isNonBlankString(stackId)) return false; - return this.client.describeStacks({ StackName: stackId }).promise() - .then(data => data.Stacks[0].StackStatus !== 'DELETE_COMPLETE') - .catch(() => false); - } + return this.client + .describeStacks({StackName: stackId}) + .promise() + .then((data) => data.Stacks[0].StackStatus !== "DELETE_COMPLETE") + .catch(() => false); + } - /** - * Describe stack status based on the stack ID - * @param {String} stackId The stack ID - * @param {Function} callback - */ - describeStack(stackId, callback) { - if (!stringUtils.isNonBlankString(stackId)) { - callback('Stack ID must be set to further describe'); - return; - } - const params = { - StackName: stackId - }; - this.client.describeStacks(params, (err, response) => { - // callback the first stack's description since stackId is required for the method - callback(err, err ? null : response.Stacks[0]); - }); + /** + * Describe stack status based on the stack ID + * @param {String} stackId The stack ID + * @param {Function} callback + */ + describeStack(stackId, callback) { + if (!stringUtils.isNonBlankString(stackId)) { + callback("Stack ID must be set to further describe"); + return; } + const params = { + StackName: stackId, + }; + this.client.describeStacks(params, (err, response) => { + // callback the first stack's description since stackId is required for the method + callback(err, err ? null : response.Stacks[0]); + }); + } - /** - * Describe specific resource in a stack - * @param {String} stackId The stack ID - * @param {String} logicalId The resource logical ID - * @param {Function} callback - */ - describeStackResource(stackId, logicalId, callback) { - if (!stringUtils.isNonBlankString(stackId)) { - callback('Stack ID must be set to describe its resources'); - return; - } - if (!stringUtils.isNonBlankString(logicalId)) { - callback('Logical ID must be set to describe its resources'); - return; - } - const params = { - StackName: stackId, - LogicalResourceId: logicalId - }; - this.client.describeStackResource(params, (err, response) => { - callback(err, err ? null : response.StackResourceDetail); - }); + /** + * Describe specific resource in a stack + * @param {String} stackId The stack ID + * @param {String} logicalId The resource logical ID + * @param {Function} callback + */ + describeStackResource(stackId, logicalId, callback) { + if (!stringUtils.isNonBlankString(stackId)) { + callback("Stack ID must be set to describe its resources"); + return; } + if (!stringUtils.isNonBlankString(logicalId)) { + callback("Logical ID must be set to describe its resources"); + return; + } + const params = { + StackName: stackId, + LogicalResourceId: logicalId, + }; + this.client.describeStackResource(params, (err, response) => { + callback(err, err ? null : response.StackResourceDetail); + }); + } - /** - * Describe all the resources for a stack - * @param {String} stackId The stack ID - * @param {Function} callback - */ - describeStackResources(stackId, callback) { - if (!stringUtils.isNonBlankString(stackId)) { - callback('Stack ID must be set to describe its resources'); - return; - } - const params = { - StackName: stackId - }; - this.client.describeStackResources(params, (err, response) => { - callback(err, err ? null : response.StackResources); - }); + /** + * Describe all the resources for a stack + * @param {String} stackId The stack ID + * @param {Function} callback + */ + describeStackResources(stackId, callback) { + if (!stringUtils.isNonBlankString(stackId)) { + callback("Stack ID must be set to describe its resources"); + return; } + const params = { + StackName: stackId, + }; + this.client.describeStackResources(params, (err, response) => { + callback(err, err ? null : response.StackResources); + }); + } }; diff --git a/lib/clients/aws-client/iam-client.js b/lib/clients/aws-client/iam-client.js index 8f8d5b2b..de059979 100644 --- a/lib/clients/aws-client/iam-client.js +++ b/lib/clients/aws-client/iam-client.js @@ -1,70 +1,70 @@ -const aws = require('aws-sdk'); +const aws = require("aws-sdk"); -const CONSTANTS = require('@src/utils/constants'); -const AbstractAwsClient = require('./abstract-aws-client'); +const CONSTANTS = require("../../utils/constants"); +const AbstractAwsClient = require("./abstract-aws-client"); /** * Class for AWS IAM Client */ module.exports = class IAMClient extends AbstractAwsClient { - constructor(configuration) { - super(configuration); - this.client = new aws.IAM(); - } + constructor(configuration) { + super(configuration); + this.client = new aws.IAM(); + } - /** - * Wrapper of iam sdk api - * Retrieves information about the specified role - * @param {string} roleArn The arn of the IAM role to get information about. - * @param {callback} callback { error, response } - */ - getIAMRole(roleArn, callback) { - const params = { - RoleName: this._extractIAMRoleName(roleArn) - }; - this.client.getRole(params, (err, response) => { - callback(err, !err ? response : null); - }); - } + /** + * Wrapper of iam sdk api + * Retrieves information about the specified role + * @param {string} roleArn The arn of the IAM role to get information about. + * @param {callback} callback { error, response } + */ + getIAMRole(roleArn, callback) { + const params = { + RoleName: this._extractIAMRoleName(roleArn), + }; + this.client.getRole(params, (err, response) => { + callback(err, !err ? response : null); + }); + } - /** - * Wrapper of iam sdk api - * Creates a new role for AWS account. - * @param {string} roleName The name of the IAM role. - * @param {callback} callback { error, response } - */ - createBasicLambdaRole(roleName, callback) { - const policy = CONSTANTS.AWS.IAM.ROLE.LAMBDA_BASIC_ROLE.POLICY; - const params = { - RoleName: roleName, - AssumeRolePolicyDocument: JSON.stringify(policy) - }; - this.client.createRole(params, (err, response) => { - callback(err, !err ? response : null); - }); - } + /** + * Wrapper of iam sdk api + * Creates a new role for AWS account. + * @param {string} roleName The name of the IAM role. + * @param {callback} callback { error, response } + */ + createBasicLambdaRole(roleName, callback) { + const policy = CONSTANTS.AWS.IAM.ROLE.LAMBDA_BASIC_ROLE.POLICY; + const params = { + RoleName: roleName, + AssumeRolePolicyDocument: JSON.stringify(policy), + }; + this.client.createRole(params, (err, response) => { + callback(err, !err ? response : null); + }); + } - /** - * Wrapper of iam sdk api - * Attaches the specified managed policy to the specified IAM role. - * @param {string} roleArn The Amazon Resource Name (ARN) specifying the group. - * @param {callback} callback { error, response } - */ - attachBasicLambdaRolePolicy(roleArn, callback) { - const params = { - PolicyArn: CONSTANTS.AWS.IAM.ROLE.LAMBDA_BASIC_ROLE.POLICY_ARN, - RoleName: this._extractIAMRoleName(roleArn) - }; - this.client.attachRolePolicy(params, (err, response) => { - callback(err, !err ? response : null); - }); - } + /** + * Wrapper of iam sdk api + * Attaches the specified managed policy to the specified IAM role. + * @param {string} roleArn The Amazon Resource Name (ARN) specifying the group. + * @param {callback} callback { error, response } + */ + attachBasicLambdaRolePolicy(roleArn, callback) { + const params = { + PolicyArn: CONSTANTS.AWS.IAM.ROLE.LAMBDA_BASIC_ROLE.POLICY_ARN, + RoleName: this._extractIAMRoleName(roleArn), + }; + this.client.attachRolePolicy(params, (err, response) => { + callback(err, !err ? response : null); + }); + } - /** - * Extracts IAM Role from an existing iam role arn. - * @param {string} roleArn The Amazon Resource Name (ARN) specifying the group. - */ - _extractIAMRoleName(roleArn) { - return roleArn.split('role/').pop(); - } + /** + * Extracts IAM Role from an existing iam role arn. + * @param {string} roleArn The Amazon Resource Name (ARN) specifying the group. + */ + _extractIAMRoleName(roleArn) { + return roleArn.split("role/").pop(); + } }; diff --git a/lib/clients/aws-client/lambda-client.js b/lib/clients/aws-client/lambda-client.js index 58470caf..337d09cc 100644 --- a/lib/clients/aws-client/lambda-client.js +++ b/lib/clients/aws-client/lambda-client.js @@ -1,149 +1,150 @@ -const aws = require('aws-sdk'); +const aws = require("aws-sdk"); -const AbstractAwsClient = require('./abstract-aws-client'); +const stringUtils = require("../../utils/string-utils"); +const AbstractAwsClient = require("./abstract-aws-client"); /** * Class for Lambda Client */ module.exports = class LambdaClient extends AbstractAwsClient { - constructor(configuration) { - super(configuration); - this.client = new aws.Lambda(); - } + constructor(configuration) { + super(configuration); + this.client = new aws.Lambda(); + } - /** - * Wrapper of aws sdk api - * Creates a Lambda function - * @param {string} functionName The name of the Lambda function. - * @param {object} config The configuration of the Lambda function. - * @param {string} role The Amazon Resource Name (ARN) of the function's execution role. - * @param {Buffer} zipFile The base64-encoded contents of the deployment package. - * @param {callback} callback { error, response } - */ - createLambdaFunction(functionName, config, role, zipFile, callback) { - const { runtime, handler, description, memorySize, timeout, environmentVariables } = config; - const params = { - Code: { - ZipFile: zipFile - }, - FunctionName: functionName, - Handler: handler, - MemorySize: memorySize, - Role: role, - Runtime: runtime, - Timeout: timeout, - ...(description && { Description: description }), - ...(environmentVariables && { Environment: { Variables: environmentVariables } }) - }; - this.client.createFunction(params, (err, data) => { - callback(err, !err ? data : null); - }); - } + /** + * Wrapper of aws sdk api + * Creates a Lambda function + * @param {string} functionName The name of the Lambda function. + * @param {object} config The configuration of the Lambda function. + * @param {string} role The Amazon Resource Name (ARN) of the function's execution role. + * @param {Buffer} zipFile The base64-encoded contents of the deployment package. + * @param {callback} callback { error, response } + */ + createLambdaFunction(functionName, config, role, zipFile, callback) { + const {runtime, handler, description, memorySize, timeout, environmentVariables} = config; + const params = { + Code: { + ZipFile: zipFile, + }, + FunctionName: functionName, + Handler: handler, + MemorySize: memorySize, + Role: role, + Runtime: runtime, + Timeout: timeout, + ...(description && {Description: description}), + ...(environmentVariables && {Environment: {Variables: environmentVariables}}), + }; + this.client.createFunction(params, (err, data) => { + callback(err, !err ? data : null); + }); + } - /** - * Wrapper of aws sdk api - * Grants an AWS service or another account permission to use a function. - * @param {string} domain The type of skill. - * @param {string} skillId The skill ID is used as a token that must be supplied by the invoker. - * @param {string} functionArn The arn of the Lambda function. - * @param {callback} callback { error, response } - */ - addAlexaPermissionByDomain(domain, skillId, functionArn, callback) { - const params = this._getDomainPermission(domain); - if (!params) return callback(); + /** + * Wrapper of aws sdk api + * Grants an AWS service or another account permission to use a function. + * @param {string} domain The type of skill. + * @param {string} skillId The skill ID is used as a token that must be supplied by the invoker. + * @param {string} functionArn The arn of the Lambda function. + * @param {callback} callback { error, response } + */ + addAlexaPermissionByDomain(domain, skillId, functionArn, callback) { + const params = this._getDomainPermission(domain); + if (!params) return callback(); - params.FunctionName = functionArn; - params.EventSourceToken = skillId; - this.client.addPermission(params, (err, data) => { - callback(err, !err ? data : null); - }); - } + params.FunctionName = functionArn; + params.EventSourceToken = skillId; + this.client.addPermission(params, (err, data) => { + callback(err, !err ? data : null); + }); + } - /** - * Wrapper of aws sdk api - * Returns information about the function or function version - * @param {string} functionArn The name of the Lambda function - * @param {callback} callback { error, response } - */ - getFunction(functionArn, callback) { - const params = { - FunctionName: functionArn - }; - this.client.getFunction(params, (err, data) => { - callback(err, !err ? data : null); - }); - } + /** + * Wrapper of aws sdk api + * Returns information about the function or function version + * @param {string} functionArn The name of the Lambda function + * @param {callback} callback { error, response } + */ + getFunction(functionArn, callback) { + const params = { + FunctionName: functionArn, + }; + this.client.getFunction(params, (err, data) => { + callback(err, !err ? data : null); + }); + } - /** - * Wrapper of aws sdk api - * Updates a Lambda function's code. - * @param {Buffer} zipFile The base64-encoded contents of the deployment package. - * @param {string} functionArn The arn of the Lambda function. - * @param {string} revisionId Only update the function if the revision ID matches the ID that's specified. - * @param {callback} callback { error, response } - */ - updateFunctionCode(zipFile, functionArn, revisionId, callback) { - const codeUpdateParams = { - ZipFile: zipFile, - FunctionName: functionArn, - RevisionId: revisionId - }; - this.client.updateFunctionCode(codeUpdateParams, (err, data) => { - callback(err, !err ? data : null); - }); - } + /** + * Wrapper of aws sdk api + * Updates a Lambda function's code. + * @param {Buffer} zipFile The base64-encoded contents of the deployment package. + * @param {string} functionArn The arn of the Lambda function. + * @param {string} revisionId Only update the function if the revision ID matches the ID that's specified. + * @param {callback} callback { error, response } + */ + updateFunctionCode(zipFile, functionArn, revisionId, callback) { + const codeUpdateParams = { + ZipFile: zipFile, + FunctionName: functionArn, + RevisionId: revisionId, + }; + this.client.updateFunctionCode(codeUpdateParams, (err, data) => { + callback(err, !err ? data : null); + }); + } - /** - * Wrapper of aws sdk api - * Modifies the version-specific settings of a Lambda function. - * @param {string} functionArn The arn of the Lambda function. - * @param {object} config The configuration of the Lambda function. - * @param {string} revisionId Only update the function if the revision ID matches the ID that's specified. - * @param {callback} callback { error, response } - */ - updateFunctionConfiguration(functionArn, config, revisionId, callback) { - const { runtime, handler, description, memorySize, timeout, environmentVariables } = config; - const params = { - FunctionName: functionArn, - Handler: handler, - MemorySize: memorySize, - RevisionId: revisionId, - Runtime: runtime, - Timeout: timeout, - ...(description && { Description: description }), - ...(environmentVariables && { Environment: { Variables: environmentVariables } }) - }; - this.client.updateFunctionConfiguration(params, (err, data) => { - callback(err, !err ? data : null); - }); - } + /** + * Wrapper of aws sdk api + * Modifies the version-specific settings of a Lambda function. + * @param {string} functionArn The arn of the Lambda function. + * @param {object} config The configuration of the Lambda function. + * @param {string} revisionId Only update the function if the revision ID matches the ID that's specified. + * @param {callback} callback { error, response } + */ + updateFunctionConfiguration(functionArn, config, revisionId, callback) { + const {runtime, handler, description, memorySize, timeout, environmentVariables} = config; + const params = { + FunctionName: functionArn, + Handler: handler, + MemorySize: memorySize, + RevisionId: revisionId, + Runtime: runtime, + Timeout: timeout, + ...(description && {Description: description}), + ...(environmentVariables && {Environment: {Variables: environmentVariables}}), + }; + this.client.updateFunctionConfiguration(params, (err, data) => { + callback(err, !err ? data : null); + }); + } - /** - * Gets a permission configuration by skill domain. - * @param {string} domain skill domain - */ - _getDomainPermission(domain) { - let permission; - switch (domain) { - case 'smartHome': - case 'video': - permission = { - Action: 'lambda:InvokeFunction', - StatementId: Date.now().toString(), - Principal: 'alexa-connectedhome.amazon.com' - }; - break; - case 'custom': - case 'houseHoldList': - case 'music': - permission = { - Action: 'lambda:InvokeFunction', - StatementId: Date.now().toString(), - Principal: 'alexa-appkit.amazon.com' - }; - break; - default: - } - return permission; + /** + * Gets a permission configuration by skill domain. + * @param {string} domain skill domain + */ + _getDomainPermission(domain) { + let permission; + switch (domain) { + case "smartHome": + case "video": + permission = { + Action: "lambda:InvokeFunction", + StatementId: Date.now().toString(), + Principal: "alexa-connectedhome.amazon.com", + }; + break; + case "custom": + case "houseHoldList": + case "music": + permission = { + Action: "lambda:InvokeFunction", + StatementId: Date.now().toString(), + Principal: "alexa-appkit.amazon.com", + }; + break; + default: } + return permission; + } }; diff --git a/lib/clients/aws-client/s3-client.js b/lib/clients/aws-client/s3-client.js index 41a069a8..8e91d67d 100644 --- a/lib/clients/aws-client/s3-client.js +++ b/lib/clients/aws-client/s3-client.js @@ -1,76 +1,76 @@ -const fs = require('fs'); -const path = require('path'); -const R = require('ramda'); -const requestLib = require('request'); -const prettyBytes = require('pretty-bytes'); -const aws = require('aws-sdk'); +const fs = require("fs"); +const path = require("path"); +const R = require("ramda"); +const requestLib = require("request"); +const prettyBytes = require("pretty-bytes"); +const aws = require("aws-sdk"); -const SpinnerView = require('@src/view/spinner-view'); -const { ParallelStream } = require('@src/utils/stream-utility'); -const CONSTANTS = require('@src/utils/constants'); -const AbstractAwsClient = require('./abstract-aws-client'); +const SpinnerView = require("../../view/spinner-view"); +const {ParallelStream} = require("../../utils/stream-utility"); +const CONSTANTS = require("../../utils/constants"); +const AbstractAwsClient = require("./abstract-aws-client"); /** * Class for S3 client */ module.exports = class S3Client extends AbstractAwsClient { - constructor(configuration) { - super(configuration); + constructor(configuration) { + super(configuration); - const httpClient = new aws.NodeHttpClient(); - const httpAgent = httpClient.getAgent(true, { - keepAlive: false - }); - this.client = new aws.S3({ - httpOptions: { - agent: httpAgent - } - }); - } + const httpClient = new aws.NodeHttpClient(); + const httpAgent = httpClient.getAgent(true, { + keepAlive: false, + }); + this.client = new aws.S3({ + httpOptions: { + agent: httpAgent, + }, + }); + } - /** - * Upload to a pre-signed S3 url with custom options - * @param {string} url - * @param {object} options - * @param {function} callback - */ - static preSignedPutObject(url, options, callback) { - if (typeof url !== 'string' || !url.trim()) { - process.nextTick(() => callback('[Error]: The url for the S3 presigned URL upload must not be blank.')); - } - requestLib.put(url, options, (err, response) => { - callback(err, response); - }); + /** + * Upload to a pre-signed S3 url with custom options + * @param {string} url + * @param {object} options + * @param {function} callback + */ + static preSignedPutObject(url, options, callback) { + if (typeof url !== "string" || !url.trim()) { + process.nextTick(() => callback("[Error]: The url for the S3 presigned URL upload must not be blank.")); } + requestLib.put(url, options, (err, response) => { + callback(err, response); + }); + } - /** - * Function used to provision bucket and upload object to it - * @param {string} bucketName bucket name - * @param {string} key key name, key is the unique identifier for an object within a bucket. - * @param {string} lambdaRegion lambda region name - * @param {string} filePath file path to content want to upload - * @param {callback} callback { error, response } - */ - provisionBucketAndPutObject(bucketName, key, lambdaRegion, filePath, callback) { - this.createBucketIfNotExist(bucketName, lambdaRegion, (createErr) => { - if (createErr) { - return callback(createErr); - } - this.putBucketVersioningIfUninitialized(bucketName, (putVersionErr) => { - if (putVersionErr) { - return callback(putVersionErr); - } - this.putObject(bucketName, key, fs.readFileSync(filePath), (putObjectErr, putResponse) => { - if (putObjectErr) { - return callback(putObjectErr); - } - callback(null, putResponse); - }); - }); + /** + * Function used to provision bucket and upload object to it + * @param {string} bucketName bucket name + * @param {string} key key name, key is the unique identifier for an object within a bucket. + * @param {string} lambdaRegion lambda region name + * @param {string} filePath file path to content want to upload + * @param {callback} callback { error, response } + */ + provisionBucketAndPutObject(bucketName, key, lambdaRegion, filePath, callback) { + this.createBucketIfNotExist(bucketName, lambdaRegion, (createErr) => { + if (createErr) { + return callback(createErr); + } + this.putBucketVersioningIfUninitialized(bucketName, (putVersionErr) => { + if (putVersionErr) { + return callback(putVersionErr); + } + this.putObject(bucketName, key, fs.readFileSync(filePath), (putObjectErr, putResponse) => { + if (putObjectErr) { + return callback(putObjectErr); + } + callback(null, putResponse); }); - } + }); + }); + } - /** + /** * Function used to create s3 bucket with input bucket name * if no bucket with that name is found * first check whether the bucket is exist already and user has permission to access it @@ -81,56 +81,56 @@ module.exports = class S3Client extends AbstractAwsClient { * @param {string} region aws region name * @param {callback} callback { error } */ - createBucketIfNotExist(bucket, region, callback) { - this.headBucket(bucket, (headErr) => { - if (headErr) { - if (headErr.code !== 'NotFound') { - return callback(headErr); - } - this.createBucket(bucket, region, (createErr) => { - if (createErr) { - return callback(createErr); - } - this.waitForBucketExists(bucket, (waitErr) => { - if (waitErr) { - return callback(waitErr); - } - callback(); - }); - }); - } else { - callback(); + createBucketIfNotExist(bucket, region, callback) { + this.headBucket(bucket, (headErr) => { + if (headErr) { + if (headErr.code !== "NotFound") { + return callback(headErr); + } + this.createBucket(bucket, region, (createErr) => { + if (createErr) { + return callback(createErr); + } + this.waitForBucketExists(bucket, (waitErr) => { + if (waitErr) { + return callback(waitErr); } + callback(); + }); }); - } + } else { + callback(); + } + }); + } - /** - * Check if bucket versioning is initialized - * if not, put bucket versioning - * @param {string} bucketName bucket name - * @param {callback} callback { error } - */ - putBucketVersioningIfUninitialized(bucketName, callback) { - this.getBucketVersioning(bucketName, (getVersionErr, response) => { - if (getVersionErr) { - return callback(getVersionErr); - } - // if bucket versioning is not set, cli will set it with fixed config { MFADelete: Disabled, Status: Enabled } - // if bucket verisoning is already set, skip this step - if (typeof response === 'object' && R.keys(response).length === 0) { - this.putBucketVersioning(bucketName, 'Disabled', 'Enabled', (putVersionErr) => { - if (putVersionErr) { - return callback(putVersionErr); - } - callback(); - }); - } else { - callback(); - } + /** + * Check if bucket versioning is initialized + * if not, put bucket versioning + * @param {string} bucketName bucket name + * @param {callback} callback { error } + */ + putBucketVersioningIfUninitialized(bucketName, callback) { + this.getBucketVersioning(bucketName, (getVersionErr, response) => { + if (getVersionErr) { + return callback(getVersionErr); + } + // if bucket versioning is not set, cli will set it with fixed config { MFADelete: Disabled, Status: Enabled } + // if bucket verisoning is already set, skip this step + if (typeof response === "object" && R.keys(response).length === 0) { + this.putBucketVersioning(bucketName, "Disabled", "Enabled", (putVersionErr) => { + if (putVersionErr) { + return callback(putVersionErr); + } + callback(); }); - } + } else { + callback(); + } + }); + } - /** + /** * Wrapper of aws sdk api * Function used to update s3 bucket version * @param {string} bucketName bucket name @@ -140,247 +140,257 @@ module.exports = class S3Client extends AbstractAwsClient { * @param {enum} status Valid Values: Suspended | Enabled. Sets the versioning state of the bucket. * @param {callback} callback { error, response } */ - putBucketVersioning(bucketName, mfaDelete, status, callback) { - const params = { - Bucket: bucketName, - VersioningConfiguration: { - MFADelete: mfaDelete, - Status: status - } - }; - const request = this.client.putBucketVersioning(params); + putBucketVersioning(bucketName, mfaDelete, status, callback) { + const params = { + Bucket: bucketName, + VersioningConfiguration: { + MFADelete: mfaDelete, + Status: status, + }, + }; + const request = this.client.putBucketVersioning(params); - request.on('retry', (response) => { - this.retryBucketVersionOperations(response); - }); - request.on('success', (response) => { - callback(null, response.data); - }); - request.on('error', (error) => { - callback(error, null); - }); + request.on("retry", (response) => { + this.retryBucketVersionOperations(response); + }); + request.on("success", (response) => { + callback(null, response.data); + }); + request.on("error", (error) => { + callback(error, null); + }); - request.send(); - } + request.send(); + } - /** - * Wrapper of aws sdk api - * Function used to check whether the bucket versioning is set or not - * @param {string} bucketName bucket name - * @param {callback} callback { error, response } - */ - getBucketVersioning(bucketName, callback) { - const params = { - Bucket: bucketName - }; - const request = this.client.getBucketVersioning(params); + /** + * Wrapper of aws sdk api + * Function used to check whether the bucket versioning is set or not + * @param {string} bucketName bucket name + * @param {callback} callback { error, response } + */ + getBucketVersioning(bucketName, callback) { + const params = { + Bucket: bucketName, + }; + const request = this.client.getBucketVersioning(params); - request.on('retry', (response) => { - this.retryBucketVersionOperations(response); - }); - request.on('success', (response) => { - callback(null, response.data); - }); - request.on('error', (error) => { - callback(error, null); - }); + request.on("retry", (response) => { + this.retryBucketVersionOperations(response); + }); + request.on("success", (response) => { + callback(null, response.data); + }); + request.on("error", (error) => { + callback(error, null); + }); - request.send(); - } + request.send(); + } - /** - * Wrapper of aws sdk api - * Function used to create s3 bucket - * @param {string} bucketName the name of bucket want to create - * @param {string} region aws region code - * @param {callback} callback { error, response } - */ - createBucket(bucketName, region, callback) { - const params = { - Bucket: bucketName - }; - // us-east-1 is not a supported value for LocationConstraint property at aws apis - // should leave LocationConstraint empty when region code is us-east-1 - if (region && region !== 'us-east-1') { - params.CreateBucketConfiguration = { - LocationConstraint: region - }; - } - this.client.createBucket(params, (err, response) => { - callback(err, !err ? response : null); - }); + /** + * Wrapper of aws sdk api + * Function used to create s3 bucket + * @param {string} bucketName the name of bucket want to create + * @param {string} region aws region code + * @param {callback} callback { error, response } + */ + createBucket(bucketName, region, callback) { + const params = { + Bucket: bucketName, + }; + // us-east-1 is not a supported value for LocationConstraint property at aws apis + // should leave LocationConstraint empty when region code is us-east-1 + if (region && region !== "us-east-1") { + params.CreateBucketConfiguration = { + LocationConstraint: region, + }; } + this.client.createBucket(params, (err, response) => { + callback(err, !err ? response : null); + }); + } - /** - * Wrapper of aws sdk api - * Function used to determine if a bucket exists and user has permission to access it - * @param {string} bucketName bucket name - * @param {callback} callback { error, response } - */ - headBucket(bucketName, callback) { - const params = { - Bucket: bucketName - }; - this.client.headBucket(params, (err, response) => { - callback(err, !err ? response : null); - }); - } + /** + * Wrapper of aws sdk api + * Function used to determine if a bucket exists and user has permission to access it + * @param {string} bucketName bucket name + * @param {callback} callback { error, response } + */ + headBucket(bucketName, callback) { + const params = { + Bucket: bucketName, + }; + this.client.headBucket(params, (err, response) => { + callback(err, !err ? response : null); + }); + } - /** - * Wrapper of aws sdk api - * Function used to upload object to aws s3 bucket - * @param {string} bucket bucket name - * @param {string} key the name of uploaded content on s3 bucket - * @param {Object} body the content want to upload to s3 bucket - * @param {callback} callback { ETag, VersionId } - */ - putObject(bucket, key, body, callback) { - const params = { - Body: body, - Bucket: bucket, - Key: key - }; - this.client.putObject(params, (err, response) => { - callback(err, !err ? response : null); - }); - } + /** + * Wrapper of aws sdk api + * Function used to upload object to aws s3 bucket + * @param {string} bucket bucket name + * @param {string} key the name of uploaded content on s3 bucket + * @param {Object} body the content want to upload to s3 bucket + * @param {callback} callback { ETag, VersionId } + */ + putObject(bucket, key, body, callback) { + const params = { + Body: body, + Bucket: bucket, + Key: key, + }; + this.client.putObject(params, (err, response) => { + callback(err, !err ? response : null); + }); + } - /** - * Wait for s3 bucket exists - * @param {string} bucketName bucket name - * @param {callback} callback - */ - waitForBucketExists(bucketName, callback) { - const params = { - Bucket: bucketName - }; - this.client.waitFor('bucketExists', params, (err, response) => { - callback(err, !err ? response : null); - }); - } + /** + * Wait for s3 bucket exists + * @param {string} bucketName bucket name + * @param {callback} callback + */ + waitForBucketExists(bucketName, callback) { + const params = { + Bucket: bucketName, + }; + this.client.waitFor("bucketExists", params, (err, response) => { + callback(err, !err ? response : null); + }); + } - /** - * Function used to generate valid bucketName - * The bucket name should follow the pattern: ask-projectName-profileName-awsRegion-timeStamp - * a valid bucket name cannot longer than 63 characters, so cli fix the project name no longer than 22 characters - * and fix the profile name no longer than 9 characters - * @param {string} profile profile name - * @param {string} awsRegion aws region code, eg: us-east-1 - */ - static generateBucketName(profile, awsRegion) { - const projectName = path.basename(process.cwd()); - const validProjectName = projectName.toLowerCase().replace(/[^a-z0-9-.]+/g, '').substring(0, 22); - const validProfile = profile.toLowerCase().replace(/[^a-z0-9-.]+/g, '').substring(0, 9); - const shortRegionName = awsRegion.replace(/-/g, ''); - return `ask-${validProjectName}-${validProfile}-${shortRegionName}-${Date.now()}`; - } + /** + * Function used to generate valid bucketName + * The bucket name should follow the pattern: ask-projectName-profileName-awsRegion-timeStamp + * a valid bucket name cannot longer than 63 characters, so cli fix the project name no longer than 22 characters + * and fix the profile name no longer than 9 characters + * @param {string} profile profile name + * @param {string} awsRegion aws region code, eg: us-east-1 + */ + static generateBucketName(profile, awsRegion) { + const projectName = path.basename(process.cwd()); + const validProjectName = projectName + .toLowerCase() + .replace(/[^a-z0-9-.]+/g, "") + .substring(0, 22); + const validProfile = profile + .toLowerCase() + .replace(/[^a-z0-9-.]+/g, "") + .substring(0, 9); + const shortRegionName = awsRegion.replace(/-/g, ""); + return `ask-${validProjectName}-${validProfile}-${shortRegionName}-${Date.now()}`; + } - /** - * Implement the multipart upload to S3. Run upload in parallel for each part by using ParallelStream. - * - * @param {object} uploadPartsMap Mapping between partNumber and its eTag - * @param {string} filePath The file to upload - * @param {integer} totalSize Total size of the file - * @param {integer} partSize The size of each partition (the last part can be smaller then this) - * @param {integer} partsNumber The number of partitions of the file - * @param {callback} callback - */ - static multipartsUploadToPresignedUrls(uploadPartsMap, filePath, totalSize, partSize, partsNumber, callback) { - const progressSpinner = new SpinnerView(); + /** + * Implement the multipart upload to S3. Run upload in parallel for each part by using ParallelStream. + * + * @param {object} uploadPartsMap Mapping between partNumber and its eTag + * @param {string} filePath The file to upload + * @param {integer} totalSize Total size of the file + * @param {integer} partSize The size of each partition (the last part can be smaller then this) + * @param {integer} partsNumber The number of partitions of the file + * @param {callback} callback + */ + static multipartsUploadToPresignedUrls(uploadPartsMap, filePath, totalSize, partSize, partsNumber, callback) { + const progressSpinner = new SpinnerView(); - // Declarations of the state signals for the unordered stream upload - const partETagsList = []; - let partBuffer = []; - let partBufferTotalLength = 0; - let loadedPartCount = 0; - let loadedSize = 0; - let uploadedPartCount = 0; - let uploadedSize = 0; - const uploadTask = (chunk, enc, done) => { - // 1. Clear the partBuffer and append the rest (by slicing a partSize buffer) to the partBuffer - const aggregatedBuffer = Buffer.concat(partBuffer); - const rest = aggregatedBuffer.slice(partSize); - partBuffer = []; - partBuffer.push(rest); - partBufferTotalLength = rest.length; + // Declarations of the state signals for the unordered stream upload + const partETagsList = []; + let partBuffer = []; + let partBufferTotalLength = 0; + let loadedPartCount = 0; + let loadedSize = 0; + let uploadedPartCount = 0; + let uploadedSize = 0; + const uploadTask = (chunk, enc, done) => { + // 1. Clear the partBuffer and append the rest (by slicing a partSize buffer) to the partBuffer + const aggregatedBuffer = Buffer.concat(partBuffer); + const rest = aggregatedBuffer.slice(partSize); + partBuffer = []; + partBuffer.push(rest); + partBufferTotalLength = rest.length; - // 2. Upload by S3 presigned URL - // Need to store the part number for current "thread" to avoid wrong mapping for eTag and partNumber - const threadPartNum = ++loadedPartCount; - progressSpinner.update(` ${loadedPartCount}/${partsNumber} uploads have been requested. ` - + `Currently ${uploadedPartCount}/${partsNumber} parts and ${prettyBytes(uploadedSize)}/${prettyBytes(totalSize)} have been uploaded...`); - S3Client.preSignedPutObject( - uploadPartsMap.get(threadPartNum), - { body: aggregatedBuffer }, - (err, response) => { - if (err) { - return done(err); - } + // 2. Upload by S3 presigned URL + // Need to store the part number for current "thread" to avoid wrong mapping for eTag and partNumber + const threadPartNum = ++loadedPartCount; + progressSpinner.update( + ` ${loadedPartCount}/${partsNumber} uploads have been requested. ` + + `Currently ${uploadedPartCount}/${partsNumber} parts and ${prettyBytes(uploadedSize)}/${prettyBytes( + totalSize, + )} have been uploaded...`, + ); + S3Client.preSignedPutObject(uploadPartsMap.get(threadPartNum), {body: aggregatedBuffer}, (err, response) => { + if (err) { + return done(err); + } - // 3. Update uploaded parts state. - uploadedPartCount++; - uploadedSize += aggregatedBuffer.byteLength; - partETagsList.push({ - eTag: response.headers.etag, - partNumber: threadPartNum - }); + // 3. Update uploaded parts state. + uploadedPartCount++; + uploadedSize += aggregatedBuffer.byteLength; + partETagsList.push({ + eTag: response.headers.etag, + partNumber: threadPartNum, + }); - progressSpinner.update(` ${loadedPartCount}/${partsNumber} uploads have been requested. ` - + `Currently ${uploadedPartCount}/${partsNumber} parts ` - + `and ${prettyBytes(uploadedSize)}/${prettyBytes(totalSize)} have been uploaded...`); - done(); - } - ); - }; + progressSpinner.update( + ` ${loadedPartCount}/${partsNumber} uploads have been requested. ` + + `Currently ${uploadedPartCount}/${partsNumber} parts ` + + `and ${prettyBytes(uploadedSize)}/${prettyBytes(totalSize)} have been uploaded...`, + ); + done(); + }); + }; - const processStreamBuffer = (chunk) => { - // Process data whenever stream buffer is readable. Accumulate part and total length for the partBuffer - partBuffer.push(chunk); - partBufferTotalLength += chunk.byteLength; - loadedSize += chunk.byteLength; - }; + const processStreamBuffer = (chunk) => { + // Process data whenever stream buffer is readable. Accumulate part and total length for the partBuffer + partBuffer.push(chunk); + partBufferTotalLength += chunk.byteLength; + loadedSize += chunk.byteLength; + }; - const verifyAndFinish = () => { - progressSpinner.terminate(); - if (partETagsList.length !== partsNumber) { - callback(`[Error]: Multipart upload failed. There are ${partsNumber - partETagsList.length}` - + ` part(s) over ${partsNumber} parts not uploaded. Please try again!`); - return; - } - for (const element of partETagsList) { - const tmpETag = element.eTag; - if (typeof tmpETag !== 'string' || !tmpETag.trim()) { - callback(`[Error]: Failed to get the ETag for part number ${element.partNumber}. Please try again!`); - return; - } - } - callback(null, partETagsList); - }; + const verifyAndFinish = () => { + progressSpinner.terminate(); + if (partETagsList.length !== partsNumber) { + callback( + `[Error]: Multipart upload failed. There are ${partsNumber - partETagsList.length}` + + ` part(s) over ${partsNumber} parts not uploaded. Please try again!`, + ); + return; + } + for (const element of partETagsList) { + const tmpETag = element.eTag; + if (typeof tmpETag !== "string" || !tmpETag.trim()) { + callback(`[Error]: Failed to get the ETag for part number ${element.partNumber}. Please try again!`); + return; + } + } + callback(null, partETagsList); + }; - const parallelStreamOptions = { - willTransform: () => partBufferTotalLength >= partSize || (loadedPartCount === partsNumber - 1 && loadedSize === totalSize), - concurrency: CONSTANTS.CONFIGURATION.S3.MULTIPART_UPLOAD.CONCURRENCY, - isObjectMode: false, - }; + const parallelStreamOptions = { + willTransform: () => partBufferTotalLength >= partSize || (loadedPartCount === partsNumber - 1 && loadedSize === totalSize), + concurrency: CONSTANTS.CONFIGURATION.S3.MULTIPART_UPLOAD.CONCURRENCY, + isObjectMode: false, + }; - // Main stream processing - progressSpinner.start(); - fs.createReadStream(filePath) - .pipe(new ParallelStream(uploadTask, processStreamBuffer, verifyAndFinish, parallelStreamOptions)) - .on('error', (err) => { - callback(err); - }); - } + // Main stream processing + progressSpinner.start(); + fs.createReadStream(filePath) + .pipe(new ParallelStream(uploadTask, processStreamBuffer, verifyAndFinish, parallelStreamOptions)) + .on("error", (err) => { + callback(err); + }); + } - /** - * Retry logic to apply to GetBucketVersioning and PutBucketVersioning operations - * to mitigate S3 eventual consistency issues following a bucket creation - * @param {*} S3 response - */ - retryBucketVersionOperations(response) { - if (response.httpResponse.statusCode === 404 && response.error) { - response.error.retryable = true; - response.error.retryDelay = CONSTANTS.CONFIGURATION.S3.VERSIONING.NOT_FOUND_RETRY_DELAY_MS; - } + /** + * Retry logic to apply to GetBucketVersioning and PutBucketVersioning operations + * to mitigate S3 eventual consistency issues following a bucket creation + * @param {*} S3 response + */ + retryBucketVersionOperations(response) { + if (response.httpResponse.statusCode === 404 && response.error) { + response.error.retryable = true; + response.error.retryDelay = CONSTANTS.CONFIGURATION.S3.VERSIONING.NOT_FOUND_RETRY_DELAY_MS; } + } }; diff --git a/lib/clients/git-client.js b/lib/clients/git-client.js index 36afdc55..0bb92a3c 100644 --- a/lib/clients/git-client.js +++ b/lib/clients/git-client.js @@ -1,241 +1,244 @@ -const { execSync } = require('child_process'); -const fs = require('fs-extra'); -const path = require('path'); +const {execSync} = require("child_process"); +const fs = require("fs-extra"); +const path = require("path"); -const CLiError = require('@src/exceptions/cli-error'); -const Messenger = require('@src/view/messenger'); +const CLiError = require("../exceptions/cli-error"); +const Messenger = require("../view/messenger"); /** * Class for git commands management */ module.exports = class GitClient { - /** - * Constructor for GitClient with projectPath and verbosity options - * @param {string} projectPath the path of a project - * @param {object} verbosityOptions | showOutput - * | showCommand - */ - constructor(projectPath, verbosityOptions) { - this.projectPath = projectPath; - this.verbosityOptions = verbosityOptions; - } - - /** - * Execute git-init to create an empty Git repository or reinitialize an existing one - */ - init() { - const commands = [`git init "${this.projectPath}"${this.verbosityOptions.showOutput === false ? ' --quiet' : ''}`]; - const options = { - showStdOut: this.verbosityOptions.showOutput, - showStdErr: true, - showCmd: this.verbosityOptions.showCommand - }; - this._execCommands(commands, options); - } - - /** - * Config local git credential helper with credentialHelperPath - * @param {string} credentialScriptExecution the command to execute the git-credential-helper - * @param {string} hostUrl the host url to apply to the credential helper - */ - configureCredentialHelper(credentialScriptExecution, hostUrl) { - const commands = [ - `git config --local credential.${hostUrl}.helper ""`, - `git config --local --add credential.${hostUrl}.helper "!${credentialScriptExecution}"`, - `git config --local credential.${hostUrl}.UseHttpPath true`]; - const options = { - showStdOut: this.verbosityOptions.showOutput, - showStdErr: true, - showCmd: this.verbosityOptions.showCommand, - workingDir: this.projectPath - }; - this._execCommands(commands, options); - } - - /** - * Add a new remote in the directory your repository is stored at - * @param {String} repoUrl a remote url - */ - addOrigin(repoUrl) { - const commands = [`git remote add origin ${repoUrl}`]; - const options = { - showStdOut: this.verbosityOptions.showOutput, - showStdErr: true, - showCmd: this.verbosityOptions.showCommand, - workingDir: this.projectPath - }; - this._execCommands(commands, options); - } - - /** - * Execute git fetch to fetch all remotes - */ - fetchAll() { - const commands = [`git fetch --all${this.verbosityOptions.showOutput === false ? ' --quiet' : ''}`]; - const options = { - showStdOut: this.verbosityOptions.showOutput, - showStdErr: false, - showCmd: this.verbosityOptions.showCommand, - workingDir: this.projectPath - }; - this._execCommands(commands, options); - } - - /** - * Execute git checkout to switch branch or restore working tree files - * @param {string} branch the branch name - */ - checkoutBranch(branch) { - const commands = [`git checkout ${branch}${this.verbosityOptions.showOutput === false ? ' --quiet' : ''}`]; - const options = { - showStdOut: this.verbosityOptions.showOutput, - showStdErr: true, - showCmd: this.verbosityOptions.showCommand, - workingDir: this.projectPath - }; - this._execCommands(commands, options); - } - - /** - * Execute git clone to clone a repository into a new directory - * @param {string} cloneUrl the clone url - * @param {string} branch the branch name - * @param {string} folderName the directory folder name - */ - clone(cloneUrl, branch, folderName) { - const commands = [`git clone --branch ${branch} ${cloneUrl} "${folderName}" ${this.verbosityOptions.showOutput === false ? ' --quiet' : ''}`]; - const options = { - showStdOut: this.verbosityOptions.showOutput, - showStdErr: true, - showCmd: this.verbosityOptions.showCommand - }; - this._execCommands(commands, options); - } - - /** - * Set up or update a gitignore file - * @param {Array} filesToIgnore the list of files to ignore for git - */ - setupGitIgnore(filesToIgnore) { - const gitignorePath = path.join(this.projectPath, '.gitignore'); - if (fs.existsSync(gitignorePath) === false) { - fs.writeFileSync(gitignorePath, `${filesToIgnore.join('\n')}`); - } else { - const gitignoreFile = fs.readFileSync(gitignorePath).toString(); - filesToIgnore.forEach((file) => { - if (gitignoreFile.indexOf(file) === -1) { - fs.appendFileSync(gitignorePath, `\n${file}`); - } - }); + /** + * Constructor for GitClient with projectPath and verbosity options + * @param {string} projectPath the path of a project + * @param {object} verbosityOptions | showOutput + * | showCommand + */ + constructor(projectPath, verbosityOptions) { + this.projectPath = projectPath; + this.verbosityOptions = verbosityOptions; + } + + /** + * Execute git-init to create an empty Git repository or reinitialize an existing one + */ + init() { + const commands = [`git init "${this.projectPath}"${this.verbosityOptions.showOutput === false ? " --quiet" : ""}`]; + const options = { + showStdOut: this.verbosityOptions.showOutput, + showStdErr: true, + showCmd: this.verbosityOptions.showCommand, + }; + this._execCommands(commands, options); + } + + /** + * Config local git credential helper with credentialHelperPath + * @param {string} credentialScriptExecution the command to execute the git-credential-helper + * @param {string} hostUrl the host url to apply to the credential helper + */ + configureCredentialHelper(credentialScriptExecution, hostUrl) { + const commands = [ + `git config --local credential.${hostUrl}.helper ""`, + `git config --local --add credential.${hostUrl}.helper "!${credentialScriptExecution}"`, + `git config --local credential.${hostUrl}.UseHttpPath true`, + ]; + const options = { + showStdOut: this.verbosityOptions.showOutput, + showStdErr: true, + showCmd: this.verbosityOptions.showCommand, + workingDir: this.projectPath, + }; + this._execCommands(commands, options); + } + + /** + * Add a new remote in the directory your repository is stored at + * @param {String} repoUrl a remote url + */ + addOrigin(repoUrl) { + const commands = [`git remote add origin ${repoUrl}`]; + const options = { + showStdOut: this.verbosityOptions.showOutput, + showStdErr: true, + showCmd: this.verbosityOptions.showCommand, + workingDir: this.projectPath, + }; + this._execCommands(commands, options); + } + + /** + * Execute git fetch to fetch all remotes + */ + fetchAll() { + const commands = [`git fetch --all${this.verbosityOptions.showOutput === false ? " --quiet" : ""}`]; + const options = { + showStdOut: this.verbosityOptions.showOutput, + showStdErr: false, + showCmd: this.verbosityOptions.showCommand, + workingDir: this.projectPath, + }; + this._execCommands(commands, options); + } + + /** + * Execute git checkout to switch branch or restore working tree files + * @param {string} branch the branch name + */ + checkoutBranch(branch) { + const commands = [`git checkout ${branch}${this.verbosityOptions.showOutput === false ? " --quiet" : ""}`]; + const options = { + showStdOut: this.verbosityOptions.showOutput, + showStdErr: true, + showCmd: this.verbosityOptions.showCommand, + workingDir: this.projectPath, + }; + this._execCommands(commands, options); + } + + /** + * Execute git clone to clone a repository into a new directory + * @param {string} cloneUrl the clone url + * @param {string} branch the branch name + * @param {string} folderName the directory folder name + */ + clone(cloneUrl, branch, folderName) { + const commands = [ + `git clone --branch ${branch} ${cloneUrl} "${folderName}" ${this.verbosityOptions.showOutput === false ? " --quiet" : ""}`, + ]; + const options = { + showStdOut: this.verbosityOptions.showOutput, + showStdErr: true, + showCmd: this.verbosityOptions.showCommand, + }; + this._execCommands(commands, options); + } + + /** + * Set up or update a gitignore file + * @param {Array} filesToIgnore the list of files to ignore for git + */ + setupGitIgnore(filesToIgnore) { + const gitignorePath = path.join(this.projectPath, ".gitignore"); + if (fs.existsSync(gitignorePath) === false) { + fs.writeFileSync(gitignorePath, `${filesToIgnore.join("\n")}`); + } else { + const gitignoreFile = fs.readFileSync(gitignorePath).toString(); + filesToIgnore.forEach((file) => { + if (gitignoreFile.indexOf(file) === -1) { + fs.appendFileSync(gitignorePath, `\n${file}`); } - this.add('.gitignore'); + }); } - - /** - * Execute git add to add file contents to the index - * @param {string} file the file to add content from - */ - add(file) { - const commands = [`git add "${file}"`]; - const options = { - showStdOut: this.verbosityOptions.showOutput, - showStdErr: true, - showCmd: this.verbosityOptions.showCommand, - workingDir: this.projectPath - }; - this._execCommands(commands, options); - } - - /** - * Execute git delete to delete a local branch - * @param {string} file the file to add content from - */ - deleteBranch(branch) { - const commands = [`git branch -d ${branch}`]; - const options = { - showStdOut: this.verbosityOptions.showOutput, - showStdErr: true, - showCmd: this.verbosityOptions.showCommand - }; - this._execCommands(commands, options); + this.add(".gitignore"); + } + + /** + * Execute git add to add file contents to the index + * @param {string} file the file to add content from + */ + add(file) { + const commands = [`git add "${file}"`]; + const options = { + showStdOut: this.verbosityOptions.showOutput, + showStdErr: true, + showCmd: this.verbosityOptions.showCommand, + workingDir: this.projectPath, + }; + this._execCommands(commands, options); + } + + /** + * Execute git delete to delete a local branch + * @param {string} file the file to add content from + */ + deleteBranch(branch) { + const commands = [`git branch -d ${branch}`]; + const options = { + showStdOut: this.verbosityOptions.showOutput, + showStdErr: true, + showCmd: this.verbosityOptions.showCommand, + }; + this._execCommands(commands, options); + } + + /** + * Execute git merge to join two development histories together + * @param {String} branch the development branch + */ + merge(branch) { + const commands = [`git merge ${branch}`]; + const options = { + showStdOut: this.verbosityOptions.showOutput, + showStdErr: true, + showCmd: this.verbosityOptions.showCommand, + }; + this._execCommands(commands, options); + } + + /** + * Execute git status to show the working tree status in short-format + * @param {callback} callback { error } + */ + shortStatus() { + const command = "git status -s"; + const options = { + showStdOut: this.verbosityOptions.showOutput, + showStdErr: true, + showCmd: this.verbosityOptions.showCommand, + }; + try { + return this._execChildProcessSync(command, options); + } catch (ex) { + throw new CLiError(`${ex}`); } - - /** - * Execute git merge to join two development histories together - * @param {String} branch the development branch - */ - merge(branch) { - const commands = [`git merge ${branch}`]; - const options = { - showStdOut: this.verbosityOptions.showOutput, - showStdErr: true, - showCmd: this.verbosityOptions.showCommand - }; - this._execCommands(commands, options); - } - - /** - * Execute git status to show the working tree status in short-format - * @param {callback} callback { error } - */ - shortStatus() { - const command = 'git status -s'; - const options = { - showStdOut: this.verbosityOptions.showOutput, - showStdErr: true, - showCmd: this.verbosityOptions.showCommand - }; - try { - return this._execChildProcessSync(command, options); - } catch (ex) { - throw new CLiError(`${ex}`); - } + } + + /** + * Execute git rev-list to count the list of commit objects + * @param {String} commit1 the first commit + * @param {String} commit2 the second commit + * @param {callback} callback { error } + */ + countCommitDifference(commit1, commit2) { + const command = `git rev-list --count ${commit1}...${commit2}`; + const options = { + showStdOut: this.verbosityOptions.showOutput, + showStdErr: true, + showCmd: this.verbosityOptions.showCommand, + workingDir: this.projectPath, + }; + try { + return this._execChildProcessSync(command, options); + } catch (ex) { + throw new CLiError(`${ex}`); } - - /** - * Execute git rev-list to count the list of commit objects - * @param {String} commit1 the first commit - * @param {String} commit2 the second commit - * @param {callback} callback { error } - */ - countCommitDifference(commit1, commit2) { - const command = `git rev-list --count ${commit1}...${commit2}`; - const options = { - showStdOut: this.verbosityOptions.showOutput, - showStdErr: true, - showCmd: this.verbosityOptions.showCommand, - workingDir: this.projectPath - }; - try { - return this._execChildProcessSync(command, options); - } catch (ex) { - throw new CLiError(`${ex}`); - } + } + + _execCommands(commands, options) { + for (const command of commands) { + try { + this._execChildProcessSync(command, options); + } catch (ex) { + throw new CLiError(`${ex}`); + } } - - _execCommands(commands, options) { - for (const command of commands) { - try { - this._execChildProcessSync(command, options); - } catch (ex) { - throw new CLiError(`${ex}`); - } - } + } + + _execChildProcessSync(command, options) { + const {showOutput, showStdErr, showCommand, workingDir} = options; + const execOptions = { + stdio: [null, showOutput ? 1 : null, showStdErr ? 2 : null], + shell: true, + windowsHide: true, + }; + if (workingDir) { + execOptions.cwd = options.workingDir; } - - _execChildProcessSync(command, options) { - const { showOutput, showStdErr, showCommand, workingDir } = options; - const execOptions = { - stdio: [null, showOutput ? 1 : null, showStdErr ? 2 : null], - shell: true, - windowsHide: true - }; - if (workingDir) { - execOptions.cwd = options.workingDir; - } - if (showCommand) { - Messenger.getInstance().info(command); - } - return execSync(command, execOptions); + if (showCommand) { + Messenger.getInstance().info(command); } + return execSync(command, execOptions); + } }; diff --git a/lib/clients/http-client.js b/lib/clients/http-client.js index ab9098ec..f9c51e0a 100644 --- a/lib/clients/http-client.js +++ b/lib/clients/http-client.js @@ -1,15 +1,15 @@ -const R = require('ramda'); -const requestLib = require('request'); +const R = require("ramda"); +const requestLib = require("request"); -const DynamicConfig = require('@src/utils/dynamic-config'); -const logger = require('@src/utils/logger-utility'); -const urlUtils = require('@src/utils/url-utils'); -const stringUtils = require('@src/utils/string-utils'); -const CONSTANTS = require('@src/utils/constants'); +const DynamicConfig = require("../utils/dynamic-config"); +const logger = require("../utils/logger-utility"); +const urlUtils = require("../utils/url-utils"); +const stringUtils = require("../utils/string-utils"); +const CONSTANTS = require("../utils/constants"); module.exports = { - request, - putByUrl + request, + putByUrl, }; /** @@ -21,48 +21,48 @@ module.exports = { * @param {function} callback */ function request(options, operation, doDebug, callback) { - // Validation of input parameters - const requestOptions = R.clone(options); - if (typeof operation !== 'string' || !operation.trim()) { - process.nextTick(() => { - callback('[Fatal]: CLI request must have a non-empty operation name.'); - }); - return; + // Validation of input parameters + const requestOptions = R.clone(options); + if (typeof operation !== "string" || !operation.trim()) { + process.nextTick(() => { + callback("[Fatal]: CLI request must have a non-empty operation name."); + }); + return; + } + if (!urlUtils.isValidUrl(requestOptions.url)) { + process.nextTick(() => { + callback(`[Fatal]: Invalid URL:${requestOptions.url}. CLI request must call with valid url.`); + }); + return; + } + + const proxyUrl = process.env.ASK_CLI_PROXY; + if (stringUtils.isNonBlankString(proxyUrl)) { + requestOptions.proxy = proxyUrl; + } + + // Set user-agent for each CLI request + if (!requestOptions.headers) { + requestOptions.headers = {}; + } + requestOptions.headers["User-Agent"] = DynamicConfig.userAgent; + + // Make request + requestLib(requestOptions, (error, response) => { + if (doDebug) { + logger.getInstance().debug(debugContentForResponse(operation, error, response)); } - if (!urlUtils.isValidUrl(requestOptions.url)) { - process.nextTick(() => { - callback(`[Fatal]: Invalid URL:${requestOptions.url}. CLI request must call with valid url.`); - }); - return; + if (error) { + return callback(`Failed to make request to ${operation}.\nError response: ${error}`); } - - const proxyUrl = process.env.ASK_CLI_PROXY; - if (stringUtils.isNonBlankString(proxyUrl)) { - requestOptions.proxy = proxyUrl; + if (!response) { + return callback(`Failed to make request to ${operation}.\nPlease make sure "${requestOptions.url}" is responding.`); } - - // Set user-agent for each CLI request - if (!requestOptions.headers) { - requestOptions.headers = {}; + if (!response.statusCode) { + return callback(`Failed to access the statusCode from the request to ${operation}.`); } - requestOptions.headers['User-Agent'] = DynamicConfig.userAgent; - - // Make request - requestLib(requestOptions, (error, response) => { - if (doDebug) { - logger.getInstance().debug(debugContentForResponse(operation, error, response)); - } - if (error) { - return callback(`Failed to make request to ${operation}.\nError response: ${error}`); - } - if (!response) { - return callback(`Failed to make request to ${operation}.\nPlease make sure "${requestOptions.url}" is responding.`); - } - if (!response.statusCode) { - return callback(`Failed to access the statusCode from the request to ${operation}.`); - } - return callback(null, response); - }); + return callback(null, response); + }); } /** @@ -74,15 +74,15 @@ function request(options, operation, doDebug, callback) { * @param {Function} callback */ function putByUrl(url, payload, operation, doDebug, callback) { - const options = { - url, - method: CONSTANTS.HTTP_REQUEST.VERB.PUT, - headers: {}, - body: payload - }; - request(options, operation, doDebug, (reqErr, reqResponse) => { - callback(reqErr, reqResponse); - }); + const options = { + url, + method: CONSTANTS.HTTP_REQUEST.VERB.PUT, + headers: {}, + body: payload, + }; + request(options, operation, doDebug, (reqErr, reqResponse) => { + callback(reqErr, reqResponse); + }); } /** @@ -92,21 +92,21 @@ function putByUrl(url, payload, operation, doDebug, callback) { * @param {object} response */ function debugContentForResponse(operation, error, response) { - return { - activity: operation, - error, - 'request-id': response.headers['x-amzn-requestid'] || null, - request: { - method: response.request.method, - url: response.request.href, - headers: response.request.headers, - body: response.request.body - }, - response: { - statusCode: response.statusCode, - statusMessage: response.statusMessage, - headers: response.headers - }, - body: response.body - }; + return { + activity: operation, + error, + "request-id": response.headers["x-amzn-requestid"] || null, + request: { + method: response.request.method, + url: response.request.href, + headers: response.request.headers, + body: response.request.body, + }, + response: { + statusCode: response.statusCode, + statusMessage: response.statusMessage, + headers: response.headers, + }, + body: response.body, + }; } diff --git a/lib/clients/lwa-auth-code-client/index.js b/lib/clients/lwa-auth-code-client/index.js index 605fa403..6753f0cc 100644 --- a/lib/clients/lwa-auth-code-client/index.js +++ b/lib/clients/lwa-auth-code-client/index.js @@ -1,144 +1,144 @@ -const R = require('ramda'); -const { URL } = require('url'); -const queryString = require('querystring'); -const addSeconds = require('date-fns/addSeconds'); -const isAfter = require('date-fns/isAfter'); -const parseISO = require('date-fns/parseISO'); +const R = require("ramda"); +const {URL} = require("url"); +const queryString = require("querystring"); +const addSeconds = require("date-fns/addSeconds"); +const isAfter = require("date-fns/isAfter"); +const parseISO = require("date-fns/parseISO"); -const httpClient = require('@src/clients/http-client'); -const CONSTANTS = require('@src/utils/constants'); -const DynamicConfig = require('@src/utils/dynamic-config'); -const stringUtils = require('@src/utils/string-utils'); -const jsonView = require('@src/view/json-view'); -const CliError = require('@src/exceptions/cli-error'); +const httpClient = require("../../clients/http-client"); +const CONSTANTS = require("../../utils/constants"); +const DynamicConfig = require("../../utils/dynamic-config"); +const stringUtils = require("../../utils/string-utils"); +const jsonView = require("../../view/json-view"); +const CliError = require("../../exceptions/cli-error"); module.exports = class LWAAuthCodeClient { - constructor(config) { - this.config = this._handleDefaultLwaAuthCodeConfiguration(config); - } + constructor(config) { + this.config = this._handleDefaultLwaAuthCodeConfiguration(config); + } - /** - * @param {String} authCode | used for fetching accessTokens - * @param {Function} callback (err, accessToken) - * @returns accessToken | Used for request validation in skill development process. - */ - getAccessTokenUsingAuthCode(authCode, callback) { - const url = new URL(this.config.tokenPath, this.config.tokenHost); - const body = { - grant_type: 'authorization_code', - redirect_uri: this.config.redirectUri, - client_id: this.config.clientId, - client_secret: this.config.clientConfirmation, - code: authCode - }; - const options = { - url: `${url}`, - method: 'POST', - body, - json: !!body - }; - httpClient.request(options, 'GET_ACCESS_TOKEN', this.config.doDebug, (err, response) => { - if (err) { - return callback(err); - } - const tokenBody = R.clone(response.body); - if (tokenBody.error) { - return callback(new CliError(tokenBody.error)); - } - tokenBody.expires_at = this._getExpiresAt(tokenBody.expires_in).toISOString(); - callback(null, tokenBody); - }); - } + /** + * @param {String} authCode | used for fetching accessTokens + * @param {Function} callback (err, accessToken) + * @returns accessToken | Used for request validation in skill development process. + */ + getAccessTokenUsingAuthCode(authCode, callback) { + const url = new URL(this.config.tokenPath, this.config.tokenHost); + const body = { + grant_type: "authorization_code", + redirect_uri: this.config.redirectUri, + client_id: this.config.clientId, + client_secret: this.config.clientConfirmation, + code: authCode, + }; + const options = { + url: `${url}`, + method: "POST", + body, + json: !!body, + }; + httpClient.request(options, "GET_ACCESS_TOKEN", this.config.doDebug, (err, response) => { + if (err) { + return callback(err); + } + const tokenBody = R.clone(response.body); + if (tokenBody.error) { + return callback(new CliError(tokenBody.error)); + } + tokenBody.expires_at = this._getExpiresAt(tokenBody.expires_in).toISOString(); + callback(null, tokenBody); + }); + } - /** - * @param {Object} token | accessToken of the profile being used currently. - * @param {Function} callback (err, token) - * @returns accessToken | a new access token. - */ - refreshToken(token, callback) { - const url = new URL(this.config.tokenPath, this.config.tokenHost); - const body = { - grant_type: 'refresh_token', - refresh_token: token.refresh_token, - client_id: this.config.clientId, - client_secret: this.config.clientConfirmation - }; - const options = { - url: `${url}`, - method: 'POST', - body, - json: !!body - }; - httpClient.request(options, 'GET_ACCESS_TOKEN_USING_REFRESH_TOKEN', this.config.doDebug, (err, response) => { - if (err) { - return callback(err); - } - const responseErr = R.view(R.lensPath(['body', 'error']), response); - if (stringUtils.isNonBlankString(responseErr)) { - return callback(`Refresh LWA tokens failed, please run "ask configure" to manually update your tokens. Error: ${responseErr}.`); - } - const expiresIn = R.view(R.lensPath(['body', 'expires_in']), response); - if (!expiresIn) { - return callback(`Received invalid response body from LWA without "expires_in":\n${jsonView.toString(response.body)}`); - } + /** + * @param {Object} token | accessToken of the profile being used currently. + * @param {Function} callback (err, token) + * @returns accessToken | a new access token. + */ + refreshToken(token, callback) { + const url = new URL(this.config.tokenPath, this.config.tokenHost); + const body = { + grant_type: "refresh_token", + refresh_token: token.refresh_token, + client_id: this.config.clientId, + client_secret: this.config.clientConfirmation, + }; + const options = { + url: `${url}`, + method: "POST", + body, + json: !!body, + }; + httpClient.request(options, "GET_ACCESS_TOKEN_USING_REFRESH_TOKEN", this.config.doDebug, (err, response) => { + if (err) { + return callback(err); + } + const responseErr = R.view(R.lensPath(["body", "error"]), response); + if (stringUtils.isNonBlankString(responseErr)) { + return callback(`Refresh LWA tokens failed, please run "ask configure" to manually update your tokens. Error: ${responseErr}.`); + } + const expiresIn = R.view(R.lensPath(["body", "expires_in"]), response); + if (!expiresIn) { + return callback(`Received invalid response body from LWA without "expires_in":\n${jsonView.toString(response.body)}`); + } - const tokenBody = R.clone(response.body); - if (tokenBody.error) { - return callback(new CliError(tokenBody.error)); - } - tokenBody.expires_at = this._getExpiresAt(expiresIn).toISOString(); - callback(null, tokenBody); - }); - } + const tokenBody = R.clone(response.body); + if (tokenBody.error) { + return callback(new CliError(tokenBody.error)); + } + tokenBody.expires_at = this._getExpiresAt(expiresIn).toISOString(); + callback(null, tokenBody); + }); + } - /** - * @param {Object} token - * @returns boolean | checks validity of a given token - */ - isValidToken(token) { - return !isAfter(new Date(), parseISO(token.expires_at)); - } + /** + * @param {Object} token + * @returns boolean | checks validity of a given token + */ + isValidToken(token) { + return !isAfter(new Date(), parseISO(token.expires_at)); + } - /** - * @returns {String} authorization code URL - */ - generateAuthorizeUrl() { - const queryParams = { - response_type: 'code', - client_id: this.config.clientId, - state: this.config.state - }; - if (stringUtils.isNonBlankString(this.config.scope)) { - queryParams.scope = this.config.scope; - } - if (stringUtils.isNonBlankString(this.config.redirectUri)) { - queryParams.redirect_uri = this.config.redirectUri; - } - const baseUrl = new URL(this.config.authorizePath, this.config.authorizeHost); - return `${baseUrl}?${queryString.stringify(queryParams)}`; + /** + * @returns {String} authorization code URL + */ + generateAuthorizeUrl() { + const queryParams = { + response_type: "code", + client_id: this.config.clientId, + state: this.config.state, + }; + if (stringUtils.isNonBlankString(this.config.scope)) { + queryParams.scope = this.config.scope; } + if (stringUtils.isNonBlankString(this.config.redirectUri)) { + queryParams.redirect_uri = this.config.redirectUri; + } + const baseUrl = new URL(this.config.authorizePath, this.config.authorizeHost); + return `${baseUrl}?${queryString.stringify(queryParams)}`; + } - /** - * @param {Object} authConfig - * @returns {Object} config | sets default values if some of the values are missing. - * @private - */ - _handleDefaultLwaAuthCodeConfiguration(authConfig) { - const { doDebug, redirectUri } = authConfig; - const authorizePath = CONSTANTS.LWA.DEFAULT_AUTHORIZE_PATH; - const tokenPath = CONSTANTS.LWA.DEFAULT_TOKEN_PATH; + /** + * @param {Object} authConfig + * @returns {Object} config | sets default values if some of the values are missing. + * @private + */ + _handleDefaultLwaAuthCodeConfiguration(authConfig) { + const {doDebug, redirectUri} = authConfig; + const authorizePath = CONSTANTS.LWA.DEFAULT_AUTHORIZE_PATH; + const tokenPath = CONSTANTS.LWA.DEFAULT_TOKEN_PATH; - // Overwrite LWA options from Environmental Variable - const state = authConfig.state || Date.now(); - const scope = authConfig.scope || CONSTANTS.LWA.DEFAULT_SCOPES; - const clientId = authConfig.clientId || DynamicConfig.lwaClientId; - const clientConfirmation = authConfig.clientConfirmation || DynamicConfig.lwaClientConfirmation; - const authorizeHost = DynamicConfig.lwaAuthorizationHost; - const tokenHost = DynamicConfig.lwaTokenHost; - return { clientId, clientConfirmation, authorizeHost, tokenHost, authorizePath, tokenPath, scope, state, redirectUri, doDebug }; - } + // Overwrite LWA options from Environmental Variable + const state = authConfig.state || Date.now(); + const scope = authConfig.scope || CONSTANTS.LWA.DEFAULT_SCOPES; + const clientId = authConfig.clientId || DynamicConfig.lwaClientId; + const clientConfirmation = authConfig.clientConfirmation || DynamicConfig.lwaClientConfirmation; + const authorizeHost = DynamicConfig.lwaAuthorizationHost; + const tokenHost = DynamicConfig.lwaTokenHost; + return {clientId, clientConfirmation, authorizeHost, tokenHost, authorizePath, tokenPath, scope, state, redirectUri, doDebug}; + } - _getExpiresAt(expiresIn) { - return addSeconds(new Date(), Number.parseInt(expiresIn, 10)); - } + _getExpiresAt(expiresIn) { + return addSeconds(new Date(), Number.parseInt(expiresIn, 10)); + } }; diff --git a/lib/clients/metric-client/index.js b/lib/clients/metric-client/index.js deleted file mode 100644 index 32c20b21..00000000 --- a/lib/clients/metric-client/index.js +++ /dev/null @@ -1,175 +0,0 @@ -const uuid = require('uuid/v4'); -const axios = require('axios'); -const AppConfig = require('@src/model/app-config'); -const profileHelper = require('@src/utils/profile-helper'); -const { METRICS } = require('@src/utils/constants'); -const pck = require('../../../package.json'); - -const MetricActionResult = { - SUCCESS: 'Success', - FAILURE: 'Failure' -}; - -class MetricAction { - /** - * @constructor - * @param {string} name - The action name. - * @param {string} type - The action type. - */ - constructor(name, type) { - this.endTime = null; - this.failureMessage = ''; - this.name = name; - this.result = null; - this.startTime = new Date(); - this.type = type; - this.id = uuid(); - this._ended = false; - } - - /** - * Closes action - * @param {Error|string} [error=null] error - Error object or string indicating error. - */ - end(error = null) { - if (this._ended) return; - - // if Error object extract error message, - // otherwise error message string or null was passed as a parameter - const errorMessage = error && error instanceof Error ? error.message : error; - - this.result = errorMessage ? MetricActionResult.FAILURE : MetricActionResult.SUCCESS; - this.failureMessage = errorMessage || ''; - this.endTime = new Date(); - this._ended = true; - } - - /** - * Implementation of custom toJSON method to modify serialization with JSON.stringify - */ - toJSON() { - return { - end_time: this.endTime, - failure_message: this.failureMessage, - name: this.name, - result: this.result, - start_time: this.startTime, - type: this.type, - id: this.id - }; - } -} - -class MetricClient { - /** - * @constructor - */ - constructor() { - this.httpClient = axios.create({ - timeout: 3000, - headers: { 'Content-Type': 'text/plain' } - }); - this.serverUrl = METRICS.ENDPOINT; - this.postRetries = 3; - - this.enabled = this._isEnabled(); - this.data = { - version: pck.version, - machineId: this._getMachineId(), - timeStarted: new Date(), - newUser: false, // default to false since unused. - timeUploaded: null, - clientId: pck.name, - actions: [] - }; - } - - /** - * Starts action - * @param {string} name - The action name - * @param {string} type - The action type - * @return {MetricAction} - */ - startAction(name, type) { - const action = new MetricAction(name, type); - this.data.actions.push(action); - return action; - } - - /** - * Returns current data store in the metric client - * @return {{version: string, machineId: string, timeStarted: Date, - * newUser: boolean, timeUploaded: Date|null, clientId: string, actions: MetricAction[]}} - */ - getData() { - return this.data; - } - - /** - * Sends data to the metric server - * @param {Error|string} [error=null] error - Error object or string indicating error. - * @returns {Promise<{success: boolean}>} - */ - sendData(error = null) { - if (!this.enabled) { - this.data.actions = []; - return new Promise(resolve => resolve({ success: true })); - } - this.data.actions.forEach(action => action.end(error)); - return this._upload() - .then(() => { - this.data.actions = []; - return { success: true }; - }) - .catch(() => ({ success: false })); - } - - /** - * Implementation of custom toJSON method to modify serialization with JSON.stringify - */ - toJSON() { - return { - version: this.data.version, - machine_id: this.data.machineId, - time_started: this.data.timeStarted, - new_user: this.data.newUser, - time_uploaded: this.data.timeUploaded, - client_id: this.data.clientId, - actions: this.data.actions - }; - } - - _upload() { - this.data.timeUploaded = new Date(); - const payload = JSON.stringify({ payload: this }); - const postPromise = () => this.httpClient.post(this.serverUrl, payload); - return this._retry(this.postRetries, postPromise); - } - - _retry(retries, fn) { - return fn().catch(err => (retries > 1 ? this._retry(retries - 1, fn) : Promise.reject(err))); - } - - _isEnabled() { - if (profileHelper.isEnvProfile()) return true; - if (process.env.ASK_SHARE_USAGE === 'false') return false; - if (!AppConfig.configFileExists()) return false; - - new AppConfig(); - return AppConfig.getInstance().getShareUsage(); - } - - _getMachineId() { - if (!this.enabled) return; - if (profileHelper.isEnvProfile()) return 'all_environmental'; - const appConfig = AppConfig.getInstance(); - if (!appConfig.getMachineId()) { - appConfig.setMachineId(uuid()); - appConfig.write(); - } - - return appConfig.getMachineId(); - } -} - -module.exports = { MetricClient, MetricActionResult }; diff --git a/lib/clients/metric-client/index.ts b/lib/clients/metric-client/index.ts new file mode 100644 index 00000000..04879e80 --- /dev/null +++ b/lib/clients/metric-client/index.ts @@ -0,0 +1,247 @@ +import {v4 as uuid} from "uuid"; +import axios, {AxiosInstance} from "axios"; +import AppConfig from "../../model/app-config"; +import profileHelper from "../../utils/profile-helper"; +import {METRICS} from "../../utils/constants"; +import pck from "../../../package.json"; + +export const MetricActionResult: {[RESULT: string]: string} = { + SUCCESS: "Success", + FAILURE: "Failure", +}; + +/** + * Metric action includes the name and results of CLI command. + */ +export class MetricAction { + name: string; + type: string; + startTime: Date; + endTime: Date | null; + result: string | null; + failureMessage: string; + id: string; + _ended: boolean; + options: string[]; + optionData: {[key: string]: string}; + + /** + * @constructor + * @param name - The action name. + * @param type - The action type. + */ + constructor(name: string, type: string) { + this.endTime = null; + this.failureMessage = ""; + this.name = name; + this.result = null; + this.startTime = new Date(); + this.type = type; + this.id = uuid(); + this.options = []; + this.optionData = {}; + + this._ended = false; + } + + /** + * Add option to list, store value only if in {@link METRICS.STOREABLE_KEYS} + * @param optionName name of the option + * @param optionValue value of the option + */ + setOption(optionName: string, optionValue: string) { + const schemaOption = optionName.split("-").join("_"); + this.options.push(schemaOption); + + if (METRICS.STOREABLE_KEYS.includes(schemaOption)) { + this.optionData[schemaOption] = optionValue; + } + } + + /** + * Closes action + * @param error Error object or string indicating error. + */ + end(error: Error | string | null = null) { + if (this._ended) return; + + // if Error object extract error message, + // otherwise error message string or null was passed as a parameter + const errorMessage = error && error instanceof Error ? error.message : error; + + this.result = errorMessage ? MetricActionResult.FAILURE : MetricActionResult.SUCCESS; + this.failureMessage = errorMessage || ""; + this.endTime = new Date(); + this._ended = true; + } + + /** + * Implementation of custom toJSON method to modify serialization with JSON.stringify + */ + toJSON() { + return { + end_time: this.endTime, + failure_message: this.failureMessage, + name: this.name, + result: this.result, + start_time: this.startTime, + type: this.type, + id: this.id, + options: this.options, + ...this.optionData, + }; + } +} + +/** + * Describes the telemetry data sent by the metric client. + */ +interface MetricClientData { + version: string; + machineId: string; + timeStarted: Date; + newUser: boolean; + timeUploaded: Date | null; + clientId: string; + actions: MetricAction[]; +} + +/** + * Client that communicates with telemetry endpoint. + */ +export class MetricClient { + httpClient: AxiosInstance; + serverUrl: string; + postRetries: number; + enabled: boolean; + data: MetricClientData; + + /** + * @constructor + */ + constructor() { + this.httpClient = axios.create({ + timeout: 3000, + headers: {"Content-Type": "text/plain"}, + }); + this.serverUrl = METRICS.ENDPOINT; + this.postRetries = 3; + + this.enabled = this._isEnabled(); + + // initialize data + this.data = { + version: pck.version, + machineId: this._getMachineId(), + timeStarted: new Date(), + newUser: false, // default to false since unused. + timeUploaded: null, + clientId: pck.name, + actions: [], + }; + } + + /** + * Starts action + * @param name - The action name + * @param type - The action type + * @return the metric action that was started, {@link MetricAction} + */ + startAction(name: string, type: string): MetricAction { + const action: MetricAction = new MetricAction(name, type); + this.data.actions.push(action); + return action; + } + + /** + * Set option for the most recently started action + * @param optionName name of the option + * @param optionValue value of the option + */ + setOption(optionName: string, optionValue: string) { + const actions = this.data.actions; + if (actions.length) { + actions[actions.length - 1].setOption(optionName, optionValue); + } + } + + /** + * Returns current data store in the metric client + * @return the metric data, {@link MetricClientData} + */ + getData(): MetricClientData { + return this.data; + } + + /** + * Sends data to the metric server + * @param error - Error object or string indicating error. + * @returns whether data was sent successfully + */ + async sendData(error: Error | string | null = null): Promise<{success: boolean}> { + if (!this.enabled) { + this.data.actions = []; + return {success: true}; + } + this.data.actions.forEach((action) => action.end(error)); + try { + await this._upload(); + this.data.actions = []; + return {success: true}; + } catch { + return {success: false}; + } + } + + /** + * Implementation of custom toJSON method to modify serialization with JSON.stringify + */ + toJSON() { + return { + version: this.data.version, + machine_id: this.data.machineId, + time_started: this.data.timeStarted, + new_user: this.data.newUser, + time_uploaded: this.data.timeUploaded, + client_id: this.data.clientId, + actions: this.data.actions, + }; + } + + async _upload(): Promise { + this.data.timeUploaded = new Date(); + const payload = JSON.stringify({payload: this}); + const postPromise = () => this.httpClient.post(this.serverUrl, payload); + await this._retry(this.postRetries, postPromise); + } + + async _retry(retries: number, func: any): Promise { + try { + await func(); + } catch (error: any) { + if (retries == 1) throw error; + await this._retry(retries - 1, func); + } + } + + _isEnabled(): boolean { + if (profileHelper.isEnvProfile()) return true; + if (process.env.ASK_SHARE_USAGE === "false") return false; + if (!AppConfig.configFileExists()) return false; + + new AppConfig(); + return AppConfig.getInstance().getShareUsage(); + } + + _getMachineId(): string { + if (!this.enabled) return ""; + if (profileHelper.isEnvProfile()) return "all_environmental"; + const appConfig = AppConfig.getInstance(); + if (!appConfig.getMachineId()) { + appConfig.setMachineId(uuid()); + appConfig.write(); + } + + return appConfig.getMachineId(); + } +} diff --git a/lib/clients/smapi-client/index.js b/lib/clients/smapi-client/index.js deleted file mode 100644 index 799bab5d..00000000 --- a/lib/clients/smapi-client/index.js +++ /dev/null @@ -1,231 +0,0 @@ -const R = require('ramda'); -const async = require('async'); -const querystring = require('querystring'); -const AuthorizationController = require('@src/controllers/authorization-controller'); -const DynamicConfig = require('@src/utils/dynamic-config'); -const httpClient = require('@src/clients/http-client'); -const CONSTANTS = require('@src/utils/constants'); - -const accountLinkingApi = require('./resources/account-linking'); -const catalogApi = require('./resources/catalog'); -const historyApi = require('./resources/history'); -const ispApi = require('./resources/isp'); -const manifestApi = require('./resources/manifest'); -const interactionModelApi = require('./resources/interaction-model'); -const privateSkillApi = require('./resources/private-skill'); -const skillPackageApi = require('./resources/skill-package'); -const skillApi = require('./resources/skill'); -const testApi = require('./resources/test'); -const vendorApi = require('./resources/vendor'); -const evaluationsApi = require('./resources/evaluations'); -const alexaHostedApi = require('./resources/alexa-hosted'); -const betaTestApi = require('./resources/beta-test'); -const publishingApi = require('./resources/publishing'); -const taskApi = require('./resources/task'); - -const JSON_PROPERTIES = ['_links']; - -/** - * Class for Alexa Skill Management API Service (SMAPI) client - */ -module.exports = class SmapiClient { - /** - * Constructor for SmapiClient with "profile" for authorization and "doDebug" for client setting - * @param {object} configuration | profile - * | doDebug - */ - constructor(configuration) { - this.profile = configuration.profile; - this.doDebug = configuration.doDebug; - this._smapiRequest = this._smapiRequest.bind(this); - this.smapiRedirectRequestWithUrl = this.smapiRedirectRequestWithUrl.bind(this); - this.listWithAutoPagination = this.listWithAutoPagination.bind(this); - - this.skill = skillApi(this._smapiRequest); - this.skill.manifest = manifestApi(this._smapiRequest); - this.skill.interactionModel = interactionModelApi(this._smapiRequest); - this.skill.accountLinking = accountLinkingApi(this._smapiRequest); - this.skill.privateSkill = privateSkillApi(this._smapiRequest); - this.skill.history = historyApi(this._smapiRequest); - this.skill.test = testApi(this._smapiRequest); - this.skill.evaluations = evaluationsApi(this._smapiRequest); - this.skill.alexaHosted = alexaHostedApi(this._smapiRequest); - this.skill.betaTest = betaTestApi(this._smapiRequest); - this.skill.publishing = publishingApi(this._smapiRequest); - this.skillPackage = skillPackageApi(this._smapiRequest); - this.vendor = vendorApi(this._smapiRequest); - this.isp = ispApi(this._smapiRequest); - this.catalog = catalogApi(this._smapiRequest); - this.task = taskApi(this._smapiRequest); - } - - /** - * Method to handle response redirect urls sent by SMAPI - * @param {string} url - * @param {function} callback - */ - smapiRedirectRequestWithUrl(url, callback) { - const EMPTY_HEADERS = {}; - const method = CONSTANTS.HTTP_REQUEST.VERB.GET; - const NULL_PAYLOAD = null; - const requestOptions = { - url, - method, - headers: EMPTY_HEADERS, - body: NULL_PAYLOAD, - }; - const authorizationController = new AuthorizationController({ - auth_client_type: 'LWA', - doDebug: this.doDebug - }); - authorizationController.tokenRefreshAndRead(this.profile, (tokenErr, token) => { - if (tokenErr) { - return callback(tokenErr); - } - requestOptions.headers.authorization = token; - httpClient.request(requestOptions, 'REDIRECT_URL', this.doDebug, (reqErr, reqResponse) => { - if (reqErr) { - return callback(reqErr); - } - _normalizeSmapiResponse(reqResponse, (handleErr, smapiResponse) => { - callback(handleErr, handleErr ? null : smapiResponse); - }); - }); - }); - } - - /** - * The SMAPI specific function to extract list results by traversing all pages and return aggregated list results. - * @param {Array} callApiTrack Array to represent the target SMAPI client API request - * @param {Array} callArgv Array of the input arguements for the SMAPI API request - * @param {String} responseAccessor Name/type of listed element - * @param {Function} responseHandle Handle to extract list result in each page. Return { nextToken, listResult } from each response. - * @param {Function} callback (err, aggregatedListResult) - */ - listWithAutoPagination(callApiTrack, callArgv, responseAccessor, responseHandle, callback) { - const result = {}; - result[responseAccessor] = []; - const queryParams = { - maxResults: CONSTANTS.SMAPI.DEFAULT_MAX_RESULT_PER_PAGE, - }; - const smapiMethod = R.path(callApiTrack, this); - - async.doWhilst( - (loopCallback) => { - smapiMethod(...callArgv, queryParams, (err, res) => { - if (err) { - return loopCallback(err, null); - } - if (res.statusCode >= 300) { - // TODO stringify the body - return loopCallback(res.body, null); - } - const parseResult = responseHandle(res); - queryParams.nextToken = parseResult.nextToken; - result[responseAccessor] = result[responseAccessor].concat(parseResult.listResult); - loopCallback(null, result); - }); - }, - () => queryParams.nextToken, - (err, res) => callback(err, err ? null : res) - ); - } - - /** - * Generic SMAPI http request wrapper - * @param {String} apiName API name for metrics usage - * @param {String} method HTTP method - * @param {String} version SMAPI version - * @param {String} urlPath Path component for a SMAPI url - * @param {Object} queryParams Map of querry parameters - * @param {Object} headers Map of headers - * @param {Object} payload Payload body - * @param {Function} callback (err, requestResponse) - */ - _smapiRequest(apiName, method, version, urlPath, queryParams, headers, payload, callback) { - const qs = querystring.stringify(queryParams) && `?${querystring.stringify(queryParams)}`; - const smapiEndpoint = DynamicConfig.smapiBaseUrl; - const requestOptions = { - url: `${smapiEndpoint}/${version}/${urlPath}${qs}`, - method, - headers: headers || {}, - body: payload, - json: !!payload - }; - const authorizationController = new AuthorizationController({ - auth_client_type: 'LWA', - doDebug: this.doDebug - }); - authorizationController.tokenRefreshAndRead(this.profile, (tokenErr, token) => { - if (tokenErr) { - return callback(tokenErr); - } - requestOptions.headers.authorization = token; - httpClient.request(requestOptions, apiName, this.doDebug, (reqErr, reqResponse) => { - if (reqErr) { - return callback(reqErr); - } - _normalizeSmapiResponse(reqResponse, (normalizeErr, smapiResponse) => { - callback(normalizeErr, normalizeErr ? null : smapiResponse); - }); - }); - }); - } -}; - -/** - * Common function to validate and normalize SMAPI response. - * @param {Object} reqResponse the response from SMAPI - * @param {Function} callback (error, { statusCode, body, headers }) - */ -function _normalizeSmapiResponse(reqResponse, callback) { - let parsedResponseBody; - try { - _validateSmapiResponse(reqResponse); - parsedResponseBody = _cleanResponseBody(reqResponse.body); - } catch (validateErr) { - return callback(validateErr); - } - callback(null, { - statusCode: reqResponse.statusCode, - body: parsedResponseBody, - headers: reqResponse.headers - }); -} - -/** - * Validate SMAPI's response - * 1. If SMAPI response doesn't contain error object but status code >= 300 - * 2. If SMAPI response body is valid JSON object - * - * @param {Object} reqResponse the response from SMAPI - */ -function _validateSmapiResponse(reqResponse) { - if (reqResponse.statusCode >= 300 && !reqResponse.body) { - throw `[Fatal]: SMAPI error code ${reqResponse.statusCode}. No response body from the service request.`; - } - try { - if (reqResponse.body && typeof reqResponse.body === 'string') { - reqResponse.body = JSON.parse(reqResponse.body); - } - } catch (parseErr) { - throw `[Fatal]: Failed to parse SMAPI's response. Please run again with --debug to check more details.\nError: ${parseErr}`; - } -} - -/** - * function to clean up properties (such as _links) from the response body. - * @param {Object} reqResponseBody - */ -function _cleanResponseBody(reqResponseBody) { - if (reqResponseBody) { - Object.keys(reqResponseBody).forEach((key) => { - if (JSON_PROPERTIES.includes(key)) { - reqResponseBody = R.omit([key], reqResponseBody); - } else if (typeof reqResponseBody[key] === 'object') { - reqResponseBody[key] = _cleanResponseBody(reqResponseBody[key]); - } - }); - } - return reqResponseBody; -} diff --git a/lib/clients/smapi-client/index.ts b/lib/clients/smapi-client/index.ts new file mode 100644 index 00000000..ed7f9578 --- /dev/null +++ b/lib/clients/smapi-client/index.ts @@ -0,0 +1,307 @@ +import querystring from "querystring"; +import AuthorizationController from "../../controllers/authorization-controller"; +import DynamicConfig from "../../utils/dynamic-config"; +import httpClient from "../http-client"; + +import accountLinkingApi from "./resources/account-linking"; +import catalogApi from "./resources/catalog"; +import historyApi from "./resources/history"; +import ispApi from "./resources/isp"; +import manifestApi from "./resources/manifest"; +import interactionModelApi from "./resources/interaction-model"; +import privateSkillApi from "./resources/private-skill"; +import skillPackageApi from "./resources/skill-package"; +import skillApi from "./resources/skill"; +import testApi from "./resources/test"; +import vendorApi from "./resources/vendor"; +import evaluationsApi from "./resources/evaluations"; +import alexaHostedApi from "./resources/alexa-hosted"; +import betaTestApi from "./resources/beta-test"; +import publishingApi from "./resources/publishing"; +import taskApi from "./resources/task"; + +const JSON_PROPERTIES = ["_links"]; + +export interface ISmapiClient { + profile: string; + doDebug: boolean; + skill: ReturnType & { + manifest: ReturnType; + interactionModel: ReturnType; + accountLinking: ReturnType; + privateSkill: ReturnType; + history: ReturnType; + test: ReturnType; + evaluations: ReturnType; + alexaHosted: ReturnType; + betaTest: ReturnType; + publishing: ReturnType; + }; + skillPackage: ReturnType; + vendor: ReturnType; + isp: ReturnType; + catalog: ReturnType; + task: ReturnType; +} + +/** + * Class for Alexa Skill Management API Service (SMAPI) client + * + * Late bound to decouple the behavior from the user provided configuration of debug and profile. + */ +export class SmapiClientLateBound { + constructor() { + this._smapiRequest = this._smapiRequest.bind(this); + } + + withConfiguration(configuration: SmapiClientConfiguration): ISmapiClient { + const smapiRequest: SmapiRequest = ( + apiName: string, + method: string, + version: string, + urlPath: string, + queryParams: querystring.ParsedUrlQueryInput, + headers: Record | null, + payload: Record | null, + callback?: SmapiRequestCallback, + ) => this._smapiRequest(configuration, apiName, method, version, urlPath, queryParams, headers, payload, callback as any) as any; + return { + profile: configuration.profile, + doDebug: configuration.doDebug, + skill: { + ...skillApi(smapiRequest), + manifest: manifestApi(smapiRequest), + interactionModel: interactionModelApi(smapiRequest), + accountLinking: accountLinkingApi(smapiRequest), + privateSkill: privateSkillApi(smapiRequest), + history: historyApi(smapiRequest), + test: testApi(smapiRequest), + evaluations: evaluationsApi(smapiRequest), + alexaHosted: alexaHostedApi(smapiRequest), + betaTest: betaTestApi(smapiRequest), + publishing: publishingApi(smapiRequest), + }, + skillPackage: skillPackageApi(smapiRequest), + vendor: vendorApi(smapiRequest), + isp: ispApi(smapiRequest), + catalog: catalogApi(smapiRequest), + task: taskApi(smapiRequest), + }; + } + + /** + * Generic SMAPI http request wrapper + * @param {String} apiName API name for metrics usage + * @param {String} method HTTP method + * @param {String} version SMAPI version + * @param {String} urlPath Path component for a SMAPI url + * @param {Object} queryParams Map of querry parameters + * @param {Object} headers Map of headers + * @param {Object} payload Payload body + * @param {Function} callback (err, requestResponse) + */ + _smapiRequest( + configuration: SmapiClientConfiguration, + apiName: string, + method: string, + version: string, + urlPath: string, + queryParams: querystring.ParsedUrlQueryInput, + headers: Record | null, + payload: Record | null, + ): Promise>; + _smapiRequest( + configuration: SmapiClientConfiguration, + apiName: string, + method: string, + version: string, + urlPath: string, + queryParams: querystring.ParsedUrlQueryInput, + headers: Record | null, + payload: Record | null, + callback: SmapiRequestCallback, + ): void; + _smapiRequest( + configuration: SmapiClientConfiguration, + apiName: string, + method: string, + version: string, + urlPath: string, + queryParams: querystring.ParsedUrlQueryInput, + headers: Record | null, + payload: Record | null, + callback?: SmapiRequestCallback, + ): Promise> | void { + if (!callback) { + return new Promise((resolve, reject) => { + this._smapiRequest(configuration, apiName, method, version, urlPath, queryParams, headers, payload, (err, response) => { + if (err) { + return reject(err); + } + resolve(response as SmapiResponse); + }); + }); + } + const qs = querystring.stringify(queryParams) && `?${querystring.stringify(queryParams)}`; + const smapiEndpoint = DynamicConfig.smapiBaseUrl; + const authorizationController = new AuthorizationController({ + auth_client_type: "LWA", + doDebug: configuration.doDebug, + }); + authorizationController.tokenRefreshAndRead(configuration.profile, (tokenErr: string, token: string) => { + if (tokenErr) { + return callback(tokenErr); + } + const requestOptions = { + url: `${smapiEndpoint}/${version}/${urlPath}${qs}`, + method, + headers: { + ...headers, + authorization: token, + }, + body: payload, + json: !!payload, + }; + httpClient.request(requestOptions, apiName, configuration.doDebug, (reqErr: any, reqResponse: SmapiResponse) => { + if (reqErr) { + return callback(reqErr); + } + _normalizeSmapiResponse(reqResponse, (normalizeErr, smapiResponse) => { + callback(normalizeErr, normalizeErr ? null : smapiResponse); + }); + }); + }); + } +} + +export type SmapiRequestCallback = (err: any, response?: SmapiResponse | null) => void; +export type SmapiRequest = (( + apiName: string, + method: string, + version: string, + urlPath: string, + queryParams: querystring.ParsedUrlQueryInput, + headers: Record | null, + payload: Record | null, + callback: SmapiRequestCallback, +) => void) & + (( + apiName: string, + method: string, + version: string, + urlPath: string, + queryParams: querystring.ParsedUrlQueryInput, + headers: Record | null, + payload: Record | null, + ) => Promise>); + +export interface SmapiClientConfiguration { + profile: string; + doDebug: boolean; +} + +/** + * Class for Alexa Skill Management API Service (SMAPI) client + * + * Requires profile and debug flag. + * + * @deprecated use SmapiClientLateBound + */ +export default class SmapiClient implements ISmapiClient { + profile: string; + doDebug: boolean; + skill; + skillPackage; + vendor; + isp; + catalog; + task; + constructor(_configuration: SmapiClientConfiguration) { + const smapiClientLateBound = new SmapiClientLateBound().withConfiguration(_configuration); + this.skill = smapiClientLateBound.skill; + this.catalog = smapiClientLateBound.catalog; + this.isp = smapiClientLateBound.isp; + this.skillPackage = smapiClientLateBound.skillPackage; + this.vendor = smapiClientLateBound.vendor; + this.task = smapiClientLateBound.task; + this.profile = _configuration.profile; + this.doDebug = _configuration.doDebug; + } +} + +export type SmapiResponse, E = {}> = SmapiResponseObject | SmapiResponseError; + +export interface SmapiResponseObject> { + statusCode: number; + body: T; + headers: any[]; +} + +export interface SmapiResponseError { + statusCode: number; + body: E & {message: string}; + headers: any[]; +} + +export function isSmapiError(response: SmapiResponse): response is SmapiResponseError { + return response.statusCode >= 300; +} + +/** + * Common function to validate and normalize SMAPI response. + * @param {Object} reqResponse the response from SMAPI + * @param {Function} callback (error, { statusCode, body, headers }) + */ +function _normalizeSmapiResponse(reqResponse: SmapiResponse, callback: (err: any, resp?: SmapiResponse) => void) { + let parsedResponseBody; + try { + _validateSmapiResponse(reqResponse); + parsedResponseBody = _cleanResponseBody(reqResponse.body as Record) as T; + } catch (validateErr) { + return callback(validateErr); + } + callback(null, { + statusCode: reqResponse.statusCode, + body: parsedResponseBody, + headers: reqResponse.headers, + }); +} + +/** + * Validate SMAPI's response + * 1. If SMAPI response doesn't contain error object but status code >= 300 + * 2. If SMAPI response body is valid JSON object + * + * @param {Object} reqResponse the response from SMAPI + */ +function _validateSmapiResponse(reqResponse: SmapiResponse) { + if (reqResponse.statusCode >= 300 && !reqResponse.body) { + throw `[Fatal]: SMAPI error code ${reqResponse.statusCode}. No response body from the service request.`; + } + try { + if (reqResponse.body && typeof reqResponse.body === "string") { + reqResponse.body = JSON.parse(reqResponse.body); + } + } catch (parseErr) { + throw `[Fatal]: Failed to parse SMAPI's response. Please run again with --debug to check more details.\nError: ${parseErr}`; + } +} + +/** + * function to clean up properties (such as _links) from the response body. + * @param {Object} reqResponseBody + */ +function _cleanResponseBody(reqResponseBody?: Record): Record | undefined { + if (reqResponseBody) { + Object.keys(reqResponseBody).forEach((key) => { + if (JSON_PROPERTIES.includes(key)) { + const {[key]: k, ...rest} = reqResponseBody; + return rest; + } else if (typeof reqResponseBody[key] === "object") { + return {...reqResponseBody, [key]: _cleanResponseBody(reqResponseBody[key])}; + } + return; + }); + } + return reqResponseBody; +} diff --git a/lib/clients/smapi-client/resources/account-linking.js b/lib/clients/smapi-client/resources/account-linking.js index 59611f93..ed4d4db8 100644 --- a/lib/clients/smapi-client/resources/account-linking.js +++ b/lib/clients/smapi-client/resources/account-linking.js @@ -1,60 +1,60 @@ -const CONSTANTS = require('@src/utils/constants'); +const CONSTANTS = require("../../../utils/constants"); -const ACCOUNT_LINKING_URL_BASE = 'accountLinkingClient'; +const ACCOUNT_LINKING_URL_BASE = "accountLinkingClient"; const EMPTY_HEADERS = {}; const EMPTY_QUERY_PARAMS = {}; const NULL_PAYLOAD = null; module.exports = (smapiHandle) => { - function setAccountLinking(skillId, stage, accountLinkingInfo, callback) { - const url = `skills/${skillId}/stages/${stage}/${ACCOUNT_LINKING_URL_BASE}`; - const payload = { - accountLinkingRequest: accountLinkingInfo - }; - smapiHandle( - CONSTANTS.SMAPI.API_NAME.SET_ACCOUNT_LINKING, - CONSTANTS.HTTP_REQUEST.VERB.PUT, - CONSTANTS.SMAPI.VERSION.V1, - url, - EMPTY_QUERY_PARAMS, - EMPTY_HEADERS, - payload, - callback - ); - } + function setAccountLinking(skillId, stage, accountLinkingInfo, callback) { + const url = `skills/${skillId}/stages/${stage}/${ACCOUNT_LINKING_URL_BASE}`; + const payload = { + accountLinkingRequest: accountLinkingInfo, + }; + smapiHandle( + CONSTANTS.SMAPI.API_NAME.SET_ACCOUNT_LINKING, + CONSTANTS.HTTP_REQUEST.VERB.PUT, + CONSTANTS.SMAPI.VERSION.V1, + url, + EMPTY_QUERY_PARAMS, + EMPTY_HEADERS, + payload, + callback, + ); + } - function getAccountLinking(skillId, stage, callback) { - const url = `skills/${skillId}/stages/${stage}/${ACCOUNT_LINKING_URL_BASE}`; - smapiHandle( - CONSTANTS.SMAPI.API_NAME.GET_ACCOUNT_LINKING, - CONSTANTS.HTTP_REQUEST.VERB.GET, - CONSTANTS.SMAPI.VERSION.V1, - url, - EMPTY_QUERY_PARAMS, - EMPTY_HEADERS, - NULL_PAYLOAD, - callback - ); - } + function getAccountLinking(skillId, stage, callback) { + const url = `skills/${skillId}/stages/${stage}/${ACCOUNT_LINKING_URL_BASE}`; + smapiHandle( + CONSTANTS.SMAPI.API_NAME.GET_ACCOUNT_LINKING, + CONSTANTS.HTTP_REQUEST.VERB.GET, + CONSTANTS.SMAPI.VERSION.V1, + url, + EMPTY_QUERY_PARAMS, + EMPTY_HEADERS, + NULL_PAYLOAD, + callback, + ); + } - function deleteAccountLinking(skillId, stage, callback) { - const url = `skills/${skillId}/stages/${stage}/${ACCOUNT_LINKING_URL_BASE}`; - smapiHandle( - CONSTANTS.SMAPI.API_NAME.DELETE_ACCOUNT_LINKING, - CONSTANTS.HTTP_REQUEST.VERB.DELETE, - CONSTANTS.SMAPI.VERSION.V1, - url, - EMPTY_QUERY_PARAMS, - EMPTY_HEADERS, - NULL_PAYLOAD, - callback - ); - } + function deleteAccountLinking(skillId, stage, callback) { + const url = `skills/${skillId}/stages/${stage}/${ACCOUNT_LINKING_URL_BASE}`; + smapiHandle( + CONSTANTS.SMAPI.API_NAME.DELETE_ACCOUNT_LINKING, + CONSTANTS.HTTP_REQUEST.VERB.DELETE, + CONSTANTS.SMAPI.VERSION.V1, + url, + EMPTY_QUERY_PARAMS, + EMPTY_HEADERS, + NULL_PAYLOAD, + callback, + ); + } - return { - setAccountLinking, - getAccountLinking, - deleteAccountLinking - }; + return { + setAccountLinking, + getAccountLinking, + deleteAccountLinking, + }; }; diff --git a/lib/clients/smapi-client/resources/alexa-hosted.js b/lib/clients/smapi-client/resources/alexa-hosted.js index 6cbce161..b59c5691 100644 --- a/lib/clients/smapi-client/resources/alexa-hosted.js +++ b/lib/clients/smapi-client/resources/alexa-hosted.js @@ -1,116 +1,116 @@ -const CONSTANTS = require('@src/utils/constants'); +const CONSTANTS = require("../../../utils/constants"); const EMPTY_HEADERS = {}; const EMPTY_QUERY_PARAMS = {}; const NULL_PAYLOAD = null; module.exports = (smapiHandle) => { - /** - * To submit a skill creation request for a specified vendorId - * @param {Object} hostedSkillPayload The JSON representation of the skill, and provides Alexa with all of the metadata required - * @param {callback} callback { error, response } - */ - function createHostedSkill(hostedSkillPayload, callback) { - const url = 'skills/'; - const { vendorId, manifest, region } = hostedSkillPayload; - const runtime = CONSTANTS.HOSTED_SKILL.DEFAULT_RUNTIME[hostedSkillPayload.runtime]; + /** + * To submit a skill creation request for a specified vendorId + * @param {Object} hostedSkillPayload The JSON representation of the skill, and provides Alexa with all of the metadata required + * @param {callback} callback { error, response } + */ + function createHostedSkill(hostedSkillPayload, callback) { + const url = "skills/"; + const {vendorId, manifest, region} = hostedSkillPayload; + const runtime = CONSTANTS.HOSTED_SKILL.DEFAULT_RUNTIME[hostedSkillPayload.runtime]; - const payload = { - vendorId, - manifest, - hosting: { - alexaHosted: { - runtime, - region - } - } - }; + const payload = { + vendorId, + manifest, + hosting: { + alexaHosted: { + runtime, + region, + }, + }, + }; - smapiHandle( - CONSTANTS.SMAPI.API_NAME.CREATE_HOSTED_SKILL, - CONSTANTS.HTTP_REQUEST.VERB.POST, - CONSTANTS.SMAPI.VERSION.V1, - url, - EMPTY_QUERY_PARAMS, - EMPTY_HEADERS, - payload, - callback - ); - } + smapiHandle( + CONSTANTS.SMAPI.API_NAME.CREATE_HOSTED_SKILL, + CONSTANTS.HTTP_REQUEST.VERB.POST, + CONSTANTS.SMAPI.VERSION.V1, + url, + EMPTY_QUERY_PARAMS, + EMPTY_HEADERS, + payload, + callback, + ); + } - /** - * To get information about an Alexa-hosted skill - * @param {string} skillId The skill Id - * @param {callback} callback { error, response } - */ - function getAlexaHostedSkillMetadata(skillId, callback) { - const url = `skills/${skillId}/alexaHosted`; + /** + * To get information about an Alexa-hosted skill + * @param {string} skillId The skill Id + * @param {callback} callback { error, response } + */ + function getAlexaHostedSkillMetadata(skillId, callback) { + const url = `skills/${skillId}/alexaHosted`; - smapiHandle( - CONSTANTS.SMAPI.API_NAME.GET_HOSTED_SKILLS_META_DATA, - CONSTANTS.HTTP_REQUEST.VERB.GET, - CONSTANTS.SMAPI.VERSION.V1, - url, - EMPTY_QUERY_PARAMS, - EMPTY_HEADERS, - NULL_PAYLOAD, - callback - ); - } + smapiHandle( + CONSTANTS.SMAPI.API_NAME.GET_HOSTED_SKILLS_META_DATA, + CONSTANTS.HTTP_REQUEST.VERB.GET, + CONSTANTS.SMAPI.VERSION.V1, + url, + EMPTY_QUERY_PARAMS, + EMPTY_HEADERS, + NULL_PAYLOAD, + callback, + ); + } - /** - * To obtain the skill credentials for the specified skill - * @param {string} skillId The skill Id - * @param {string} repoUrl repository url - * @param {callback} callback { error, response } - */ - function getGitCredentials(skillId, repoUrl, callback) { - const url = `skills/${skillId}/alexaHosted/repository/credentials/generate`; + /** + * To obtain the skill credentials for the specified skill + * @param {string} skillId The skill Id + * @param {string} repoUrl repository url + * @param {callback} callback { error, response } + */ + function getGitCredentials(skillId, repoUrl, callback) { + const url = `skills/${skillId}/alexaHosted/repository/credentials/generate`; - const payload = { - repository: { - type: 'GIT', - url: repoUrl - } - }; + const payload = { + repository: { + type: "GIT", + url: repoUrl, + }, + }; - smapiHandle( - CONSTANTS.SMAPI.API_NAME.GET_GIT_CREDENTIALS, - CONSTANTS.HTTP_REQUEST.VERB.POST, - CONSTANTS.SMAPI.VERSION.V1, - url, - EMPTY_QUERY_PARAMS, - EMPTY_HEADERS, - payload, - callback - ); - } + smapiHandle( + CONSTANTS.SMAPI.API_NAME.GET_GIT_CREDENTIALS, + CONSTANTS.HTTP_REQUEST.VERB.POST, + CONSTANTS.SMAPI.VERSION.V1, + url, + EMPTY_QUERY_PARAMS, + EMPTY_HEADERS, + payload, + callback, + ); + } - /** - * To access a permission to an Alexa hosted skill - * @param {string} vendorId The vendor Id - * @param {string} permissionType The permission type - * @param {callback} callback { error, response } - */ - function getHostedSkillPermission(vendorId, permissionType, callback) { - const url = `vendors/${vendorId}/alexaHosted/permissions/${permissionType}`; + /** + * To access a permission to an Alexa hosted skill + * @param {string} vendorId The vendor Id + * @param {string} permissionType The permission type + * @param {callback} callback { error, response } + */ + function getHostedSkillPermission(vendorId, permissionType, callback) { + const url = `vendors/${vendorId}/alexaHosted/permissions/${permissionType}`; - smapiHandle( - CONSTANTS.SMAPI.API_NAME.GET_HOSTED_SKILLS_PERMISSION, - CONSTANTS.HTTP_REQUEST.VERB.GET, - CONSTANTS.SMAPI.VERSION.V1, - url, - EMPTY_QUERY_PARAMS, - EMPTY_HEADERS, - NULL_PAYLOAD, - callback - ); - } + smapiHandle( + CONSTANTS.SMAPI.API_NAME.GET_HOSTED_SKILLS_PERMISSION, + CONSTANTS.HTTP_REQUEST.VERB.GET, + CONSTANTS.SMAPI.VERSION.V1, + url, + EMPTY_QUERY_PARAMS, + EMPTY_HEADERS, + NULL_PAYLOAD, + callback, + ); + } - return { - createHostedSkill, - getAlexaHostedSkillMetadata, - getGitCredentials, - getHostedSkillPermission - }; + return { + createHostedSkill, + getAlexaHostedSkillMetadata, + getGitCredentials, + getHostedSkillPermission, + }; }; diff --git a/lib/clients/smapi-client/resources/beta-test.js b/lib/clients/smapi-client/resources/beta-test.js index 6b180907..7455d386 100644 --- a/lib/clients/smapi-client/resources/beta-test.js +++ b/lib/clients/smapi-client/resources/beta-test.js @@ -1,7 +1,7 @@ -const R = require('ramda'); +const R = require("ramda"); -const CONSTANTS = require('@src/utils/constants'); -const stringUtils = require('@src/utils/string-utils'); +const CONSTANTS = require("../../../utils/constants"); +const stringUtils = require("../../../utils/string-utils"); const EMPTY_HEADERS = {}; const EMPTY_QUERY_PARAMS = {}; @@ -9,243 +9,243 @@ const EMPTY_PAYLOAD = {}; const NULL_PAYLOAD = null; module.exports = (smapiHandle) => { - /** - * Creates a beta test. - * @param {string} skillId | skill id, - * @param {string} feedbackEmail | feedback email - * @param {function} callback | callback function from command - */ - function createBetaTest(skillId, feedbackEmail, callback) { - const url = `skills/${skillId}/betaTest`; - const payload = stringUtils.isNonBlankString(feedbackEmail) ? { feedbackEmail } : EMPTY_PAYLOAD; - - smapiHandle( - CONSTANTS.SMAPI.API_NAME.CREATE_BETA_TEST, - CONSTANTS.HTTP_REQUEST.VERB.POST, - CONSTANTS.SMAPI.VERSION.V1, - url, - EMPTY_QUERY_PARAMS, - EMPTY_HEADERS, - payload, - callback - ); + /** + * Creates a beta test. + * @param {string} skillId | skill id, + * @param {string} feedbackEmail | feedback email + * @param {function} callback | callback function from command + */ + function createBetaTest(skillId, feedbackEmail, callback) { + const url = `skills/${skillId}/betaTest`; + const payload = stringUtils.isNonBlankString(feedbackEmail) ? {feedbackEmail} : EMPTY_PAYLOAD; + + smapiHandle( + CONSTANTS.SMAPI.API_NAME.CREATE_BETA_TEST, + CONSTANTS.HTTP_REQUEST.VERB.POST, + CONSTANTS.SMAPI.VERSION.V1, + url, + EMPTY_QUERY_PARAMS, + EMPTY_HEADERS, + payload, + callback, + ); + } + + /** + * Updates the details of a beta test. Currently only the feedback email can be updated. + * @param {string} skillId | skill id, + * @param {string} feedbackEmail | feedback email + * @param {function} callback | callback function from command + */ + function updateBetaTest(skillId, feedbackEmail, callback) { + const url = `skills/${skillId}/betaTest`; + const payload = stringUtils.isNonBlankString(feedbackEmail) ? {feedbackEmail} : EMPTY_PAYLOAD; + + smapiHandle( + CONSTANTS.SMAPI.API_NAME.UPDATE_BETA_TEST, + CONSTANTS.HTTP_REQUEST.VERB.PUT, + CONSTANTS.SMAPI.VERSION.V1, + url, + EMPTY_QUERY_PARAMS, + EMPTY_HEADERS, + payload, + callback, + ); + } + + /** + * Obtains the beta test details for a specified skill ID. + * @param {string} skillId | skill id + * @param {function} callback | callback function from command + */ + function getBetaTest(skillId, callback) { + const url = `skills/${skillId}/betaTest`; + + smapiHandle( + CONSTANTS.SMAPI.API_NAME.GET_BETA_TEST, + CONSTANTS.HTTP_REQUEST.VERB.GET, + CONSTANTS.SMAPI.VERSION.V1, + url, + EMPTY_QUERY_PARAMS, + EMPTY_HEADERS, + EMPTY_PAYLOAD, + callback, + ); + } + + /** + * Start the beta test for the specified skill ID. This will start the clock for the test's duration, + * as a beta test can only last 90 days, although you can then create a new beta test. + * @param {string} skillId | skill id + * @param {function} callback | callback function from command + */ + function startBetaTest(skillId, callback) { + const url = `skills/${skillId}/betaTest/start`; + + smapiHandle( + CONSTANTS.SMAPI.API_NAME.START_BETA_TEST, + CONSTANTS.HTTP_REQUEST.VERB.POST, + CONSTANTS.SMAPI.VERSION.V1, + url, + EMPTY_QUERY_PARAMS, + EMPTY_HEADERS, + EMPTY_PAYLOAD, + callback, + ); + } + + /** + * Ends the beta test for the specified skill ID. By default, a beta test will conclude after 90 days. + * You can end a beta test early with this API. + * @param {string} skillId | skill id + * @param {function} callback | callback function from command + */ + function endBetaTest(skillId, callback) { + const url = `skills/${skillId}/betaTest/end`; + + smapiHandle( + CONSTANTS.SMAPI.API_NAME.END_BETA_TEST, + CONSTANTS.HTTP_REQUEST.VERB.POST, + CONSTANTS.SMAPI.VERSION.V1, + url, + EMPTY_QUERY_PARAMS, + EMPTY_HEADERS, + EMPTY_PAYLOAD, + callback, + ); + } + + /** + * List testers in a beta test of given Alexa skill + * @param skillId [Required] | skill id + * @param queryParams, contains nextToken | token to get next page of results and maxResults | max number of results returned, default is 50 + * @param callback | callback function from command + */ + function listBetaTesters(skillId, queryParams, callback) { + const url = `skills/${skillId}/betaTest/testers`; + let queryObject = R.clone(queryParams); + if (R.isEmpty(queryObject)) { + queryObject = {}; } - /** - * Updates the details of a beta test. Currently only the feedback email can be updated. - * @param {string} skillId | skill id, - * @param {string} feedbackEmail | feedback email - * @param {function} callback | callback function from command - */ - function updateBetaTest(skillId, feedbackEmail, callback) { - const url = `skills/${skillId}/betaTest`; - const payload = stringUtils.isNonBlankString(feedbackEmail) ? { feedbackEmail } : EMPTY_PAYLOAD; - - smapiHandle( - CONSTANTS.SMAPI.API_NAME.UPDATE_BETA_TEST, - CONSTANTS.HTTP_REQUEST.VERB.PUT, - CONSTANTS.SMAPI.VERSION.V1, - url, - EMPTY_QUERY_PARAMS, - EMPTY_HEADERS, - payload, - callback - ); - } - - /** - * Obtains the beta test details for a specified skill ID. - * @param {string} skillId | skill id - * @param {function} callback | callback function from command - */ - function getBetaTest(skillId, callback) { - const url = `skills/${skillId}/betaTest`; - - smapiHandle( - CONSTANTS.SMAPI.API_NAME.GET_BETA_TEST, - CONSTANTS.HTTP_REQUEST.VERB.GET, - CONSTANTS.SMAPI.VERSION.V1, - url, - EMPTY_QUERY_PARAMS, - EMPTY_HEADERS, - EMPTY_PAYLOAD, - callback - ); - } - - /** - * Start the beta test for the specified skill ID. This will start the clock for the test's duration, - * as a beta test can only last 90 days, although you can then create a new beta test. - * @param {string} skillId | skill id - * @param {function} callback | callback function from command - */ - function startBetaTest(skillId, callback) { - const url = `skills/${skillId}/betaTest/start`; - - smapiHandle( - CONSTANTS.SMAPI.API_NAME.START_BETA_TEST, - CONSTANTS.HTTP_REQUEST.VERB.POST, - CONSTANTS.SMAPI.VERSION.V1, - url, - EMPTY_QUERY_PARAMS, - EMPTY_HEADERS, - EMPTY_PAYLOAD, - callback - ); - } - - /** - * Ends the beta test for the specified skill ID. By default, a beta test will conclude after 90 days. - * You can end a beta test early with this API. - * @param {string} skillId | skill id - * @param {function} callback | callback function from command - */ - function endBetaTest(skillId, callback) { - const url = `skills/${skillId}/betaTest/end`; - - smapiHandle( - CONSTANTS.SMAPI.API_NAME.END_BETA_TEST, - CONSTANTS.HTTP_REQUEST.VERB.POST, - CONSTANTS.SMAPI.VERSION.V1, - url, - EMPTY_QUERY_PARAMS, - EMPTY_HEADERS, - EMPTY_PAYLOAD, - callback - ); - } - - /** - * List testers in a beta test of given Alexa skill - * @param skillId [Required] | skill id - * @param queryParams, contains nextToken | token to get next page of results and maxResults | max number of results returned, default is 50 - * @param callback | callback function from command - */ - function listBetaTesters(skillId, queryParams, callback) { - const url = `skills/${skillId}/betaTest/testers`; - let queryObject = R.clone(queryParams); - if (R.isEmpty(queryObject)) { - queryObject = {}; - } - - smapiHandle( - CONSTANTS.SMAPI.API_NAME.LIST_BETA_TESTERS, - CONSTANTS.HTTP_REQUEST.VERB.GET, - CONSTANTS.SMAPI.VERSION.V1, - url, - queryObject, - EMPTY_HEADERS, - NULL_PAYLOAD, - callback - ); - } - - /** - * Add testers to a beta test of given Alexa skill - * @param skillId [Required] skill id - * @param testers tester email id list - * @param callback callback function from command - */ - function addBetaTesters(skillId, testers, callback) { - const url = `skills/${skillId}/betaTest/testers/add`; - const payload = { - testers, - }; - - smapiHandle( - CONSTANTS.SMAPI.API_NAME.ADD_BETA_TESTERS, - CONSTANTS.HTTP_REQUEST.VERB.POST, - CONSTANTS.SMAPI.VERSION.V1, - url, - EMPTY_QUERY_PARAMS, - EMPTY_HEADERS, - payload, - callback - ); - } - - /** - * Remove testers from a beta test of a given Alexa skill - * @param skillId [Required] skill id - * @param testers tester email id list - * @param callback callback function from command - */ - function removeBetaTesters(skillId, testers, callback) { - const url = `skills/${skillId}/betaTest/testers/remove`; - const payload = { - testers, - }; - - smapiHandle( - CONSTANTS.SMAPI.API_NAME.REMOVE_BETA_TESTERS, - CONSTANTS.HTTP_REQUEST.VERB.POST, - CONSTANTS.SMAPI.VERSION.V1, - url, - EMPTY_QUERY_PARAMS, - EMPTY_HEADERS, - payload, - callback - ); - } + smapiHandle( + CONSTANTS.SMAPI.API_NAME.LIST_BETA_TESTERS, + CONSTANTS.HTTP_REQUEST.VERB.GET, + CONSTANTS.SMAPI.VERSION.V1, + url, + queryObject, + EMPTY_HEADERS, + NULL_PAYLOAD, + callback, + ); + } + + /** + * Add testers to a beta test of given Alexa skill + * @param skillId [Required] skill id + * @param testers tester email id list + * @param callback callback function from command + */ + function addBetaTesters(skillId, testers, callback) { + const url = `skills/${skillId}/betaTest/testers/add`; + const payload = { + testers, + }; - /** - * Send reminder to testers in a beta test of a given Alexa skill - * @param skillId [Required] skill id - * @param testers tester email id list - * @param callback callback function from command - */ - function sendReminderToBetaTesters(skillId, testers, callback) { - const url = `skills/${skillId}/betaTest/testers/sendReminder`; - const payload = { - testers, - }; - - smapiHandle( - CONSTANTS.SMAPI.API_NAME.SEND_REMINDER_TO_BETA_TESTERS, - CONSTANTS.HTTP_REQUEST.VERB.POST, - CONSTANTS.SMAPI.VERSION.V1, - url, - EMPTY_QUERY_PARAMS, - EMPTY_HEADERS, - payload, - callback - ); - } + smapiHandle( + CONSTANTS.SMAPI.API_NAME.ADD_BETA_TESTERS, + CONSTANTS.HTTP_REQUEST.VERB.POST, + CONSTANTS.SMAPI.VERSION.V1, + url, + EMPTY_QUERY_PARAMS, + EMPTY_HEADERS, + payload, + callback, + ); + } + + /** + * Remove testers from a beta test of a given Alexa skill + * @param skillId [Required] skill id + * @param testers tester email id list + * @param callback callback function from command + */ + function removeBetaTesters(skillId, testers, callback) { + const url = `skills/${skillId}/betaTest/testers/remove`; + const payload = { + testers, + }; - /** - * Request feedback from testers in a beta test of given Alexa skill - * @param skillId [Required] skill id - * @param testers tester email id list - * @param callback callback function from command - */ - function requestFeedbackFromBetaTesters(skillId, testers, callback) { - const url = `skills/${skillId}/betaTest/testers/requestFeedback`; - const payload = { - testers, - }; - - smapiHandle( - CONSTANTS.SMAPI.API_NAME.REQUEST_FEEDBACK_FROM_BETA_TESTERS, - CONSTANTS.HTTP_REQUEST.VERB.POST, - CONSTANTS.SMAPI.VERSION.V1, - url, - EMPTY_QUERY_PARAMS, - EMPTY_HEADERS, - payload, - callback - ); - } + smapiHandle( + CONSTANTS.SMAPI.API_NAME.REMOVE_BETA_TESTERS, + CONSTANTS.HTTP_REQUEST.VERB.POST, + CONSTANTS.SMAPI.VERSION.V1, + url, + EMPTY_QUERY_PARAMS, + EMPTY_HEADERS, + payload, + callback, + ); + } + + /** + * Send reminder to testers in a beta test of a given Alexa skill + * @param skillId [Required] skill id + * @param testers tester email id list + * @param callback callback function from command + */ + function sendReminderToBetaTesters(skillId, testers, callback) { + const url = `skills/${skillId}/betaTest/testers/sendReminder`; + const payload = { + testers, + }; - return { - createBetaTest, - updateBetaTest, - getBetaTest, - startBetaTest, - endBetaTest, - listBetaTesters, - addBetaTesters, - removeBetaTesters, - sendReminderToBetaTesters, - requestFeedbackFromBetaTesters + smapiHandle( + CONSTANTS.SMAPI.API_NAME.SEND_REMINDER_TO_BETA_TESTERS, + CONSTANTS.HTTP_REQUEST.VERB.POST, + CONSTANTS.SMAPI.VERSION.V1, + url, + EMPTY_QUERY_PARAMS, + EMPTY_HEADERS, + payload, + callback, + ); + } + + /** + * Request feedback from testers in a beta test of given Alexa skill + * @param skillId [Required] skill id + * @param testers tester email id list + * @param callback callback function from command + */ + function requestFeedbackFromBetaTesters(skillId, testers, callback) { + const url = `skills/${skillId}/betaTest/testers/requestFeedback`; + const payload = { + testers, }; + + smapiHandle( + CONSTANTS.SMAPI.API_NAME.REQUEST_FEEDBACK_FROM_BETA_TESTERS, + CONSTANTS.HTTP_REQUEST.VERB.POST, + CONSTANTS.SMAPI.VERSION.V1, + url, + EMPTY_QUERY_PARAMS, + EMPTY_HEADERS, + payload, + callback, + ); + } + + return { + createBetaTest, + updateBetaTest, + getBetaTest, + startBetaTest, + endBetaTest, + listBetaTesters, + addBetaTesters, + removeBetaTesters, + sendReminderToBetaTesters, + requestFeedbackFromBetaTesters, + }; }; diff --git a/lib/clients/smapi-client/resources/catalog.js b/lib/clients/smapi-client/resources/catalog.js index b70d135c..1100e8ac 100644 --- a/lib/clients/smapi-client/resources/catalog.js +++ b/lib/clients/smapi-client/resources/catalog.js @@ -1,165 +1,165 @@ -const R = require('ramda'); -const CONSTANTS = require('@src/utils/constants'); +const R = require("ramda"); +const CONSTANTS = require("../../../utils/constants"); const EMPTY_HEADERS = {}; const EMPTY_QUERY_PARAMS = {}; const NULL_PAYLOAD = null; module.exports = (smapiHandle) => { - function createCatalog(title, type, usage, vendorId, callback) { - const url = 'catalogs'; - const payload = { - title, - type, - usage, - vendorId - }; - smapiHandle( - CONSTANTS.SMAPI.API_NAME.CREATE_CATALOG, - CONSTANTS.HTTP_REQUEST.VERB.POST, - CONSTANTS.SMAPI.VERSION.V0, - url, - EMPTY_QUERY_PARAMS, - EMPTY_HEADERS, - payload, - callback - ); - } + function createCatalog(title, type, usage, vendorId, callback) { + const url = "catalogs"; + const payload = { + title, + type, + usage, + vendorId, + }; + smapiHandle( + CONSTANTS.SMAPI.API_NAME.CREATE_CATALOG, + CONSTANTS.HTTP_REQUEST.VERB.POST, + CONSTANTS.SMAPI.VERSION.V0, + url, + EMPTY_QUERY_PARAMS, + EMPTY_HEADERS, + payload, + callback, + ); + } - function getCatalog(catalogId, callback) { - const url = `catalogs/${catalogId}`; - smapiHandle( - CONSTANTS.SMAPI.API_NAME.GET_CATALOG, - CONSTANTS.HTTP_REQUEST.VERB.GET, - CONSTANTS.SMAPI.VERSION.V0, - url, - EMPTY_QUERY_PARAMS, - EMPTY_HEADERS, - NULL_PAYLOAD, - callback - ); - } + function getCatalog(catalogId, callback) { + const url = `catalogs/${catalogId}`; + smapiHandle( + CONSTANTS.SMAPI.API_NAME.GET_CATALOG, + CONSTANTS.HTTP_REQUEST.VERB.GET, + CONSTANTS.SMAPI.VERSION.V0, + url, + EMPTY_QUERY_PARAMS, + EMPTY_HEADERS, + NULL_PAYLOAD, + callback, + ); + } - /** - * List ISPs based on the vendor-id - * @param {*} vendorId - * @param {*} queryParams | nextToken - * | maxResults - * @param {*} callback - */ - function listCatalogs(vendorId, queryParams, callback) { - let queryObject = R.clone(queryParams); - if (!queryObject) { - queryObject = {}; - } - queryObject.vendorId = vendorId; - if (queryObject && !queryObject.maxResults) { - queryObject.maxResults = CONSTANTS.SMAPI.DEFAULT_MAX_RESULT_PER_PAGE; - } - const url = 'catalogs'; - smapiHandle( - CONSTANTS.SMAPI.API_NAME.LIST_CATALOGS, - CONSTANTS.HTTP_REQUEST.VERB.GET, - CONSTANTS.SMAPI.VERSION.V0, - url, - queryObject, - EMPTY_HEADERS, - NULL_PAYLOAD, - callback - ); + /** + * List ISPs based on the vendor-id + * @param {*} vendorId + * @param {*} queryParams | nextToken + * | maxResults + * @param {*} callback + */ + function listCatalogs(vendorId, queryParams, callback) { + let queryObject = R.clone(queryParams); + if (!queryObject) { + queryObject = {}; } - - function createCatalogUpload(catalogId, numberOfUploadParts, callback) { - const url = `catalogs/${catalogId}/uploads`; - const payload = { - numberOfUploadParts - }; - smapiHandle( - CONSTANTS.SMAPI.API_NAME.UPLOAD_CATALOG, - CONSTANTS.HTTP_REQUEST.VERB.POST, - CONSTANTS.SMAPI.VERSION.V0, - url, - EMPTY_QUERY_PARAMS, - EMPTY_HEADERS, - payload, - callback - ); + queryObject.vendorId = vendorId; + if (queryObject && !queryObject.maxResults) { + queryObject.maxResults = CONSTANTS.SMAPI.DEFAULT_MAX_RESULT_PER_PAGE; } + const url = "catalogs"; + smapiHandle( + CONSTANTS.SMAPI.API_NAME.LIST_CATALOGS, + CONSTANTS.HTTP_REQUEST.VERB.GET, + CONSTANTS.SMAPI.VERSION.V0, + url, + queryObject, + EMPTY_HEADERS, + NULL_PAYLOAD, + callback, + ); + } - function getCatalogUpload(catalogId, uploadId, callback) { - const url = `catalogs/${catalogId}/uploads/${uploadId}`; - smapiHandle( - CONSTANTS.SMAPI.API_NAME.GET_CATALOG_UPLOAD, - CONSTANTS.HTTP_REQUEST.VERB.GET, - CONSTANTS.SMAPI.VERSION.V0, - url, - EMPTY_QUERY_PARAMS, - EMPTY_HEADERS, - NULL_PAYLOAD, - callback - ); - } + function createCatalogUpload(catalogId, numberOfUploadParts, callback) { + const url = `catalogs/${catalogId}/uploads`; + const payload = { + numberOfUploadParts, + }; + smapiHandle( + CONSTANTS.SMAPI.API_NAME.UPLOAD_CATALOG, + CONSTANTS.HTTP_REQUEST.VERB.POST, + CONSTANTS.SMAPI.VERSION.V0, + url, + EMPTY_QUERY_PARAMS, + EMPTY_HEADERS, + payload, + callback, + ); + } - function listCatalogUploads(catalogId, queryParams, callback) { - let queryObject = R.clone(queryParams); - if (!queryObject) { - queryObject = {}; - } - if (queryObject && !queryObject.maxResults) { - queryObject.maxResults = CONSTANTS.SMAPI.DEFAULT_MAX_RESULT_PER_PAGE; - } - const url = `catalogs/${catalogId}/uploads`; - smapiHandle( - CONSTANTS.SMAPI.API_NAME.LIST_CATALOG_UPLOADS, - CONSTANTS.HTTP_REQUEST.VERB.GET, - CONSTANTS.SMAPI.VERSION.V0, - url, - queryObject, - EMPTY_HEADERS, - NULL_PAYLOAD, - callback - ); - } + function getCatalogUpload(catalogId, uploadId, callback) { + const url = `catalogs/${catalogId}/uploads/${uploadId}`; + smapiHandle( + CONSTANTS.SMAPI.API_NAME.GET_CATALOG_UPLOAD, + CONSTANTS.HTTP_REQUEST.VERB.GET, + CONSTANTS.SMAPI.VERSION.V0, + url, + EMPTY_QUERY_PARAMS, + EMPTY_HEADERS, + NULL_PAYLOAD, + callback, + ); + } - function associateCatalogWithSkill(skillId, catalogId, callback) { - const url = `skills/${skillId}/catalogs/${catalogId}`; - smapiHandle( - CONSTANTS.SMAPI.API_NAME.ASSOCIATE_CATALOG_WITH_SKILL, - CONSTANTS.HTTP_REQUEST.VERB.PUT, - CONSTANTS.SMAPI.VERSION.V0, - url, - EMPTY_QUERY_PARAMS, - EMPTY_HEADERS, - NULL_PAYLOAD, - callback - ); + function listCatalogUploads(catalogId, queryParams, callback) { + let queryObject = R.clone(queryParams); + if (!queryObject) { + queryObject = {}; } - - function completeCatalogUpload(catalogId, uploadId, partETagsList, callback) { - const url = `catalogs/${catalogId}/uploads/${uploadId}`; - const payload = { - partETags: partETagsList - }; - smapiHandle( - CONSTANTS.SMAPI.API_NAME.COMPLET_CATALOG_UPLOAD, - CONSTANTS.HTTP_REQUEST.VERB.POST, - CONSTANTS.SMAPI.VERSION.V0, - url, - EMPTY_QUERY_PARAMS, - EMPTY_HEADERS, - payload, - callback - ); + if (queryObject && !queryObject.maxResults) { + queryObject.maxResults = CONSTANTS.SMAPI.DEFAULT_MAX_RESULT_PER_PAGE; } + const url = `catalogs/${catalogId}/uploads`; + smapiHandle( + CONSTANTS.SMAPI.API_NAME.LIST_CATALOG_UPLOADS, + CONSTANTS.HTTP_REQUEST.VERB.GET, + CONSTANTS.SMAPI.VERSION.V0, + url, + queryObject, + EMPTY_HEADERS, + NULL_PAYLOAD, + callback, + ); + } - return { - createCatalog, - getCatalog, - listCatalogs, - createCatalogUpload, - getCatalogUpload, - listCatalogUploads, - associateCatalogWithSkill, - completeCatalogUpload + function associateCatalogWithSkill(skillId, catalogId, callback) { + const url = `skills/${skillId}/catalogs/${catalogId}`; + smapiHandle( + CONSTANTS.SMAPI.API_NAME.ASSOCIATE_CATALOG_WITH_SKILL, + CONSTANTS.HTTP_REQUEST.VERB.PUT, + CONSTANTS.SMAPI.VERSION.V0, + url, + EMPTY_QUERY_PARAMS, + EMPTY_HEADERS, + NULL_PAYLOAD, + callback, + ); + } + + function completeCatalogUpload(catalogId, uploadId, partETagsList, callback) { + const url = `catalogs/${catalogId}/uploads/${uploadId}`; + const payload = { + partETags: partETagsList, }; + smapiHandle( + CONSTANTS.SMAPI.API_NAME.COMPLET_CATALOG_UPLOAD, + CONSTANTS.HTTP_REQUEST.VERB.POST, + CONSTANTS.SMAPI.VERSION.V0, + url, + EMPTY_QUERY_PARAMS, + EMPTY_HEADERS, + payload, + callback, + ); + } + + return { + createCatalog, + getCatalog, + listCatalogs, + createCatalogUpload, + getCatalogUpload, + listCatalogUploads, + associateCatalogWithSkill, + completeCatalogUpload, + }; }; diff --git a/lib/clients/smapi-client/resources/evaluations.js b/lib/clients/smapi-client/resources/evaluations.js index 1e95da74..525461e8 100644 --- a/lib/clients/smapi-client/resources/evaluations.js +++ b/lib/clients/smapi-client/resources/evaluations.js @@ -1,42 +1,42 @@ -const CONSTANTS = require('@src/utils/constants'); +const CONSTANTS = require("../../../utils/constants"); const EMPTY_HEADERS = {}; const EMPTY_QUERY_PARAMS = {}; module.exports = (smapiHandle) => { - /** - * Profile utterance with NLU - * @param {string} skillId | skill id - * @param {string} stage | skill stage, default is development - * @param {string} locale | skill locale - * @param {string} utterance | utterance to be profiled - * @param {string} multiTurnToken | multiturn token for dialog - * @param {function} callback | callback function from command - */ - function callProfileNlu(skillId, stage, locale, utterance, multiTurnToken, callback) { - const skillStage = stage || CONSTANTS.SKILL.STAGE.DEVELOPMENT; - const url = `skills/${skillId}/stages/${skillStage}/interactionModel/locales/${locale}/profileNlu`; - const payload = { - utterance, - }; - - if (multiTurnToken) { - payload.multiTurnToken = multiTurnToken; - } + /** + * Profile utterance with NLU + * @param {string} skillId | skill id + * @param {string} stage | skill stage, default is development + * @param {string} locale | skill locale + * @param {string} utterance | utterance to be profiled + * @param {string} multiTurnToken | multiTurn token for dialog + * @param {function} callback | callback function from command + */ + function callProfileNlu(skillId, stage, locale, utterance, multiTurnToken, callback) { + const skillStage = stage || CONSTANTS.SKILL.STAGE.DEVELOPMENT; + const url = `skills/${skillId}/stages/${skillStage}/interactionModel/locales/${locale}/profileNlu`; + const payload = { + utterance, + }; - smapiHandle( - CONSTANTS.SMAPI.API_NAME.NLU_PROFILE, - CONSTANTS.HTTP_REQUEST.VERB.POST, - CONSTANTS.SMAPI.VERSION.V1, - url, - EMPTY_QUERY_PARAMS, - EMPTY_HEADERS, - payload, - callback - ); + if (multiTurnToken) { + payload.multiTurnToken = multiTurnToken; } - return { - callProfileNlu - }; + smapiHandle( + CONSTANTS.SMAPI.API_NAME.NLU_PROFILE, + CONSTANTS.HTTP_REQUEST.VERB.POST, + CONSTANTS.SMAPI.VERSION.V1, + url, + EMPTY_QUERY_PARAMS, + EMPTY_HEADERS, + payload, + callback, + ); + } + + return { + callProfileNlu, + }; }; diff --git a/lib/clients/smapi-client/resources/history.js b/lib/clients/smapi-client/resources/history.js index 7cc78b4d..74d95d82 100644 --- a/lib/clients/smapi-client/resources/history.js +++ b/lib/clients/smapi-client/resources/history.js @@ -1,40 +1,40 @@ -const R = require('ramda'); +const R = require("ramda"); -const CONSTANTS = require('@src/utils/constants'); +const CONSTANTS = require("../../../utils/constants"); const EMPTY_HEADERS = {}; const NULL_PAYLOAD = null; module.exports = (smapiHandle) => { - /** - * Get utterance transcripts for a skill - * @param {String} skillId | skill id - * @param {*} queryParameters | maxResults - * sortDirection - * sortField - * nextToken - * @param {function} callback | callback function from command - */ - function getIntentRequestsHistory(skillId, queryParams, callback) { - let queryObject = R.clone(queryParams); - if (R.isEmpty(queryObject)) { - queryObject = {}; - } - const url = `skills/${skillId}/history/intentRequests`; - - smapiHandle( - CONSTANTS.SMAPI.API_NAME.INTENT_REQUEST_HISTORY, - CONSTANTS.HTTP_REQUEST.VERB.GET, - CONSTANTS.SMAPI.VERSION.V1, - url, - queryObject, - EMPTY_HEADERS, - NULL_PAYLOAD, - callback - ); + /** + * Get utterance transcripts for a skill + * @param {String} skillId | skill id + * @param {*} queryParameters | maxResults + * sortDirection + * sortField + * nextToken + * @param {function} callback | callback function from command + */ + function getIntentRequestsHistory(skillId, queryParams, callback) { + let queryObject = R.clone(queryParams); + if (R.isEmpty(queryObject)) { + queryObject = {}; } + const url = `skills/${skillId}/history/intentRequests`; + + smapiHandle( + CONSTANTS.SMAPI.API_NAME.INTENT_REQUEST_HISTORY, + CONSTANTS.HTTP_REQUEST.VERB.GET, + CONSTANTS.SMAPI.VERSION.V1, + url, + queryObject, + EMPTY_HEADERS, + NULL_PAYLOAD, + callback, + ); + } - return { - getIntentRequestsHistory - }; + return { + getIntentRequestsHistory, + }; }; diff --git a/lib/clients/smapi-client/resources/interaction-model.js b/lib/clients/smapi-client/resources/interaction-model.js index f9595c3e..264b74ac 100644 --- a/lib/clients/smapi-client/resources/interaction-model.js +++ b/lib/clients/smapi-client/resources/interaction-model.js @@ -1,95 +1,95 @@ -const R = require('ramda'); +const R = require("ramda"); -const CONSTANTS = require('@src/utils/constants'); +const CONSTANTS = require("../../../utils/constants"); const EMPTY_HEADERS = {}; const EMPTY_QUERY_PARAMS = {}; const NULL_PAYLOAD = null; module.exports = (smapiHandle) => { - function getInteractionModel(skillId, stage, locale, callback) { - const url = `skills/${skillId}/stages/${stage}/interactionModel/locales/${locale}`; - smapiHandle( - CONSTANTS.SMAPI.API_NAME.GET_INTERACTION_MODEL, - CONSTANTS.HTTP_REQUEST.VERB.GET, - CONSTANTS.SMAPI.VERSION.V1, - url, - EMPTY_QUERY_PARAMS, - EMPTY_HEADERS, - NULL_PAYLOAD, - callback - ); - } + function getInteractionModel(skillId, stage, locale, callback) { + const url = `skills/${skillId}/stages/${stage}/interactionModel/locales/${locale}`; + smapiHandle( + CONSTANTS.SMAPI.API_NAME.GET_INTERACTION_MODEL, + CONSTANTS.HTTP_REQUEST.VERB.GET, + CONSTANTS.SMAPI.VERSION.V1, + url, + EMPTY_QUERY_PARAMS, + EMPTY_HEADERS, + NULL_PAYLOAD, + callback, + ); + } - function setInteractionModel(skillId, stage, locale, modelSchema, eTag, callback) { - const url = `skills/${skillId}/stages/${stage}/interactionModel/locales/${locale}`; - const payload = { - interactionModel: modelSchema.interactionModel - }; - smapiHandle( - CONSTANTS.SMAPI.API_NAME.SET_INTERACTION_MODEL, - CONSTANTS.HTTP_REQUEST.VERB.PUT, - CONSTANTS.SMAPI.VERSION.V1, - url, - EMPTY_QUERY_PARAMS, - eTag ? { 'If-Match': eTag } : {}, - payload, - callback - ); - } + function setInteractionModel(skillId, stage, locale, modelSchema, eTag, callback) { + const url = `skills/${skillId}/stages/${stage}/interactionModel/locales/${locale}`; + const payload = { + interactionModel: modelSchema.interactionModel, + }; + smapiHandle( + CONSTANTS.SMAPI.API_NAME.SET_INTERACTION_MODEL, + CONSTANTS.HTTP_REQUEST.VERB.PUT, + CONSTANTS.SMAPI.VERSION.V1, + url, + EMPTY_QUERY_PARAMS, + eTag ? {"If-Match": eTag} : {}, + payload, + callback, + ); + } - function headInteractionModel(skillId, stage, locale, callback) { - const url = `skills/${skillId}/stages/${stage}/interactionModel/locales/${locale}`; - smapiHandle( - CONSTANTS.SMAPI.API_NAME.HEAD_INTERACTION_MODEL, - CONSTANTS.HTTP_REQUEST.VERB.HEAD, - CONSTANTS.SMAPI.VERSION.V1, - url, - EMPTY_QUERY_PARAMS, - EMPTY_HEADERS, - NULL_PAYLOAD, - callback - ); - } + function headInteractionModel(skillId, stage, locale, callback) { + const url = `skills/${skillId}/stages/${stage}/interactionModel/locales/${locale}`; + smapiHandle( + CONSTANTS.SMAPI.API_NAME.HEAD_INTERACTION_MODEL, + CONSTANTS.HTTP_REQUEST.VERB.HEAD, + CONSTANTS.SMAPI.VERSION.V1, + url, + EMPTY_QUERY_PARAMS, + EMPTY_HEADERS, + NULL_PAYLOAD, + callback, + ); + } - /** - * List Interaction Model Versions for the skill. - * @param {string} skillId Skill ID to retrieve interaction model versions for - * @param {string} stage Skill stage to retrieve interaction model versions for - * @param {string} locale Skill locale to retrieve interaction model versions for - * @param {Object} queryParams Query parameters for the API - * @param {string} queryParams.nextToken token to get more model versions - * , after you receive a response with truncated results. Set it to the value of - * nextToken from the truncated response you just received. - * @param {string} queryParams.maxResults The max number of items to return in the - * response. Default maximum is 50. - * @param {string} queryParams.sortDirection Sets the sorting direction of the versions - * returned in the response. - * @param {string} queryParams.sortField Sets the field that the sorting is applied to. - * @param {Function} callback - */ - function listInteractionModelVersions(skillId, stage, locale, queryParams, callback) { - let queryObject = R.clone(queryParams); - if (!queryObject) { - queryObject = {}; - } - const url = `skills/${skillId}/stages/${stage}/interactionModel/locales/${locale}/versions`; - smapiHandle( - CONSTANTS.SMAPI.API_NAME.LIST_INTERACTION_MODEL_VERSIONS, - CONSTANTS.HTTP_REQUEST.VERB.GET, - CONSTANTS.SMAPI.VERSION.V1, - url, - queryObject, - EMPTY_HEADERS, - NULL_PAYLOAD, - callback - ); + /** + * List Interaction Model Versions for the skill. + * @param {string} skillId Skill ID to retrieve interaction model versions for + * @param {string} stage Skill stage to retrieve interaction model versions for + * @param {string} locale Skill locale to retrieve interaction model versions for + * @param {Object} queryParams Query parameters for the API + * @param {string} queryParams.nextToken token to get more model versions + * , after you receive a response with truncated results. Set it to the value of + * nextToken from the truncated response you just received. + * @param {string} queryParams.maxResults The max number of items to return in the + * response. Default maximum is 50. + * @param {string} queryParams.sortDirection Sets the sorting direction of the versions + * returned in the response. + * @param {string} queryParams.sortField Sets the field that the sorting is applied to. + * @param {Function} callback + */ + function listInteractionModelVersions(skillId, stage, locale, queryParams, callback) { + let queryObject = R.clone(queryParams); + if (!queryObject) { + queryObject = {}; } + const url = `skills/${skillId}/stages/${stage}/interactionModel/locales/${locale}/versions`; + smapiHandle( + CONSTANTS.SMAPI.API_NAME.LIST_INTERACTION_MODEL_VERSIONS, + CONSTANTS.HTTP_REQUEST.VERB.GET, + CONSTANTS.SMAPI.VERSION.V1, + url, + queryObject, + EMPTY_HEADERS, + NULL_PAYLOAD, + callback, + ); + } - return { - getInteractionModel, - setInteractionModel, - headInteractionModel, - listInteractionModelVersions - }; + return { + getInteractionModel, + setInteractionModel, + headInteractionModel, + listInteractionModelVersions, + }; }; diff --git a/lib/clients/smapi-client/resources/isp.js b/lib/clients/smapi-client/resources/isp.js index 83ad5d65..530ca1ff 100644 --- a/lib/clients/smapi-client/resources/isp.js +++ b/lib/clients/smapi-client/resources/isp.js @@ -1,247 +1,247 @@ -const R = require('ramda'); +const R = require("ramda"); -const CONSTANTS = require('@src/utils/constants'); +const CONSTANTS = require("../../../utils/constants"); -const ISP_URL_BASE = 'inSkillProducts'; +const ISP_URL_BASE = "inSkillProducts"; const EMPTY_HEADERS = {}; const EMPTY_QUERY_PARAMS = {}; const NULL_PAYLOAD = null; module.exports = (smapiHandle) => { - function createIsp(vendorId, ispDefinition, callback) { - const url = `${ISP_URL_BASE}/`; - const payload = { - vendorId, - inSkillProductDefinition: ispDefinition - }; - smapiHandle( - CONSTANTS.SMAPI.API_NAME.CREATE_ISP, - CONSTANTS.HTTP_REQUEST.VERB.POST, - CONSTANTS.SMAPI.VERSION.V1, - url, - EMPTY_QUERY_PARAMS, - EMPTY_HEADERS, - payload, - callback - ); - } - - function getIsp(ispId, stage, callback) { - const url = `${ISP_URL_BASE}/${ispId}/stages/${stage}`; - smapiHandle( - CONSTANTS.SMAPI.API_NAME.GET_ISP, - CONSTANTS.HTTP_REQUEST.VERB.GET, - CONSTANTS.SMAPI.VERSION.V1, - url, - EMPTY_QUERY_PARAMS, - EMPTY_HEADERS, - NULL_PAYLOAD, - callback - ); - } - - function getIspSummary(ispId, stage, callback) { - const url = `${ISP_URL_BASE}/${ispId}/stages/${stage}/summary`; - smapiHandle( - CONSTANTS.SMAPI.API_NAME.GET_ISP, - CONSTANTS.HTTP_REQUEST.VERB.GET, - CONSTANTS.SMAPI.VERSION.V1, - url, - EMPTY_QUERY_PARAMS, - EMPTY_HEADERS, - NULL_PAYLOAD, - callback - ); - } - - function updateIsp(ispId, stage, ispDefinition, eTag, callback) { - const url = `${ISP_URL_BASE}/${ispId}/stages/${stage}`; - const headers = eTag ? { 'If-Match': eTag } : {}; - const payload = { - inSkillProductDefinition: ispDefinition - }; - smapiHandle( - CONSTANTS.SMAPI.API_NAME.UPDATE_ISP, - CONSTANTS.HTTP_REQUEST.VERB.PUT, - CONSTANTS.SMAPI.VERSION.V1, - url, - EMPTY_QUERY_PARAMS, - headers, - payload, - callback - ); - } - - function associateIsp(ispId, skillId, callback) { - const url = `${ISP_URL_BASE}/${ispId}/skills/${skillId}`; - smapiHandle( - CONSTANTS.SMAPI.API_NAME.ASSOCIATE_ISP, - CONSTANTS.HTTP_REQUEST.VERB.PUT, - CONSTANTS.SMAPI.VERSION.V1, - url, - EMPTY_QUERY_PARAMS, - EMPTY_HEADERS, - NULL_PAYLOAD, - callback - ); + function createIsp(vendorId, ispDefinition, callback) { + const url = `${ISP_URL_BASE}/`; + const payload = { + vendorId, + inSkillProductDefinition: ispDefinition, + }; + smapiHandle( + CONSTANTS.SMAPI.API_NAME.CREATE_ISP, + CONSTANTS.HTTP_REQUEST.VERB.POST, + CONSTANTS.SMAPI.VERSION.V1, + url, + EMPTY_QUERY_PARAMS, + EMPTY_HEADERS, + payload, + callback, + ); + } + + function getIsp(ispId, stage, callback) { + const url = `${ISP_URL_BASE}/${ispId}/stages/${stage}`; + smapiHandle( + CONSTANTS.SMAPI.API_NAME.GET_ISP, + CONSTANTS.HTTP_REQUEST.VERB.GET, + CONSTANTS.SMAPI.VERSION.V1, + url, + EMPTY_QUERY_PARAMS, + EMPTY_HEADERS, + NULL_PAYLOAD, + callback, + ); + } + + function getIspSummary(ispId, stage, callback) { + const url = `${ISP_URL_BASE}/${ispId}/stages/${stage}/summary`; + smapiHandle( + CONSTANTS.SMAPI.API_NAME.GET_ISP, + CONSTANTS.HTTP_REQUEST.VERB.GET, + CONSTANTS.SMAPI.VERSION.V1, + url, + EMPTY_QUERY_PARAMS, + EMPTY_HEADERS, + NULL_PAYLOAD, + callback, + ); + } + + function updateIsp(ispId, stage, ispDefinition, eTag, callback) { + const url = `${ISP_URL_BASE}/${ispId}/stages/${stage}`; + const headers = eTag ? {"If-Match": eTag} : {}; + const payload = { + inSkillProductDefinition: ispDefinition, + }; + smapiHandle( + CONSTANTS.SMAPI.API_NAME.UPDATE_ISP, + CONSTANTS.HTTP_REQUEST.VERB.PUT, + CONSTANTS.SMAPI.VERSION.V1, + url, + EMPTY_QUERY_PARAMS, + headers, + payload, + callback, + ); + } + + function associateIsp(ispId, skillId, callback) { + const url = `${ISP_URL_BASE}/${ispId}/skills/${skillId}`; + smapiHandle( + CONSTANTS.SMAPI.API_NAME.ASSOCIATE_ISP, + CONSTANTS.HTTP_REQUEST.VERB.PUT, + CONSTANTS.SMAPI.VERSION.V1, + url, + EMPTY_QUERY_PARAMS, + EMPTY_HEADERS, + NULL_PAYLOAD, + callback, + ); + } + + function disassociateIsp(ispId, skillId, callback) { + const url = `${ISP_URL_BASE}/${ispId}/skills/${skillId}`; + smapiHandle( + CONSTANTS.SMAPI.API_NAME.DISASSOCIATE_ISP, + CONSTANTS.HTTP_REQUEST.VERB.DELETE, + CONSTANTS.SMAPI.VERSION.V1, + url, + EMPTY_QUERY_PARAMS, + EMPTY_HEADERS, + NULL_PAYLOAD, + callback, + ); + } + + /** + * List ISPs based on the vendor-id + * @param {string} vendorId vendor id of the in-skill product + * @param {Array} productIdList the array of in-skill product IDs + * @param {string} stage stage for the in-skill product + * @param {string} referenceName reference name for the in-skill product + * @param {string} status status for the in-skill product + * @param {string} type type for the in-skill product + * @param {Boolean} isAssociatedWithSkill whether or not the in-skill products are associated to a skill + * @param {Object} queryParams | nextToken + * | maxResults + * @param {*} callback + */ + function listIspForVendor(vendorId, productIdList, stage, referenceName, status, type, isAssociatedWithSkill, queryParams, callback) { + let queryObject = R.clone(queryParams); + if (!queryObject) { + queryObject = {}; } - - function disassociateIsp(ispId, skillId, callback) { - const url = `${ISP_URL_BASE}/${ispId}/skills/${skillId}`; - smapiHandle( - CONSTANTS.SMAPI.API_NAME.DISASSOCIATE_ISP, - CONSTANTS.HTTP_REQUEST.VERB.DELETE, - CONSTANTS.SMAPI.VERSION.V1, - url, - EMPTY_QUERY_PARAMS, - EMPTY_HEADERS, - NULL_PAYLOAD, - callback - ); + if (productIdList && productIdList.length > 0) { + queryObject.productId = productIdList.filter((id) => id); } - - /** - * List ISPs based on the vendor-id - * @param {string} vendorId vendor id of the in-skill product - * @param {Array} productIdList the array of in-skill product IDs - * @param {string} stage stage for the in-skill product - * @param {string} referenceName reference name for the in-skill product - * @param {string} status status for the in-skill product - * @param {string} type type for the in-skill product - * @param {Boolean} isAssociatedWithSkill whether or not the in-skill products are associated to a skill - * @param {Object} queryParams | nextToken - * | maxResults - * @param {*} callback - */ - function listIspForVendor(vendorId, productIdList, stage, referenceName, status, type, isAssociatedWithSkill, queryParams, callback) { - let queryObject = R.clone(queryParams); - if (!queryObject) { - queryObject = {}; - } - if (productIdList && productIdList.length > 0) { - queryObject.productId = productIdList.filter(id => id); - } - queryObject.vendorId = vendorId; - if (referenceName) { - queryObject.referenceName = referenceName; - } - - if (type) { - queryObject.type = type; - } - - if (stage) { - queryObject.stage = stage; - } - - if (status) { - queryObject.status = status; - } - - if (isAssociatedWithSkill) { - queryObject.isAssociatedWithSkill = isAssociatedWithSkill; - } - - const url = `${ISP_URL_BASE}`; - - smapiHandle( - CONSTANTS.SMAPI.API_NAME.LIST_ISP_FOR_VENDOR, - CONSTANTS.HTTP_REQUEST.VERB.GET, - CONSTANTS.SMAPI.VERSION.V1, - url, - queryObject, - EMPTY_HEADERS, - NULL_PAYLOAD, - callback - ); + queryObject.vendorId = vendorId; + if (referenceName) { + queryObject.referenceName = referenceName; } - /** - * List Isp based on the skill - * @param {*} skillId - * @param {*} stage - * @param {*} queryParams | nextToken - * | maxResults - * @param {*} callback - */ - function listIspForSkill(skillId, stage, queryParams, callback) { - const queryObject = R.clone(queryParams); - const url = `skills/${skillId}/stages/${stage}/${ISP_URL_BASE}`; - smapiHandle( - CONSTANTS.SMAPI.API_NAME.LIST_SKILLS_FOR_ISP, - CONSTANTS.HTTP_REQUEST.VERB.GET, - CONSTANTS.SMAPI.VERSION.V1, - url, - queryObject, - EMPTY_HEADERS, - NULL_PAYLOAD, - callback - ); + if (type) { + queryObject.type = type; } - /** - * List skills based on the isp - * @param {*} ispId - * @param {*} stage - * @param {*} queryParams | nextToken - * | maxResults - * @param {*} callback - */ - function listSkillsForIsp(ispId, stage, queryParams, callback) { - const queryObject = R.clone(queryParams); - const url = `${ISP_URL_BASE}/${ispId}/stages/${stage}/skills`; - smapiHandle( - CONSTANTS.SMAPI.API_NAME.LIST_SKILLS_FOR_ISP, - CONSTANTS.HTTP_REQUEST.VERB.GET, - CONSTANTS.SMAPI.VERSION.V1, - url, - queryObject, - EMPTY_HEADERS, - NULL_PAYLOAD, - callback - ); + if (stage) { + queryObject.stage = stage; } - function deleteIsp(ispId, stage, eTag, callback) { - const url = `${ISP_URL_BASE}/${ispId}/stages/${stage}`; - const headers = eTag ? { 'If-Match': eTag } : {}; - smapiHandle( - CONSTANTS.SMAPI.API_NAME.DELETE_ISP, - CONSTANTS.HTTP_REQUEST.VERB.DELETE, - CONSTANTS.SMAPI.VERSION.V1, - url, - EMPTY_QUERY_PARAMS, - headers, - NULL_PAYLOAD, - callback - ); + if (status) { + queryObject.status = status; } - function resetIspEntitlement(ispId, stage, callback) { - const url = `${ISP_URL_BASE}/${ispId}/stages/${stage}/entitlement`; - smapiHandle( - CONSTANTS.SMAPI.API_NAME.RESET_ISP_ENTITLEMENT, - CONSTANTS.HTTP_REQUEST.VERB.DELETE, - CONSTANTS.SMAPI.VERSION.V1, - url, - EMPTY_QUERY_PARAMS, - EMPTY_HEADERS, - NULL_PAYLOAD, - callback - ); + if (isAssociatedWithSkill) { + queryObject.isAssociatedWithSkill = isAssociatedWithSkill; } - return { - createIsp, - getIsp, - getIspSummary, - updateIsp, - associateIsp, - disassociateIsp, - listIspForVendor, - listIspForSkill, - listSkillsForIsp, - deleteIsp, - resetIspEntitlement - }; + const url = `${ISP_URL_BASE}`; + + smapiHandle( + CONSTANTS.SMAPI.API_NAME.LIST_ISP_FOR_VENDOR, + CONSTANTS.HTTP_REQUEST.VERB.GET, + CONSTANTS.SMAPI.VERSION.V1, + url, + queryObject, + EMPTY_HEADERS, + NULL_PAYLOAD, + callback, + ); + } + + /** + * List Isp based on the skill + * @param {*} skillId + * @param {*} stage + * @param {*} queryParams | nextToken + * | maxResults + * @param {*} callback + */ + function listIspForSkill(skillId, stage, queryParams, callback) { + const queryObject = R.clone(queryParams); + const url = `skills/${skillId}/stages/${stage}/${ISP_URL_BASE}`; + smapiHandle( + CONSTANTS.SMAPI.API_NAME.LIST_SKILLS_FOR_ISP, + CONSTANTS.HTTP_REQUEST.VERB.GET, + CONSTANTS.SMAPI.VERSION.V1, + url, + queryObject, + EMPTY_HEADERS, + NULL_PAYLOAD, + callback, + ); + } + + /** + * List skills based on the isp + * @param {*} ispId + * @param {*} stage + * @param {*} queryParams | nextToken + * | maxResults + * @param {*} callback + */ + function listSkillsForIsp(ispId, stage, queryParams, callback) { + const queryObject = R.clone(queryParams); + const url = `${ISP_URL_BASE}/${ispId}/stages/${stage}/skills`; + smapiHandle( + CONSTANTS.SMAPI.API_NAME.LIST_SKILLS_FOR_ISP, + CONSTANTS.HTTP_REQUEST.VERB.GET, + CONSTANTS.SMAPI.VERSION.V1, + url, + queryObject, + EMPTY_HEADERS, + NULL_PAYLOAD, + callback, + ); + } + + function deleteIsp(ispId, stage, eTag, callback) { + const url = `${ISP_URL_BASE}/${ispId}/stages/${stage}`; + const headers = eTag ? {"If-Match": eTag} : {}; + smapiHandle( + CONSTANTS.SMAPI.API_NAME.DELETE_ISP, + CONSTANTS.HTTP_REQUEST.VERB.DELETE, + CONSTANTS.SMAPI.VERSION.V1, + url, + EMPTY_QUERY_PARAMS, + headers, + NULL_PAYLOAD, + callback, + ); + } + + function resetIspEntitlement(ispId, stage, callback) { + const url = `${ISP_URL_BASE}/${ispId}/stages/${stage}/entitlement`; + smapiHandle( + CONSTANTS.SMAPI.API_NAME.RESET_ISP_ENTITLEMENT, + CONSTANTS.HTTP_REQUEST.VERB.DELETE, + CONSTANTS.SMAPI.VERSION.V1, + url, + EMPTY_QUERY_PARAMS, + EMPTY_HEADERS, + NULL_PAYLOAD, + callback, + ); + } + + return { + createIsp, + getIsp, + getIspSummary, + updateIsp, + associateIsp, + disassociateIsp, + listIspForVendor, + listIspForSkill, + listSkillsForIsp, + deleteIsp, + resetIspEntitlement, + }; }; diff --git a/lib/clients/smapi-client/resources/manifest.js b/lib/clients/smapi-client/resources/manifest.js deleted file mode 100644 index 6b3bbf74..00000000 --- a/lib/clients/smapi-client/resources/manifest.js +++ /dev/null @@ -1,42 +0,0 @@ -const CONSTANTS = require('@src/utils/constants'); - -const EMPTY_HEADERS = {}; -const EMPTY_QUERY_PARAMS = {}; -const NULL_PAYLOAD = null; - -module.exports = (smapiHandle) => { - function getManifest(skillId, stage, callback) { - const url = `skills/${skillId}/stages/${stage}/manifest`; - smapiHandle( - CONSTANTS.SMAPI.API_NAME.GET_MANIFEST, - CONSTANTS.HTTP_REQUEST.VERB.GET, - CONSTANTS.SMAPI.VERSION.V1, - url, - EMPTY_QUERY_PARAMS, - EMPTY_HEADERS, - NULL_PAYLOAD, - callback - ); - } - - function updateManifest(skillId, stage, manifest, eTag, callback) { - const url = `skills/${skillId}/stages/${stage}/manifest`; - const headers = eTag ? { 'If-Match': eTag } : {}; - const payload = { manifest: manifest.manifest }; - smapiHandle( - CONSTANTS.SMAPI.API_NAME.UPDATE_MANIFEST, - CONSTANTS.HTTP_REQUEST.VERB.PUT, - CONSTANTS.SMAPI.VERSION.V1, - url, - EMPTY_QUERY_PARAMS, - headers, - payload, - callback - ); - } - - return { - getManifest, - updateManifest - }; -}; diff --git a/lib/clients/smapi-client/resources/manifest.ts b/lib/clients/smapi-client/resources/manifest.ts new file mode 100644 index 00000000..f3e0b9c0 --- /dev/null +++ b/lib/clients/smapi-client/resources/manifest.ts @@ -0,0 +1,62 @@ +import CONSTANTS from "../../../utils/constants"; +import {v1} from "ask-smapi-model"; +import {SmapiRequest, SmapiRequestCallback, SmapiResponse} from ".."; + +const EMPTY_HEADERS = {}; +const EMPTY_QUERY_PARAMS = {}; +const NULL_PAYLOAD = null; + +export default (smapiHandle: SmapiRequest) => { + function getManifest(skillId: string, stage: string): Promise>; + function getManifest(skillId: string, stage: string, callback: SmapiRequestCallback): void; + function getManifest( + skillId: string, + stage: string, + callback?: SmapiRequestCallback, + ): Promise> | void { + const url = `skills/${skillId}/stages/${stage}/manifest`; + if (callback) { + return smapiHandle( + CONSTANTS.SMAPI.API_NAME.GET_MANIFEST, + CONSTANTS.HTTP_REQUEST.VERB.GET, + CONSTANTS.SMAPI.VERSION.V1, + url, + EMPTY_QUERY_PARAMS, + EMPTY_HEADERS, + NULL_PAYLOAD, + callback, + ); + } else { + return smapiHandle( + CONSTANTS.SMAPI.API_NAME.GET_MANIFEST, + CONSTANTS.HTTP_REQUEST.VERB.GET, + CONSTANTS.SMAPI.VERSION.V1, + url, + EMPTY_QUERY_PARAMS, + EMPTY_HEADERS, + NULL_PAYLOAD, + ); + } + } + + function updateManifest(skillId: string, stage: string, manifest: any, eTag: string, callback: SmapiRequestCallback) { + const url = `skills/${skillId}/stages/${stage}/manifest`; + const headers = eTag ? {"If-Match": eTag} : {}; + const payload = {manifest: manifest.manifest}; + smapiHandle( + CONSTANTS.SMAPI.API_NAME.UPDATE_MANIFEST, + CONSTANTS.HTTP_REQUEST.VERB.PUT, + CONSTANTS.SMAPI.VERSION.V1, + url, + EMPTY_QUERY_PARAMS, + headers, + payload, + callback, + ); + } + + return { + getManifest, + updateManifest, + }; +}; diff --git a/lib/clients/smapi-client/resources/private-skill.js b/lib/clients/smapi-client/resources/private-skill.js index cdef4f9a..fc31ae28 100644 --- a/lib/clients/smapi-client/resources/private-skill.js +++ b/lib/clients/smapi-client/resources/private-skill.js @@ -1,69 +1,69 @@ -const R = require('ramda'); +const R = require("ramda"); -const CONSTANTS = require('@src/utils/constants'); +const CONSTANTS = require("../../../utils/constants"); const EMPTY_HEADERS = {}; const EMPTY_QUERY_PARAMS = {}; const NULL_PAYLOAD = null; module.exports = (smapiHandle) => { - function addPrivateDistributionAccount(skillId, stage, accountId, callback) { - const url = `skills/${skillId}/stages/${stage}/privateDistributionAccounts/${accountId}`; - smapiHandle( - CONSTANTS.SMAPI.API_NAME.ADD_PRIVATE_DISTRIBUTION_ACCOUNT, - CONSTANTS.HTTP_REQUEST.VERB.PUT, - CONSTANTS.SMAPI.VERSION.V1, - url, - EMPTY_QUERY_PARAMS, - EMPTY_HEADERS, - NULL_PAYLOAD, - callback - ); - } + function addPrivateDistributionAccount(skillId, stage, accountId, callback) { + const url = `skills/${skillId}/stages/${stage}/privateDistributionAccounts/${accountId}`; + smapiHandle( + CONSTANTS.SMAPI.API_NAME.ADD_PRIVATE_DISTRIBUTION_ACCOUNT, + CONSTANTS.HTTP_REQUEST.VERB.PUT, + CONSTANTS.SMAPI.VERSION.V1, + url, + EMPTY_QUERY_PARAMS, + EMPTY_HEADERS, + NULL_PAYLOAD, + callback, + ); + } - /** - * List accounts for private skill - * @param {*} skillId - * @param {*} stage - * @param {*} queryParams | nextToken - * | maxResults - * @param {*} callback - */ - function listPrivateDistributionAccounts(skillId, stage, queryParams, callback) { - const url = `skills/${skillId}/stages/${stage}/privateDistributionAccounts`; - const queryObject = R.clone(queryParams); - if (queryObject && !queryObject.maxResults) { - queryObject.maxResults = 50; - } - smapiHandle( - CONSTANTS.SMAPI.API_NAME.LIST_PRIVATE_DISTRIBUTION_ACCOUNTS, - CONSTANTS.HTTP_REQUEST.VERB.GET, - CONSTANTS.SMAPI.VERSION.V1, - url, - queryObject, - EMPTY_HEADERS, - NULL_PAYLOAD, - callback - ); + /** + * List accounts for private skill + * @param {*} skillId + * @param {*} stage + * @param {*} queryParams | nextToken + * | maxResults + * @param {*} callback + */ + function listPrivateDistributionAccounts(skillId, stage, queryParams, callback) { + const url = `skills/${skillId}/stages/${stage}/privateDistributionAccounts`; + const queryObject = R.clone(queryParams); + if (queryObject && !queryObject.maxResults) { + queryObject.maxResults = 50; } + smapiHandle( + CONSTANTS.SMAPI.API_NAME.LIST_PRIVATE_DISTRIBUTION_ACCOUNTS, + CONSTANTS.HTTP_REQUEST.VERB.GET, + CONSTANTS.SMAPI.VERSION.V1, + url, + queryObject, + EMPTY_HEADERS, + NULL_PAYLOAD, + callback, + ); + } - function deletePrivateDistributionAccount(skillId, stage, accountId, callback) { - const url = `skills/${skillId}/stages/${stage}/privateDistributionAccounts/${accountId}`; - smapiHandle( - CONSTANTS.SMAPI.API_NAME.DELETE_PRIVATE_DISTRIBUTION_ACCOUNT, - CONSTANTS.HTTP_REQUEST.VERB.DELETE, - CONSTANTS.SMAPI.VERSION.V1, - url, - EMPTY_QUERY_PARAMS, - EMPTY_HEADERS, - NULL_PAYLOAD, - callback - ); - } + function deletePrivateDistributionAccount(skillId, stage, accountId, callback) { + const url = `skills/${skillId}/stages/${stage}/privateDistributionAccounts/${accountId}`; + smapiHandle( + CONSTANTS.SMAPI.API_NAME.DELETE_PRIVATE_DISTRIBUTION_ACCOUNT, + CONSTANTS.HTTP_REQUEST.VERB.DELETE, + CONSTANTS.SMAPI.VERSION.V1, + url, + EMPTY_QUERY_PARAMS, + EMPTY_HEADERS, + NULL_PAYLOAD, + callback, + ); + } - return { - addPrivateDistributionAccount, - listPrivateDistributionAccounts, - deletePrivateDistributionAccount - }; + return { + addPrivateDistributionAccount, + listPrivateDistributionAccounts, + deletePrivateDistributionAccount, + }; }; diff --git a/lib/clients/smapi-client/resources/publishing.js b/lib/clients/smapi-client/resources/publishing.js index 7701dca5..4f9a9903 100644 --- a/lib/clients/smapi-client/resources/publishing.js +++ b/lib/clients/smapi-client/resources/publishing.js @@ -1,102 +1,102 @@ -const R = require('ramda'); +const R = require("ramda"); -const CONSTANTS = require('@src/utils/constants'); +const CONSTANTS = require("../../../utils/constants"); const EMPTY_HEADERS = {}; const EMPTY_QUERY_PARAMS = {}; const NULL_PAYLOAD = null; module.exports = (smapiHandle) => { - function submitSkill(skillId, callback) { - const url = `skills/${skillId}/submit`; - smapiHandle( - CONSTANTS.SMAPI.API_NAME.SUBMIT, - CONSTANTS.HTTP_REQUEST.VERB.POST, - CONSTANTS.SMAPI.VERSION.V1, - url, - EMPTY_QUERY_PARAMS, - EMPTY_HEADERS, - NULL_PAYLOAD, - callback - ); - } + function submitSkill(skillId, callback) { + const url = `skills/${skillId}/submit`; + smapiHandle( + CONSTANTS.SMAPI.API_NAME.SUBMIT, + CONSTANTS.HTTP_REQUEST.VERB.POST, + CONSTANTS.SMAPI.VERSION.V1, + url, + EMPTY_QUERY_PARAMS, + EMPTY_HEADERS, + NULL_PAYLOAD, + callback, + ); + } - function withdrawSkill(skillId, withdrawReason, withdrawMessage, callback) { - const url = `skills/${skillId}/withdraw`; - const payload = { - reason: withdrawReason, - message: withdrawMessage - }; - smapiHandle( - CONSTANTS.SMAPI.API_NAME.WITHDRAW, - CONSTANTS.HTTP_REQUEST.VERB.POST, - CONSTANTS.SMAPI.VERSION.V1, - url, - EMPTY_QUERY_PARAMS, - EMPTY_HEADERS, - payload, - callback - ); - } + function withdrawSkill(skillId, withdrawReason, withdrawMessage, callback) { + const url = `skills/${skillId}/withdraw`; + const payload = { + reason: withdrawReason, + message: withdrawMessage, + }; + smapiHandle( + CONSTANTS.SMAPI.API_NAME.WITHDRAW, + CONSTANTS.HTTP_REQUEST.VERB.POST, + CONSTANTS.SMAPI.VERSION.V1, + url, + EMPTY_QUERY_PARAMS, + EMPTY_HEADERS, + payload, + callback, + ); + } - /** - * List Certifications based on the skill-id. - * @param {string} skillId Skill ID to retrieve certifications for - * @param {Object} queryParams Query parameters for the API - * @param {string} queryParams.nextToken token to get more certification - * reviews, after you receive a response with truncated results. Set it to the value of - * nextToken from the truncated response you just received. - * @param {string} queryParams.maxResults The max number of items to return in the - * response. Default maximum is 50. - * @param {Function} callback - */ - function listCertifications(skillId, queryParams, callback) { - let queryObject = R.clone(queryParams); - if (!queryObject) { - queryObject = {}; - } - const url = `skills/${skillId}/certifications`; - smapiHandle( - CONSTANTS.SMAPI.API_NAME.LIST_CERTIFICATIONS, - CONSTANTS.HTTP_REQUEST.VERB.GET, - CONSTANTS.SMAPI.VERSION.V1, - url, - queryObject, - EMPTY_HEADERS, - NULL_PAYLOAD, - callback - ); + /** + * List Certifications based on the skill-id. + * @param {string} skillId Skill ID to retrieve certifications for + * @param {Object} queryParams Query parameters for the API + * @param {string} queryParams.nextToken token to get more certification + * reviews, after you receive a response with truncated results. Set it to the value of + * nextToken from the truncated response you just received. + * @param {string} queryParams.maxResults The max number of items to return in the + * response. Default maximum is 50. + * @param {Function} callback + */ + function listCertifications(skillId, queryParams, callback) { + let queryObject = R.clone(queryParams); + if (!queryObject) { + queryObject = {}; } + const url = `skills/${skillId}/certifications`; + smapiHandle( + CONSTANTS.SMAPI.API_NAME.LIST_CERTIFICATIONS, + CONSTANTS.HTTP_REQUEST.VERB.GET, + CONSTANTS.SMAPI.VERSION.V1, + url, + queryObject, + EMPTY_HEADERS, + NULL_PAYLOAD, + callback, + ); + } - /** - * Get details about a specific certification review based on the skill-id. - * @param {string} skillId Skill ID to retrieve certifications for - * @param {string} certificationId Certification ID for Skill to retrieve certifications for - * @param {string} acceptLanguage Language to receive localized response - * @param {Function} callback - */ - function getCertification(skillId, certificationId, acceptLanguage, callback) { - const url = `skills/${skillId}/certifications/${certificationId}`; - const headers = {}; - if (acceptLanguage) { - headers['Accept-Language'] = acceptLanguage; - } - smapiHandle( - CONSTANTS.SMAPI.API_NAME.GET_CERTIFICATION, - CONSTANTS.HTTP_REQUEST.VERB.GET, - CONSTANTS.SMAPI.VERSION.V1, - url, - EMPTY_QUERY_PARAMS, - headers, - NULL_PAYLOAD, - callback - ); + /** + * Get details about a specific certification review based on the skill-id. + * @param {string} skillId Skill ID to retrieve certifications for + * @param {string} certificationId Certification ID for Skill to retrieve certifications for + * @param {string} acceptLanguage Language to receive localized response + * @param {Function} callback + */ + function getCertification(skillId, certificationId, acceptLanguage, callback) { + const url = `skills/${skillId}/certifications/${certificationId}`; + const headers = {}; + if (acceptLanguage) { + headers["Accept-Language"] = acceptLanguage; } + smapiHandle( + CONSTANTS.SMAPI.API_NAME.GET_CERTIFICATION, + CONSTANTS.HTTP_REQUEST.VERB.GET, + CONSTANTS.SMAPI.VERSION.V1, + url, + EMPTY_QUERY_PARAMS, + headers, + NULL_PAYLOAD, + callback, + ); + } - return { - submitSkill, - withdrawSkill, - listCertifications, - getCertification - }; + return { + submitSkill, + withdrawSkill, + listCertifications, + getCertification, + }; }; diff --git a/lib/clients/smapi-client/resources/skill-package.js b/lib/clients/smapi-client/resources/skill-package.js index 932b2274..7c2c2502 100644 --- a/lib/clients/smapi-client/resources/skill-package.js +++ b/lib/clients/smapi-client/resources/skill-package.js @@ -1,92 +1,92 @@ -const CONSTANTS = require('@src/utils/constants'); -const stringUtils = require('@src/utils/string-utils'); +const CONSTANTS = require("../../../utils/constants"); +const stringUtils = require("../../../utils/string-utils"); const EMPTY_HEADERS = {}; const EMPTY_QUERY_PARAMS = {}; const NULL_PAYLOAD = null; module.exports = (smapiHandle) => { - function createUpload(callback) { - const url = 'skills/uploads'; - smapiHandle( - CONSTANTS.SMAPI.API_NAME.CREATE_UPLOAD, - CONSTANTS.HTTP_REQUEST.VERB.POST, - CONSTANTS.SMAPI.VERSION.V1, - url, - EMPTY_QUERY_PARAMS, - EMPTY_HEADERS, - NULL_PAYLOAD, - callback - ); - } + function createUpload(callback) { + const url = "skills/uploads"; + smapiHandle( + CONSTANTS.SMAPI.API_NAME.CREATE_UPLOAD, + CONSTANTS.HTTP_REQUEST.VERB.POST, + CONSTANTS.SMAPI.VERSION.V1, + url, + EMPTY_QUERY_PARAMS, + EMPTY_HEADERS, + NULL_PAYLOAD, + callback, + ); + } - function importPackage(skillId, vendorId, location, callback) { - const url = stringUtils.isNonBlankString(skillId) ? `skills/${skillId}/imports` : 'skills/imports'; - const payload = { - location - }; - if (stringUtils.isNonBlankString(vendorId)) { - payload.vendorId = vendorId; - } - smapiHandle( - CONSTANTS.SMAPI.API_NAME.IMPORT_PACKAGE, - CONSTANTS.HTTP_REQUEST.VERB.POST, - CONSTANTS.SMAPI.VERSION.V1, - url, - EMPTY_QUERY_PARAMS, - EMPTY_HEADERS, - payload, - callback - ); + function importPackage(skillId, vendorId, location, callback) { + const url = stringUtils.isNonBlankString(skillId) ? `skills/${skillId}/imports` : "skills/imports"; + const payload = { + location, + }; + if (stringUtils.isNonBlankString(vendorId)) { + payload.vendorId = vendorId; } + smapiHandle( + CONSTANTS.SMAPI.API_NAME.IMPORT_PACKAGE, + CONSTANTS.HTTP_REQUEST.VERB.POST, + CONSTANTS.SMAPI.VERSION.V1, + url, + EMPTY_QUERY_PARAMS, + EMPTY_HEADERS, + payload, + callback, + ); + } - function getImportStatus(importId, callback) { - const url = `skills/imports/${importId}`; - smapiHandle( - CONSTANTS.SMAPI.API_NAME.GET_IMPORT_STATUS, - CONSTANTS.HTTP_REQUEST.VERB.GET, - CONSTANTS.SMAPI.VERSION.V1, - url, - EMPTY_QUERY_PARAMS, - EMPTY_HEADERS, - NULL_PAYLOAD, - callback - ); - } + function getImportStatus(importId, callback) { + const url = `skills/imports/${importId}`; + smapiHandle( + CONSTANTS.SMAPI.API_NAME.GET_IMPORT_STATUS, + CONSTANTS.HTTP_REQUEST.VERB.GET, + CONSTANTS.SMAPI.VERSION.V1, + url, + EMPTY_QUERY_PARAMS, + EMPTY_HEADERS, + NULL_PAYLOAD, + callback, + ); + } - function exportPackage(skillId, stage, callback) { - const url = `skills/${skillId}/stages/${stage}/exports`; - smapiHandle( - CONSTANTS.SMAPI.API_NAME.EXPORT_PACKAGE, - CONSTANTS.HTTP_REQUEST.VERB.POST, - CONSTANTS.SMAPI.VERSION.V1, - url, - EMPTY_QUERY_PARAMS, - EMPTY_HEADERS, - NULL_PAYLOAD, - callback - ); - } + function exportPackage(skillId, stage, callback) { + const url = `skills/${skillId}/stages/${stage}/exports`; + smapiHandle( + CONSTANTS.SMAPI.API_NAME.EXPORT_PACKAGE, + CONSTANTS.HTTP_REQUEST.VERB.POST, + CONSTANTS.SMAPI.VERSION.V1, + url, + EMPTY_QUERY_PARAMS, + EMPTY_HEADERS, + NULL_PAYLOAD, + callback, + ); + } - function getExportStatus(exportId, callback) { - const url = `skills/exports/${exportId}`; - smapiHandle( - CONSTANTS.SMAPI.API_NAME.GET_EXPORT_STATUS, - CONSTANTS.HTTP_REQUEST.VERB.GET, - CONSTANTS.SMAPI.VERSION.V1, - url, - EMPTY_QUERY_PARAMS, - EMPTY_HEADERS, - NULL_PAYLOAD, - callback - ); - } + function getExportStatus(exportId, callback) { + const url = `skills/exports/${exportId}`; + smapiHandle( + CONSTANTS.SMAPI.API_NAME.GET_EXPORT_STATUS, + CONSTANTS.HTTP_REQUEST.VERB.GET, + CONSTANTS.SMAPI.VERSION.V1, + url, + EMPTY_QUERY_PARAMS, + EMPTY_HEADERS, + NULL_PAYLOAD, + callback, + ); + } - return { - createUpload, - importPackage, - getImportStatus, - exportPackage, - getExportStatus - }; + return { + createUpload, + importPackage, + getImportStatus, + exportPackage, + getExportStatus, + }; }; diff --git a/lib/clients/smapi-client/resources/skill.js b/lib/clients/smapi-client/resources/skill.js deleted file mode 100644 index 53814af4..00000000 --- a/lib/clients/smapi-client/resources/skill.js +++ /dev/null @@ -1,279 +0,0 @@ -const R = require('ramda'); -const querystring = require('querystring'); - -const CONSTANTS = require('@src/utils/constants'); - -const ISP_URL_BASE = 'inSkillProducts'; -const EMPTY_HEADERS = {}; -const EMPTY_QUERY_PARAMS = {}; -const NULL_PAYLOAD = null; - -module.exports = (smapiHandle) => { - function createSkill(manifest, vendorId, callback) { - const url = 'skills/'; - const payload = { - vendorId, - manifest: manifest.manifest - }; - smapiHandle( - CONSTANTS.SMAPI.API_NAME.CREATE_SKILL, - CONSTANTS.HTTP_REQUEST.VERB.POST, - CONSTANTS.SMAPI.VERSION.V1, - url, - EMPTY_QUERY_PARAMS, - EMPTY_HEADERS, - payload, - callback - ); - } - - function deleteSkill(skillId, callback) { - const url = `skills/${skillId}`; - smapiHandle( - CONSTANTS.SMAPI.API_NAME.DELETE_SKILL, - CONSTANTS.HTTP_REQUEST.VERB.DELETE, - CONSTANTS.SMAPI.VERSION.V1, - url, - EMPTY_QUERY_PARAMS, - EMPTY_HEADERS, - NULL_PAYLOAD, - callback - ); - } - - /** - * List skills based on the vendor-id - * @param {*} vendorId - * @param {*} queryParams | nextToken - * | maxResults - * @param {*} callback - */ - function listSkills(vendorId, queryParams, callback) { - let queryObject = R.clone(queryParams); - if (!queryObject) { - queryObject = {}; - } - queryObject.vendorId = vendorId; - if (queryObject && !queryObject.maxResults) { - queryObject.maxResults = CONSTANTS.SMAPI.DEFAULT_MAX_RESULT_PER_PAGE; - } - const url = 'skills'; - smapiHandle( - CONSTANTS.SMAPI.API_NAME.LIST_SKILLS, - CONSTANTS.HTTP_REQUEST.VERB.GET, - CONSTANTS.SMAPI.VERSION.V1, - url, - queryObject, - EMPTY_HEADERS, - NULL_PAYLOAD, - callback - ); - } - - function getSkillStatus(skillId, resourcesList, callback) { - let url = `skills/${skillId}/status`; - if (resourcesList && resourcesList.length !== 0) { - url += `?${querystring.stringify({ resource: resourcesList })}`; - } - smapiHandle( - CONSTANTS.SMAPI.API_NAME.GET_SKILL_STATUS, - CONSTANTS.HTTP_REQUEST.VERB.GET, - CONSTANTS.SMAPI.VERSION.V1, - url, - EMPTY_QUERY_PARAMS, - EMPTY_HEADERS, - NULL_PAYLOAD, - callback - ); - } - - function enableSkill(skillId, stage, callback) { - const url = `skills/${skillId}/stages/${stage}/enablement`; - smapiHandle( - CONSTANTS.SMAPI.API_NAME.ENABLE_SKILL, - CONSTANTS.HTTP_REQUEST.VERB.PUT, - CONSTANTS.SMAPI.VERSION.V1, - url, - EMPTY_QUERY_PARAMS, - EMPTY_HEADERS, - NULL_PAYLOAD, - callback - ); - } - - function disableSkill(skillId, stage, callback) { - const url = `skills/${skillId}/stages/${stage}/enablement`; - smapiHandle( - CONSTANTS.SMAPI.API_NAME.DISABLE_SKILL, - CONSTANTS.HTTP_REQUEST.VERB.DELETE, - CONSTANTS.SMAPI.VERSION.V1, - url, - EMPTY_QUERY_PARAMS, - EMPTY_HEADERS, - NULL_PAYLOAD, - callback - ); - } - - function getSkillEnablement(skillId, stage, callback) { - const url = `skills/${skillId}/stages/${stage}/enablement`; - smapiHandle( - CONSTANTS.SMAPI.API_NAME.GET_SKILL_ENABLEMENT, - CONSTANTS.HTTP_REQUEST.VERB.GET, - CONSTANTS.SMAPI.VERSION.V1, - url, - EMPTY_QUERY_PARAMS, - EMPTY_HEADERS, - NULL_PAYLOAD, - callback - ); - } - - function getSkillCredentials(skillId, callback) { - const url = `skills/${skillId}/credentials`; - smapiHandle( - CONSTANTS.SMAPI.API_NAME.GET_SKILL_CREDENTIALS, - CONSTANTS.HTTP_REQUEST.VERB.GET, - CONSTANTS.SMAPI.VERSION.V1, - url, - EMPTY_QUERY_PARAMS, - EMPTY_HEADERS, - NULL_PAYLOAD, - callback - ); - } - - function validateSkill(skillId, stage, locales, callback) { - const url = `skills/${skillId}/stages/${stage}/validations`; - const payload = { - locales: locales.trim().split(/[\s,]+/) // comma or space deliminater regex - }; - smapiHandle( - CONSTANTS.SMAPI.API_NAME.VALIDATE_SKILL, - CONSTANTS.HTTP_REQUEST.VERB.POST, - CONSTANTS.SMAPI.VERSION.V1, - url, - EMPTY_QUERY_PARAMS, - EMPTY_HEADERS, - payload, - callback - ); - } - - function getValidation(skillId, stage, validationId, callback) { - const url = `skills/${skillId}/stages/${stage}/validations/${validationId}`; - smapiHandle( - CONSTANTS.SMAPI.API_NAME.GET_VALIDATION, - CONSTANTS.HTTP_REQUEST.VERB.GET, - CONSTANTS.SMAPI.VERSION.V1, - url, - EMPTY_QUERY_PARAMS, - EMPTY_HEADERS, - NULL_PAYLOAD, - callback - ); - } - - /** - * List ISPs based on the skill-id. - * @param {*} skillId - * @param {*} stage - * @param {*} queryParams | nextToken - * | maxResults - * @param {*} callback - */ - function listIspForSkill(skillId, stage, queryParams, callback) { - const queryObject = R.clone(queryParams); - if (queryObject && !queryObject.maxResults) { - queryObject.maxResults = CONSTANTS.SMAPI.DEFAULT_MAX_RESULT_PER_PAGE; - } - const url = `skills/${skillId}/stages/${stage}/${ISP_URL_BASE}`; - smapiHandle( - CONSTANTS.SMAPI.API_NAME.LIST_ISP_FOR_SKILL, - CONSTANTS.HTTP_REQUEST.VERB.GET, - CONSTANTS.SMAPI.VERSION.V1, - url, - queryObject, - EMPTY_HEADERS, - NULL_PAYLOAD, - callback - ); - } - - /** - * Get calculated metrics, insights and advanced analytics report for skills usage. - * @param {String} skillId [required] Unique identifier of skill. - * @param {String} startTime [required] The start time of query. - * @param {String} endTime [required] The end time of the query. The maximum duration is one week. - * @param {Enum} period [required] The aggregation period that is used when retrieving the metric. The values are SINGLE, PT15M, PT1H, P1D. - * @param {Enum} metric [required] A distinct set of logic that predictably returns a set of data. - * @param {Enum} stage [required] This parameter shows the stage of the skill. The accepted values are: live or development. - * @param {Enum} skillType [required] The type of skill. Potential values are: custom, smartHome, or flashBriefing. - * @param {String} intent The skill intent. - * @param {String} locale The locale of the skill. - * @param {String} maxResults The maximum number of results to display per page (100,000 is the maximum number of results). - * @param {String} nextToken The continuation token returned in response to an object of the last get metrics report response. - * @param {callback} callback callback function - */ - function getMetrics(skillId, startTime, endTime, period, metric, stage, skillType, - intent, locale, maxResults, nextToken, callback) { - const queryObject = {}; - if (startTime) { - queryObject.startTime = startTime; - } - if (endTime) { - queryObject.endTime = endTime; - } - if (period) { - queryObject.period = period; - } - if (metric) { - queryObject.metric = metric; - } - if (stage) { - queryObject.stage = stage; - } - if (skillType) { - queryObject.skillType = skillType; - } - if (intent) { - queryObject.intent = intent; - } - if (locale) { - queryObject.locale = locale; - } - - queryObject.maxResults = maxResults || CONSTANTS.SMAPI.DEFAULT_MAX_RESULT_PER_PAGE; - - if (nextToken) { - queryObject.nextToken = nextToken; - } - - const url = `skills/${skillId}/metrics`; - smapiHandle( - CONSTANTS.SMAPI.API_NAME.GET_METRICS, - CONSTANTS.HTTP_REQUEST.VERB.GET, - CONSTANTS.SMAPI.VERSION.V1, - url, - queryObject, - EMPTY_HEADERS, - NULL_PAYLOAD, - callback - ); - } - - return { - createSkill, - deleteSkill, - listSkills, - getSkillStatus, - enableSkill, - disableSkill, - getSkillEnablement, - getSkillCredentials, - validateSkill, - getValidation, - listIspForSkill, - getMetrics - }; -}; diff --git a/lib/clients/smapi-client/resources/skill.ts b/lib/clients/smapi-client/resources/skill.ts new file mode 100644 index 00000000..61248366 --- /dev/null +++ b/lib/clients/smapi-client/resources/skill.ts @@ -0,0 +1,310 @@ +import {SmapiRequest, SmapiRequestCallback, SmapiResponse} from ".."; + +import R from "ramda"; +import querystring from "querystring"; +import CONSTANTS from "../../../utils/constants"; + +const ISP_URL_BASE = "inSkillProducts"; +const EMPTY_HEADERS = {}; +const EMPTY_QUERY_PARAMS = {}; +const NULL_PAYLOAD = null; + +export default (smapiHandle: SmapiRequest) => { + function createSkill(manifest: any, vendorId: string, callback: SmapiRequestCallback) { + const url = "skills/"; + const payload = { + vendorId, + manifest: manifest.manifest, + }; + smapiHandle( + CONSTANTS.SMAPI.API_NAME.CREATE_SKILL, + CONSTANTS.HTTP_REQUEST.VERB.POST, + CONSTANTS.SMAPI.VERSION.V1, + url, + EMPTY_QUERY_PARAMS, + EMPTY_HEADERS, + payload, + callback, + ); + } + + function deleteSkill(skillId: string, callback: SmapiRequestCallback) { + const url = `skills/${skillId}`; + smapiHandle( + CONSTANTS.SMAPI.API_NAME.DELETE_SKILL, + CONSTANTS.HTTP_REQUEST.VERB.DELETE, + CONSTANTS.SMAPI.VERSION.V1, + url, + EMPTY_QUERY_PARAMS, + EMPTY_HEADERS, + NULL_PAYLOAD, + callback, + ); + } + + /** + * List skills based on the vendor-id + * @param {*} vendorId + * @param {*} queryParams | nextToken + * | maxResults + * @param {*} callback + */ + function listSkills(vendorId: string, queryParams: querystring.ParsedUrlQueryInput, callback: SmapiRequestCallback) { + let queryObject = R.clone(queryParams); + if (!queryObject) { + queryObject = {}; + } + queryObject.vendorId = vendorId; + if (queryObject && !queryObject.maxResults) { + queryObject.maxResults = CONSTANTS.SMAPI.DEFAULT_MAX_RESULT_PER_PAGE; + } + const url = "skills"; + smapiHandle( + CONSTANTS.SMAPI.API_NAME.LIST_SKILLS, + CONSTANTS.HTTP_REQUEST.VERB.GET, + CONSTANTS.SMAPI.VERSION.V1, + url, + queryObject, + EMPTY_HEADERS, + NULL_PAYLOAD, + callback, + ); + } + + function getSkillStatus(skillId: string, resourcesList: string[], callback: SmapiRequestCallback) { + let url = `skills/${skillId}/status`; + if (resourcesList && resourcesList.length !== 0) { + url += `?${querystring.stringify({resource: resourcesList})}`; + } + smapiHandle( + CONSTANTS.SMAPI.API_NAME.GET_SKILL_STATUS, + CONSTANTS.HTTP_REQUEST.VERB.GET, + CONSTANTS.SMAPI.VERSION.V1, + url, + EMPTY_QUERY_PARAMS, + EMPTY_HEADERS, + NULL_PAYLOAD, + callback, + ); + } + + function enableSkill(skillId: string, stage: string, callback: SmapiRequestCallback) { + const url = `skills/${skillId}/stages/${stage}/enablement`; + smapiHandle( + CONSTANTS.SMAPI.API_NAME.ENABLE_SKILL, + CONSTANTS.HTTP_REQUEST.VERB.PUT, + CONSTANTS.SMAPI.VERSION.V1, + url, + EMPTY_QUERY_PARAMS, + EMPTY_HEADERS, + NULL_PAYLOAD, + callback, + ); + } + + function disableSkill(skillId: string, stage: string, callback: SmapiRequestCallback) { + const url = `skills/${skillId}/stages/${stage}/enablement`; + smapiHandle( + CONSTANTS.SMAPI.API_NAME.DISABLE_SKILL, + CONSTANTS.HTTP_REQUEST.VERB.DELETE, + CONSTANTS.SMAPI.VERSION.V1, + url, + EMPTY_QUERY_PARAMS, + EMPTY_HEADERS, + NULL_PAYLOAD, + callback, + ); + } + + function getSkillEnablement(skillId: string, stage: string): Promise>; + function getSkillEnablement(skillId: string, stage: string, callback: SmapiRequestCallback): void; + function getSkillEnablement(skillId: string, stage: string, callback?: SmapiRequestCallback): Promise> | void { + const url = `skills/${skillId}/stages/${stage}/enablement`; + if (callback) { + return smapiHandle( + CONSTANTS.SMAPI.API_NAME.GET_SKILL_ENABLEMENT, + CONSTANTS.HTTP_REQUEST.VERB.GET, + CONSTANTS.SMAPI.VERSION.V1, + url, + EMPTY_QUERY_PARAMS, + EMPTY_HEADERS, + NULL_PAYLOAD, + callback, + ); + } + return smapiHandle( + CONSTANTS.SMAPI.API_NAME.GET_SKILL_ENABLEMENT, + CONSTANTS.HTTP_REQUEST.VERB.GET, + CONSTANTS.SMAPI.VERSION.V1, + url, + EMPTY_QUERY_PARAMS, + EMPTY_HEADERS, + NULL_PAYLOAD, + ); + } + + function getSkillCredentials(skillId: string, callback: SmapiRequestCallback) { + const url = `skills/${skillId}/credentials`; + smapiHandle( + CONSTANTS.SMAPI.API_NAME.GET_SKILL_CREDENTIALS, + CONSTANTS.HTTP_REQUEST.VERB.GET, + CONSTANTS.SMAPI.VERSION.V1, + url, + EMPTY_QUERY_PARAMS, + EMPTY_HEADERS, + NULL_PAYLOAD, + callback, + ); + } + + function validateSkill(skillId: string, stage: string, locales: string, callback: SmapiRequestCallback) { + const url = `skills/${skillId}/stages/${stage}/validations`; + const payload = { + locales: locales.trim().split(/[\s,]+/), // comma or space deliminater regex + }; + smapiHandle( + CONSTANTS.SMAPI.API_NAME.VALIDATE_SKILL, + CONSTANTS.HTTP_REQUEST.VERB.POST, + CONSTANTS.SMAPI.VERSION.V1, + url, + EMPTY_QUERY_PARAMS, + EMPTY_HEADERS, + payload, + callback, + ); + } + + function getValidation(skillId: string, stage: string, validationId: string, callback: SmapiRequestCallback) { + const url = `skills/${skillId}/stages/${stage}/validations/${validationId}`; + smapiHandle( + CONSTANTS.SMAPI.API_NAME.GET_VALIDATION, + CONSTANTS.HTTP_REQUEST.VERB.GET, + CONSTANTS.SMAPI.VERSION.V1, + url, + EMPTY_QUERY_PARAMS, + EMPTY_HEADERS, + NULL_PAYLOAD, + callback, + ); + } + + /** + * List ISPs based on the skill-id. + * @param {*} skillId + * @param {*} stage + * @param {*} queryParams | nextToken + * | maxResults + * @param {*} callback + */ + function listIspForSkill( + skillId: string, + stage: string, + queryParams: querystring.ParsedUrlQueryInput, + callback: SmapiRequestCallback, + ) { + const queryObject = R.clone(queryParams); + if (queryObject && !queryObject.maxResults) { + queryObject.maxResults = CONSTANTS.SMAPI.DEFAULT_MAX_RESULT_PER_PAGE; + } + const url = `skills/${skillId}/stages/${stage}/${ISP_URL_BASE}`; + smapiHandle( + CONSTANTS.SMAPI.API_NAME.LIST_ISP_FOR_SKILL, + CONSTANTS.HTTP_REQUEST.VERB.GET, + CONSTANTS.SMAPI.VERSION.V1, + url, + queryObject, + EMPTY_HEADERS, + NULL_PAYLOAD, + callback, + ); + } + + /** + * Get calculated metrics, insights and advanced analytics report for skills usage. + * @param {String} skillId [required] Unique identifier of skill. + * @param {String} startTime [required] The start time of query. + * @param {String} endTime [required] The end time of the query. The maximum duration is one week. + * @param {Enum} period [required] The aggregation period that is used when retrieving the metric. The values are SINGLE, PT15M, PT1H, P1D. + * @param {Enum} metric [required] A distinct set of logic that predictably returns a set of data. + * @param {Enum} stage [required] This parameter shows the stage of the skill. The accepted values are: live or development. + * @param {Enum} skillType [required] The type of skill. Potential values are: custom, smartHome, or flashBriefing. + * @param {String} intent The skill intent. + * @param {String} locale The locale of the skill. + * @param {String} maxResults The maximum number of results to display per page (100,000 is the maximum number of results). + * @param {String} nextToken The continuation token returned in response to an object of the last get metrics report response. + * @param {callback} callback callback function + */ + function getMetrics( + skillId: string, + startTime: string, + endTime: string, + period: string, + metric: string, + stage: string, + skillType: string, + intent: string, + locale: string, + maxResults: string, + nextToken: string, + callback: SmapiRequestCallback, + ) { + const queryObject = {} as any; + if (startTime) { + queryObject.startTime = startTime; + } + if (endTime) { + queryObject.endTime = endTime; + } + if (period) { + queryObject.period = period; + } + if (metric) { + queryObject.metric = metric; + } + if (stage) { + queryObject.stage = stage; + } + if (skillType) { + queryObject.skillType = skillType; + } + if (intent) { + queryObject.intent = intent; + } + if (locale) { + queryObject.locale = locale; + } + + queryObject.maxResults = maxResults || CONSTANTS.SMAPI.DEFAULT_MAX_RESULT_PER_PAGE; + + if (nextToken) { + queryObject.nextToken = nextToken; + } + + const url = `skills/${skillId}/metrics`; + smapiHandle( + CONSTANTS.SMAPI.API_NAME.GET_METRICS, + CONSTANTS.HTTP_REQUEST.VERB.GET, + CONSTANTS.SMAPI.VERSION.V1, + url, + queryObject, + EMPTY_HEADERS, + NULL_PAYLOAD, + callback, + ); + } + + return { + createSkill, + deleteSkill, + listSkills, + getSkillStatus, + enableSkill, + disableSkill, + getSkillEnablement, + getSkillCredentials, + validateSkill, + getValidation, + listIspForSkill, + getMetrics, + }; +}; diff --git a/lib/clients/smapi-client/resources/task.js b/lib/clients/smapi-client/resources/task.js index 6f0ea146..bbfceb87 100644 --- a/lib/clients/smapi-client/resources/task.js +++ b/lib/clients/smapi-client/resources/task.js @@ -1,64 +1,64 @@ -const R = require('ramda'); -const CONSTANTS = require('@src/utils/constants'); +const R = require("ramda"); +const CONSTANTS = require("../../../utils/constants"); const EMPTY_HEADERS = {}; const EMPTY_QUERY_PARAMS = {}; const NULL_PAYLOAD = null; module.exports = (smapiHandle) => { - /** - * Get details of task definition. - * @param {String} skillId [required] skill id - * @param {String} taskName [required] name of task - * @param {Integer} taskVersion [required] version of task - * @param {Function} callback callback function - */ - function getTask(skillId, taskName, taskVersion, callback) { - const url = `tasks/${taskName}/versions/${taskVersion}/?skillId=${skillId}`; - smapiHandle( - CONSTANTS.SMAPI.API_NAME.GET_TASK, - CONSTANTS.HTTP_REQUEST.VERB.GET, - CONSTANTS.SMAPI.VERSION.V1, - url, - EMPTY_QUERY_PARAMS, - EMPTY_HEADERS, - NULL_PAYLOAD, - callback - ); - } + /** + * Get details of task definition. + * @param {String} skillId [required] skill id + * @param {String} taskName [required] name of task + * @param {Integer} taskVersion [required] version of task + * @param {Function} callback callback function + */ + function getTask(skillId, taskName, taskVersion, callback) { + const url = `tasks/${taskName}/versions/${taskVersion}/?skillId=${skillId}`; + smapiHandle( + CONSTANTS.SMAPI.API_NAME.GET_TASK, + CONSTANTS.HTTP_REQUEST.VERB.GET, + CONSTANTS.SMAPI.VERSION.V1, + url, + EMPTY_QUERY_PARAMS, + EMPTY_HEADERS, + NULL_PAYLOAD, + callback, + ); + } - /** - * Search for task definitions. - * @param {String} skillId [required] skill id - * @param {String} keywords search task keywords - * @param {String} providerSkillId task provider skill id - * @param {Object} queryParams | nextToken - * | maxResults - * @param {Function} callback callback function - */ - function searchTask(skillId, keywords, providerSkillId, queryParams, callback) { - const queryObject = R.clone(queryParams) || {}; - queryObject.skillId = skillId; - if (keywords) { - queryObject.keywords = keywords; - } - if (providerSkillId) { - queryObject.providerSkillId = providerSkillId; - } - const url = 'tasks/'; - smapiHandle( - CONSTANTS.SMAPI.API_NAME.SEARCH_TASK, - CONSTANTS.HTTP_REQUEST.VERB.GET, - CONSTANTS.SMAPI.VERSION.V1, - url, - queryObject, - EMPTY_HEADERS, - NULL_PAYLOAD, - callback - ); + /** + * Search for task definitions. + * @param {String} skillId [required] skill id + * @param {String} keywords search task keywords + * @param {String} providerSkillId task provider skill id + * @param {Object} queryParams | nextToken + * | maxResults + * @param {Function} callback callback function + */ + function searchTask(skillId, keywords, providerSkillId, queryParams, callback) { + const queryObject = R.clone(queryParams) || {}; + queryObject.skillId = skillId; + if (keywords) { + queryObject.keywords = keywords; + } + if (providerSkillId) { + queryObject.providerSkillId = providerSkillId; } - return { - getTask, - searchTask - }; + const url = "tasks/"; + smapiHandle( + CONSTANTS.SMAPI.API_NAME.SEARCH_TASK, + CONSTANTS.HTTP_REQUEST.VERB.GET, + CONSTANTS.SMAPI.VERSION.V1, + url, + queryObject, + EMPTY_HEADERS, + NULL_PAYLOAD, + callback, + ); + } + return { + getTask, + searchTask, + }; }; diff --git a/lib/clients/smapi-client/resources/test.js b/lib/clients/smapi-client/resources/test.js deleted file mode 100644 index eff88ccf..00000000 --- a/lib/clients/smapi-client/resources/test.js +++ /dev/null @@ -1,78 +0,0 @@ -const CONSTANTS = require('@src/utils/constants'); - -const EMPTY_HEADERS = {}; -const EMPTY_QUERY_PARAMS = {}; -const NULL_PAYLOAD = null; - -module.exports = (smapiHandle) => { - function invokeSkill(skillId, stage, invokePayload, endpointRegion, callback) { - const url = `skills/${skillId}/stages/${stage}/invocations`; - const payload = { - endpointRegion, - skillRequest: invokePayload - }; - smapiHandle( - CONSTANTS.SMAPI.API_NAME.INVOKE_SKILL, - CONSTANTS.HTTP_REQUEST.VERB.POST, - CONSTANTS.SMAPI.VERSION.V2, - url, - EMPTY_QUERY_PARAMS, - EMPTY_HEADERS, - payload, - callback - ); - } - - function simulateSkill(skillId, stage, input, newSession, locale, simulationType, callback) { - const url = `skills/${skillId}/stages/${stage}/simulations`; - const payload = { - input: { - content: input - }, - device: { - locale - } - }; - if (newSession) { - payload.session = { - mode: 'FORCE_NEW_SESSION' - }; - } - - if (simulationType) { - payload.simulation = { - type: simulationType - }; - } - smapiHandle( - CONSTANTS.SMAPI.API_NAME.SIMULATE_SKILL, - CONSTANTS.HTTP_REQUEST.VERB.POST, - CONSTANTS.SMAPI.VERSION.V2, - url, - EMPTY_QUERY_PARAMS, - EMPTY_HEADERS, - payload, - callback - ); - } - - function getSimulation(skillId, simulationId, stage, callback) { - const url = `skills/${skillId}/stages/${stage}/simulations/${simulationId}`; - smapiHandle( - CONSTANTS.SMAPI.API_NAME.GET_SIMULATION, - CONSTANTS.HTTP_REQUEST.VERB.GET, - CONSTANTS.SMAPI.VERSION.V2, - url, - EMPTY_QUERY_PARAMS, - EMPTY_HEADERS, - NULL_PAYLOAD, - callback - ); - } - - return { - invokeSkill, - simulateSkill, - getSimulation - }; -}; diff --git a/lib/clients/smapi-client/resources/test.ts b/lib/clients/smapi-client/resources/test.ts new file mode 100644 index 00000000..b5b8db40 --- /dev/null +++ b/lib/clients/smapi-client/resources/test.ts @@ -0,0 +1,162 @@ +import {SmapiRequest, SmapiRequestCallback, SmapiResponse} from ".."; +import CONSTANTS from "../../../utils/constants"; + +const EMPTY_HEADERS = {}; +const EMPTY_QUERY_PARAMS = {}; +const NULL_PAYLOAD = null; + +export default (smapiHandle: SmapiRequest) => { + function invokeSkill(skillId: string, stage: string, invokePayload: any, endpointRegion: string, callback: SmapiRequestCallback) { + const url = `skills/${skillId}/stages/${stage}/invocations`; + const payload = { + endpointRegion, + skillRequest: invokePayload, + }; + smapiHandle( + CONSTANTS.SMAPI.API_NAME.INVOKE_SKILL, + CONSTANTS.HTTP_REQUEST.VERB.POST, + CONSTANTS.SMAPI.VERSION.V2, + url, + EMPTY_QUERY_PARAMS, + EMPTY_HEADERS, + payload, + callback, + ); + } + + function simulateSkill(skillId: string, stage: string, input: string, newSession: boolean, locale: string): Promise>; + function simulateSkill( + skillId: string, + stage: string, + input: string, + newSession: boolean, + locale: string, + callback: SmapiRequestCallback, + ): void; + function simulateSkill( + skillId: string, + stage: string, + input: string, + newSession: boolean, + locale: string, + callback?: SmapiRequestCallback, + ): Promise> | void { + const url = `skills/${skillId}/stages/${stage}/simulations`; + const payload = { + input: { + content: input, + }, + device: { + locale, + }, + ...(newSession + ? { + session: { + mode: "FORCE_NEW_SESSION", + }, + } + : {}), + }; + if (callback) { + return smapiHandle( + CONSTANTS.SMAPI.API_NAME.SIMULATE_SKILL, + CONSTANTS.HTTP_REQUEST.VERB.POST, + CONSTANTS.SMAPI.VERSION.V2, + url, + EMPTY_QUERY_PARAMS, + EMPTY_HEADERS, + payload, + callback, + ); + } + return smapiHandle( + CONSTANTS.SMAPI.API_NAME.SIMULATE_SKILL, + CONSTANTS.HTTP_REQUEST.VERB.POST, + CONSTANTS.SMAPI.VERSION.V2, + url, + EMPTY_QUERY_PARAMS, + EMPTY_HEADERS, + payload, + ); + } + + function getSimulation(skillId: string, simulationId: string, stage: string): Promise>; + function getSimulation(skillId: string, simulationId: string, stage: string, callback: SmapiRequestCallback): void; + function getSimulation(skillId: string, simulationId: string, stage: string, callback?: SmapiRequestCallback) { + const url = `skills/${skillId}/stages/${stage}/simulations/${simulationId}`; + if (callback) { + return smapiHandle( + CONSTANTS.SMAPI.API_NAME.GET_SIMULATION, + CONSTANTS.HTTP_REQUEST.VERB.GET, + CONSTANTS.SMAPI.VERSION.V2, + url, + EMPTY_QUERY_PARAMS, + EMPTY_HEADERS, + NULL_PAYLOAD, + callback, + ); + } + return smapiHandle( + CONSTANTS.SMAPI.API_NAME.GET_SIMULATION, + CONSTANTS.HTTP_REQUEST.VERB.GET, + CONSTANTS.SMAPI.VERSION.V2, + url, + EMPTY_QUERY_PARAMS, + EMPTY_HEADERS, + NULL_PAYLOAD, + ); + } + + function modifyLastTurn(params: ModifyLastTurnParams): Promise>; + function modifyLastTurn(params: ModifyLastTurnParams, callback: SmapiRequestCallback>): void; + function modifyLastTurn( + params: ModifyLastTurnParams, + callback?: SmapiRequestCallback>, + ): Promise> | void { + const url = `skills/${params.skillId}/stages/${params.stage}/locales/${params.locale}/conversations/turnPredictions`; + if (callback) { + return smapiHandle( + CONSTANTS.SMAPI.API_NAME.MODIFY_LAST_TURN, + CONSTANTS.HTTP_REQUEST.VERB.PUT, + CONSTANTS.SMAPI.VERSION.V1, + url, + EMPTY_QUERY_PARAMS, + EMPTY_HEADERS, + params.payload, + callback, + ); + } + return smapiHandle( + CONSTANTS.SMAPI.API_NAME.MODIFY_LAST_TURN, + CONSTANTS.HTTP_REQUEST.VERB.PUT, + CONSTANTS.SMAPI.VERSION.V1, + url, + EMPTY_QUERY_PARAMS, + EMPTY_HEADERS, + params.payload, + ); + } + + return { + invokeSkill, + simulateSkill, + getSimulation, + modifyLastTurn, + }; +}; + +export interface CorrectionPayload { + endPrediction: boolean; + corrections: any[]; +} + +export interface ModifyLastTurnParams { + skillId: string; + stage: string; + locale: string; + payload: CorrectionPayload; +} + +export interface ModifyLastTurnError { + violations: {message: string}[]; +} diff --git a/lib/clients/smapi-client/resources/vendor.js b/lib/clients/smapi-client/resources/vendor.js index 2410a1e6..d6b7c57e 100644 --- a/lib/clients/smapi-client/resources/vendor.js +++ b/lib/clients/smapi-client/resources/vendor.js @@ -1,25 +1,25 @@ -const CONSTANTS = require('@src/utils/constants'); +const CONSTANTS = require("../../../utils/constants"); const EMPTY_HEADERS = {}; const EMPTY_QUERY_PARAMS = {}; const NULL_PAYLOAD = null; module.exports = (smapiHandle) => { - function listVendors(callback) { - const url = 'vendors'; - smapiHandle( - CONSTANTS.SMAPI.API_NAME.LIST_VENDORS, - CONSTANTS.HTTP_REQUEST.VERB.GET, - CONSTANTS.SMAPI.VERSION.V1, - url, - EMPTY_QUERY_PARAMS, - EMPTY_HEADERS, - NULL_PAYLOAD, - callback - ); - } + function listVendors(callback) { + const url = "vendors"; + smapiHandle( + CONSTANTS.SMAPI.API_NAME.LIST_VENDORS, + CONSTANTS.HTTP_REQUEST.VERB.GET, + CONSTANTS.SMAPI.VERSION.V1, + url, + EMPTY_QUERY_PARAMS, + EMPTY_HEADERS, + NULL_PAYLOAD, + callback, + ); + } - return { - listVendors - }; + return { + listVendors, + }; }; diff --git a/lib/commands/abstract-command.js b/lib/commands/abstract-command.js deleted file mode 100644 index a7df0a06..00000000 --- a/lib/commands/abstract-command.js +++ /dev/null @@ -1,250 +0,0 @@ -const semver = require('semver'); - -const httpClient = require('@src/clients/http-client'); -const { - validateRequiredOption, - validateOptionString, - validateOptionRules, -} = require('@src/commands/option-validator'); -const AppConfig = require('@src/model/app-config'); -const CONSTANTS = require('@src/utils/constants'); -const Messenger = require('@src/view/messenger'); -const metricClient = require('@src/utils/metrics'); - -const packageJson = require('@root/package.json'); - -/** - * Base class for ASK CLI command that provides option parsing, commander configuration and option validation at runtime. - */ -class AbstractCommand { - constructor(optionModel) { - // eslint-disable-next-line global-require - this._optionModel = optionModel || require('@src/commands/option-model'); - } - - name() { - throw new Error('Unimplemented abstract function: name()!'); - } - - description() { - throw new Error('Unimplemented abstract function: description()!'); - } - - requiredOptions() { - return []; - } - - optionalOptions() { - return []; - } - - handle() {} - - exit(statusCode) { - Messenger.getInstance().dispose(); - process.exit(statusCode || 0); - } - - createCommand() { - new Messenger({}); - return (commander) => { - try { - // register command name and description - const commanderCopy = commander - .command(this.name()) - .description(this.description()); - - // register command options - this._registerOptions(commanderCopy); - - // register command action - this._registerAction(commanderCopy); - } catch (err) { - Messenger.getInstance().fatal(err); - this.exit(1); - } - }; - } - - _registerAction(commander) { - // the result commander's parse, args, contains a Commander object (args[0]), and an array of unrecognized user inputs (args[1]) - commander.action((...args) => new Promise((resolve) => { - const commandInstance = args[0]; - const remaining = args[1]; - - // set Messenger debug preferrance - Messenger.getInstance().doDebug = commandInstance.debug; - - // Start metric client - metricClient.startAction(commandInstance._name, ''); - const isCredentialHelperCmd = commandInstance._name === 'git-credentials-helper'; - - // Check if a new CLI version is released - this._remindsIfNewVersion(commandInstance.debug, isCredentialHelperCmd || process.env.ASK_SKIP_NEW_VERSION_REMINDER, () => { - try { - this._validateOptions(commandInstance); - - /** - * Since this code is ran for every command, we'll just be initiating appConfig here (no files created). - * Only `ask configure` command should have the eligibility to create the ASK config file (which is handled - * in the configure workflow). - */ - if (commandInstance._name !== 'configure') { - new AppConfig(); - } - } catch (err) { - Messenger.getInstance().error(err); - resolve(); - this.exit(1); - return; - } - // execute handler logic of each command; quit execution - this.handle(commandInstance, (error) => { - metricClient.sendData(error).then(() => { - resolve(); - this.exit(error ? 1 : 0); - }); - }, remaining); - }); - })); - } - - _registerOptions(commander) { - const requiredOptions = this.requiredOptions(); - if (requiredOptions && requiredOptions.length) { - for (const optionId of requiredOptions) { - commander = this._registerOption(commander, optionId, true); - } - } - - const optionalOptions = this.optionalOptions(); - if (optionalOptions && optionalOptions.length) { - for (const optionId of optionalOptions) { - commander = this._registerOption(commander, optionId, false); - } - } - - return commander; - } - - _registerOption(commander, optionId, required) { - const optionModel = this._optionModel[optionId]; - - // Check if given option name has a model defined. Refer to option-model.json for all available option models - if (!optionModel) { - throw new Error(`Unrecognized option ID: ${optionId}`); - } - - return commander.option( - AbstractCommand.buildOptionString(optionModel), - `${required ? '[REQUIRED]' : '[OPTIONAL]'} ${optionModel.description}` - ); - } - - _validateOptions(cmd) { - const requiredOptions = this.requiredOptions(); - if (requiredOptions && requiredOptions.length) { - for (const optionId of requiredOptions) { - this._validateOption(cmd, optionId, true); - } - } - - const optionalOptions = this.optionalOptions(); - if (optionalOptions && optionalOptions.length) { - for (const optionId of optionalOptions) { - this._validateOption(cmd, optionId, false); - } - } - } - - _validateOption(cmd, optionId, required) { - const optionModel = this._optionModel[optionId]; - const optionKey = AbstractCommand.parseOptionKey(optionModel.name); - try { - if (required) { - validateRequiredOption(cmd, optionKey); - } - - if (cmd[optionKey]) { - // Validate string value for options that require string input - if (optionModel.stringInput === 'REQUIRED') { - validateOptionString(cmd, optionKey); - } - - validateOptionRules(cmd, optionKey, optionModel.rule); - } - } catch (err) { - throw (`Please provide valid input for option: ${optionModel.name}. ${err}`); - } - } - - _remindsIfNewVersion(doDebug, skip, callback) { - if (skip) return callback(); - - httpClient.request({ - url: `${CONSTANTS.NPM_REGISTRY_URL_BASE}/${CONSTANTS.APPLICATION_NAME}/latest`, - method: CONSTANTS.HTTP_REQUEST.VERB.GET - }, 'GET_NPM_REGISTRY', doDebug, (err, response) => { - if (err || response.statusCode > 300) { - const error = err || `Http Status Code: ${response.statusCode}.`; - Messenger.getInstance().error(`Failed to get the latest version for ${CONSTANTS.APPLICATION_NAME} from NPM registry.\n${error}\n`); - } else { - const latestVersion = JSON.parse(response.body).version; - if (packageJson.version !== latestVersion) { - if (semver.major(packageJson.version) < semver.major(latestVersion)) { - Messenger.getInstance().warn(`\ -New MAJOR version (v${latestVersion}) of ${CONSTANTS.APPLICATION_NAME} is available now. Current version v${packageJson.version}. -It is recommended to use the latest version. Please update using "npm upgrade -g ${CONSTANTS.APPLICATION_NAME}". -\n`); - } else if ( - semver.major(packageJson.version) === semver.major(latestVersion) - && semver.minor(packageJson.version) < semver.minor(latestVersion) - ) { - Messenger.getInstance().warn(`\ -New MINOR version (v${latestVersion}) of ${CONSTANTS.APPLICATION_NAME} is available now. Current version v${packageJson.version}. -It is recommended to use the latest version. Please update using "npm upgrade -g ${CONSTANTS.APPLICATION_NAME}". -\n`); - } - } - } - callback(); - }); - } - - /** - * Build the usage string for an option - * @param {Object} optionModel - */ - static buildOptionString(optionModel) { - const optionStringArray = []; - - if (optionModel.alias) { - optionStringArray.push(`-${optionModel.alias},`); - } - - optionStringArray.push(`--${optionModel.name}`); - - if (optionModel.stringInput === 'REQUIRED') { - optionStringArray.push(`<${optionModel.name}>`); - } else if (optionModel.stringInput === 'OPTIONAL') { - optionStringArray.push(`[${optionModel.name}]`); - } - - return optionStringArray.join(' '); - } - - /** - * convert option name to option key - * Example: skill-id -> skillId - * @param name - */ - static parseOptionKey(name) { - const arr = name.split('-'); - - return arr.slice(1).reduce((end, element) => end + element.charAt(0).toUpperCase() + element.slice(1), arr[0]); - } -} - -module.exports = { - AbstractCommand -}; diff --git a/lib/commands/abstract-command.ts b/lib/commands/abstract-command.ts new file mode 100644 index 00000000..375d571a --- /dev/null +++ b/lib/commands/abstract-command.ts @@ -0,0 +1,265 @@ +import {OptionModel, OptionModelEntry} from "./option-validator"; + +import semver from "semver"; + +import httpClient from "../clients/http-client"; +import {validateRequiredOption, validateOptionString, validateOptionRules} from "./option-validator"; +import AppConfig from "../model/app-config"; +import CONSTANTS from "../utils/constants"; +import Messenger from "../view/messenger"; +import metricClient from "../utils/metrics"; +import {Command} from "commander"; + +import packageJson from "../../package.json"; + +/** + * Base class for ASK CLI command that provides option parsing, commander configuration and option validation at runtime. + */ +export abstract class AbstractCommand = Record> { + _optionModel: OptionModel; + + constructor(optionModel: OptionModel) { + // eslint-disable-next-line global-require + this._optionModel = optionModel || require("./option-model"); + } + + abstract name(): string; + + abstract description(): string; + + abstract requiredOptions(): (Partial & string)[]; + + abstract optionalOptions(): (Partial & string)[]; + + abstract handle(cmd: T, remaining: any[]): Promise; + + exit(statusCode: number) { + Messenger.getInstance().dispose(); + process.exit(statusCode || 0); + } + + createCommand() { + new Messenger({}); + return (commander: Command) => { + try { + // register command name and description + const commanderCopy = commander.command(this.name()).description(this.description()); + + // register command options + this._registerOptions(commanderCopy); + + // register command action + this._registerAction(commanderCopy); + } catch (err) { + Messenger.getInstance().fatal(err); + this.exit(1); + } + }; + } + + _registerAction(commander: Command) { + // the result commander's parse, args, contains a Commander object (args[0]), and an array of unrecognized user inputs (args[1]) + commander.action(async (...args) => { + const commandInstance = args[0]; + const remaining = args[1]; + + // set Messenger debug preferrance + Messenger.getInstance().doDebug = commandInstance.debug; + + // Start metric client + metricClient.startAction(commandInstance._name, ""); + const isCredentialHelperCmd = commandInstance._name === "git-credentials-helper"; + + // Check if a new CLI version is released + await this._remindsIfNewVersion(commandInstance.debug, isCredentialHelperCmd || process.env.ASK_SKIP_NEW_VERSION_REMINDER); + try { + this._validateOptions(commandInstance); + + /** + * Since this code is ran for every command, we'll just be initiating appConfig here (no files created). + * Only `ask configure` command should have the eligibility to create the ASK config file (which is handled + * in the configure workflow). + */ + if (commandInstance._name !== "configure") { + new AppConfig(); + } + } catch (err) { + Messenger.getInstance().error(err); + this.exit(1); + return; + } + // execute handler logic of each command; quit execution + try { + await this.handle(commandInstance, remaining); + metricClient.sendData().then(() => { + this.exit(0); + }); + } catch (error) { + metricClient.sendData(error as any).then(() => { + this.exit(error ? 1 : 0); + }); + } + }); + } + + _registerOptions(commander: Command) { + const requiredOptions = this.requiredOptions(); + if (requiredOptions && requiredOptions.length) { + for (const optionId of requiredOptions) { + commander = this._registerOption(commander, optionId, true); + } + } + + const optionalOptions = this.optionalOptions(); + if (optionalOptions && optionalOptions.length) { + for (const optionId of optionalOptions) { + commander = this._registerOption(commander, optionId, false); + } + } + + return commander; + } + + _registerOption(commander: Command, optionId: string, required: boolean) { + const optionModel = this._optionModel[optionId]; + + // Check if given option name has a model defined. Refer to option-model.json for all available option models + if (!optionModel) { + throw new Error(`Unrecognized option ID: ${optionId}`); + } + + return commander.option( + AbstractCommand.buildOptionString(optionModel), + `${required ? "[REQUIRED]" : "[OPTIONAL]"} ${optionModel.description}`, + ); + } + + _validateOptions(cmd: Record) { + const requiredOptions = this.requiredOptions(); + if (requiredOptions && requiredOptions.length) { + for (const optionId of requiredOptions) { + const [name, value] = this._validateOption(cmd, optionId, true); + if (value !== undefined) metricClient.setOption(name, value); + } + } + + const optionalOptions = this.optionalOptions(); + if (optionalOptions && optionalOptions.length) { + for (const optionId of optionalOptions) { + const [name, value] = this._validateOption(cmd, optionId, false); + if (value !== undefined) metricClient.setOption(name, value); + } + } + } + + /** + * Looks up the option, validates the value, and returns the (name, value) pair if it is valid + * @param cmd commander instance + * @param optionId the option to lookup + * @param required whether the option is required + * @returns the option name, the option value if option was set + * @throws error if the option is invalid + */ + _validateOption(cmd: Record, optionId: string, required: boolean): [string, string | undefined] { + const optionModel = this._optionModel[optionId]; + const optionKey = AbstractCommand.parseOptionKey(optionModel.name); + try { + if (required) { + validateRequiredOption(cmd, optionKey); + } + + // the value is undefined if the user did not specify this option + const optionValue = cmd[optionKey]; + if (optionValue) { + // Validate string value for options that require string input + if (optionModel.stringInput === "REQUIRED") { + validateOptionString(cmd, optionKey); + } + + validateOptionRules(cmd, optionKey, optionModel.rule); + } + return [optionModel.name, optionValue]; + } catch (err) { + throw `Please provide valid input for option: ${optionModel.name}. ${err}`; + } + } + + _remindsIfNewVersion(doDebug: boolean, skip: boolean | string | undefined): Promise { + if (skip) return Promise.resolve(); + + return new Promise((resolve) => { + httpClient.request( + { + url: `${CONSTANTS.NPM_REGISTRY_URL_BASE}/${CONSTANTS.APPLICATION_NAME}/latest`, + method: CONSTANTS.HTTP_REQUEST.VERB.GET, + }, + "GET_NPM_REGISTRY", + doDebug, + (err?: any, response?: any) => { + if (err || response.statusCode > 300) { + const error = err || `Http Status Code: ${response.statusCode}.`; + Messenger.getInstance().error( + `Failed to get the latest version for ${CONSTANTS.APPLICATION_NAME} from NPM registry.\n${error}\n`, + ); + } else { + const latestVersion = JSON.parse(response.body).version; + if (packageJson.version !== latestVersion) { + if (semver.major(packageJson.version) < semver.major(latestVersion)) { + Messenger.getInstance().warn(`\ +New MAJOR version (v${latestVersion}) of ${CONSTANTS.APPLICATION_NAME} is available now. Current version v${packageJson.version}. +It is recommended to use the latest version. Please update using "npm upgrade -g ${CONSTANTS.APPLICATION_NAME}". +\n`); + } else if ( + semver.major(packageJson.version) === semver.major(latestVersion) && + semver.minor(packageJson.version) < semver.minor(latestVersion) + ) { + Messenger.getInstance().warn(`\ +New MINOR version (v${latestVersion}) of ${CONSTANTS.APPLICATION_NAME} is available now. Current version v${packageJson.version}. +It is recommended to use the latest version. Please update using "npm upgrade -g ${CONSTANTS.APPLICATION_NAME}". +\n`); + } + } + } + resolve(); + }, + ); + }); + } + + /** + * Build the usage string for an option + * @param {Object} optionModel + */ + static buildOptionString(optionModel: OptionModelEntry) { + const optionStringArray = []; + + if (optionModel.alias) { + optionStringArray.push(`-${optionModel.alias},`); + } + + optionStringArray.push(`--${optionModel.name}`); + + if (optionModel.stringInput === "REQUIRED") { + optionStringArray.push(`<${optionModel.name}>`); + } else if (optionModel.stringInput === "OPTIONAL") { + optionStringArray.push(`[${optionModel.name}]`); + } + + return optionStringArray.join(" "); + } + + /** + * convert option name to option key + * Example: skill-id -> skillId + * @param name + */ + static parseOptionKey(name: string) { + const arr = name.split("-"); + + return arr.slice(1).reduce((end, element) => end + element.charAt(0).toUpperCase() + element.slice(1), arr[0]); + } +} + +module.exports = { + AbstractCommand, +}; diff --git a/lib/commands/configure/ask-profile-setup-helper.js b/lib/commands/configure/ask-profile-setup-helper.js index f0aa7fab..aaa836c3 100644 --- a/lib/commands/configure/ask-profile-setup-helper.js +++ b/lib/commands/configure/ask-profile-setup-helper.js @@ -1,15 +1,15 @@ -const SmapiClient = require('@src/clients/smapi-client'); -const AuthorizationController = require('@src/controllers/authorization-controller'); -const jsonView = require('@src/view/json-view'); -const Messenger = require('@src/view/messenger'); -const CONSTANTS = require('@src/utils/constants'); +const SmapiClient = require("../../clients/smapi-client").default; +const AuthorizationController = require("../../controllers/authorization-controller"); +const jsonView = require("../../view/json-view"); +const Messenger = require("../../view/messenger"); +const CONSTANTS = require("../../utils/constants"); -const messages = require('./messages'); -const ui = require('./ui'); +const messages = require("./messages"); +const ui = require("./ui"); module.exports = { - setupAskToken, - setupVendorId + setupAskToken, + setupVendorId, }; /** @@ -18,12 +18,12 @@ module.exports = { * @param {Function} callback */ function setupAskToken(config, callback) { - _getAccessToken(config, (accessTokenError, accessToken) => { - if (accessTokenError) { - return callback(accessTokenError); - } - callback(null, accessToken); - }); + _getAccessToken(config, (accessTokenError, accessToken) => { + if (accessTokenError) { + return callback(accessTokenError); + } + callback(null, accessToken); + }); } /** @@ -33,19 +33,19 @@ function setupAskToken(config, callback) { * @private */ function _getAccessToken(config, callback) { - const authorizationController = new AuthorizationController(_buildAuthorizationConfiguration(config)); - if (!config.needBrowser) { - const authorizeUrl = authorizationController.getAuthorizeUrl(); - Messenger.getInstance().info(`Paste the following url to your browser:\n ${authorizeUrl}`); - ui.getAuthCode((error, authCode) => { - if (error) { - return callback(error); - } - authorizationController.getAccessTokenUsingAuthCode(authCode, (err, accessToken) => callback(err, err == null ? accessToken : err)); - }); - } else { - authorizationController.getTokensByListeningOnPort((err, accessToken) => callback(err, err == null ? accessToken : err)); - } + const authorizationController = new AuthorizationController(_buildAuthorizationConfiguration(config)); + if (!config.needBrowser) { + const authorizeUrl = authorizationController.getAuthorizeUrl(); + Messenger.getInstance().info(`Paste the following url to your browser:\n ${authorizeUrl}`); + ui.getAuthCode((error, authCode) => { + if (error) { + return callback(error); + } + authorizationController.getAccessTokenUsingAuthCode(authCode, (err, accessToken) => callback(err, err == null ? accessToken : err)); + }); + } else { + authorizationController.getTokensByListeningOnPort((err, accessToken) => callback(err, err == null ? accessToken : err)); + } } /** @@ -55,17 +55,17 @@ function _getAccessToken(config, callback) { * @private */ function setupVendorId(config, callback) { - _getVendorInfo(config, (err, vendorInfo) => { - if (err) { - return callback(err); - } - _selectVendorId(vendorInfo, (vendorIdError, vendorId) => { - if (vendorIdError) { - return callback(vendorIdError); - } - callback(null, vendorId); - }); + _getVendorInfo(config, (err, vendorInfo) => { + if (err) { + return callback(err); + } + _selectVendorId(vendorInfo, (vendorIdError, vendorId) => { + if (vendorIdError) { + return callback(vendorIdError); + } + callback(null, vendorId); }); + }); } /** @@ -75,21 +75,21 @@ function setupVendorId(config, callback) { * @private */ function _getVendorInfo(config, callback) { - const smapiClient = new SmapiClient({ - profile: config.askProfile, - doDebug: config.debug - }); + const smapiClient = new SmapiClient({ + profile: config.askProfile, + doDebug: config.debug, + }); - smapiClient.vendor.listVendors((err, response) => { - if (err) { - return callback(err); - } - if (response.statusCode >= 300) { - const error = jsonView.toString(response.body); - return callback(error); - } - callback(null, response.body.vendors); - }); + smapiClient.vendor.listVendors((err, response) => { + if (err) { + return callback(err); + } + if (response.statusCode >= 300) { + const error = jsonView.toString(response.body); + return callback(error); + } + callback(null, response.body.vendors); + }); } /** @@ -98,25 +98,25 @@ function _getVendorInfo(config, callback) { * @param {Function} callback */ function _selectVendorId(vendorInfo, callback) { - if (!vendorInfo) { - return callback(messages.VENDOR_INFO_FETCH_ERROR); - } - const numberOfVendors = vendorInfo.length; - const LIST_PAGE_SIZE = 50; - switch (numberOfVendors) { + if (!vendorInfo) { + return callback(messages.VENDOR_INFO_FETCH_ERROR); + } + const numberOfVendors = vendorInfo.length; + const LIST_PAGE_SIZE = 50; + switch (numberOfVendors) { case 0: - process.nextTick(() => { - callback(messages.VENDOR_ID_CREATE_INSTRUCTIONS); - }); - break; + process.nextTick(() => { + callback(messages.VENDOR_ID_CREATE_INSTRUCTIONS); + }); + break; case 1: - process.nextTick(() => { - callback(null, vendorInfo[0].id); - }); - break; + process.nextTick(() => { + callback(null, vendorInfo[0].id); + }); + break; default: - ui.chooseVendorId(LIST_PAGE_SIZE, vendorInfo, (error, vendorId) => callback(error, error === null ? vendorId : error)); - } + ui.chooseVendorId(LIST_PAGE_SIZE, vendorInfo, (error, vendorId) => callback(error, error === null ? vendorId : error)); + } } /** @@ -125,12 +125,12 @@ function _selectVendorId(vendorInfo, callback) { * @private */ function _buildAuthorizationConfiguration(config) { - return { - config, - scopes: CONSTANTS.LWA.DEFAULT_SCOPES, - state: CONSTANTS.LWA.DEFAULT_STATE, - auth_client_type: 'LWA', - redirectUri: CONSTANTS.LWA.S3_RESPONSE_PARSER_URL, - doDebug: config.doDebug - }; + return { + config, + scopes: CONSTANTS.LWA.DEFAULT_SCOPES, + state: CONSTANTS.LWA.DEFAULT_STATE, + auth_client_type: "LWA", + redirectUri: CONSTANTS.LWA.S3_RESPONSE_PARSER_URL, + doDebug: config.doDebug, + }; } diff --git a/lib/commands/configure/aws-profile-setup-helper.js b/lib/commands/configure/aws-profile-setup-helper.js index 6302bbc7..aa30a616 100644 --- a/lib/commands/configure/aws-profile-setup-helper.js +++ b/lib/commands/configure/aws-profile-setup-helper.js @@ -1,20 +1,20 @@ -const awsProfileHandler = require('aws-profile-handler'); -const fs = require('fs-extra'); -const open = require('open'); -const os = require('os'); -const path = require('path'); -const querystring = require('querystring'); +const awsProfileHandler = require("aws-profile-handler"); +const fs = require("fs-extra"); +const open = require("open"); +const os = require("os"); +const path = require("path"); +const querystring = require("querystring"); -const CONSTANTS = require('@src/utils/constants'); -const Messenger = require('@src/view/messenger'); -const profileHelper = require('@src/utils/profile-helper'); -const stringUtils = require('@src/utils/string-utils'); +const CONSTANTS = require("../../utils/constants"); +const Messenger = require("../../view/messenger"); +const profileHelper = require("../../utils/profile-helper"); +const stringUtils = require("../../utils/string-utils"); -const messages = require('./messages'); -const ui = require('./ui'); +const messages = require("./messages"); +const ui = require("./ui"); module.exports = { - setupAwsProfile, + setupAwsProfile, }; /** @@ -23,16 +23,16 @@ module.exports = { * @param {Function} callback */ function setupAwsProfile(config, callback) { - let awsProfileList; - try { - const awsPath = path.join(os.homedir(), CONSTANTS.FILE_PATH.AWS.HIDDEN_FOLDER, CONSTANTS.FILE_PATH.AWS.CREDENTIAL_FILE); - awsProfileList = fs.existsSync(awsPath) ? awsProfileHandler.listProfiles(awsPath) : []; - } catch (error) { - return process.nextTick(() => { - callback(error); - }); - } - _initiateAwsProfileSetup(config, awsProfileList, (err, awsProfile) => callback(err, err === null ? awsProfile : err)); + let awsProfileList; + try { + const awsPath = path.join(os.homedir(), CONSTANTS.FILE_PATH.AWS.HIDDEN_FOLDER, CONSTANTS.FILE_PATH.AWS.CREDENTIAL_FILE); + awsProfileList = fs.existsSync(awsPath) ? awsProfileHandler.listProfiles(awsPath) : []; + } catch (error) { + return process.nextTick(() => { + callback(error); + }); + } + _initiateAwsProfileSetup(config, awsProfileList, (err, awsProfile) => callback(err, err === null ? awsProfile : err)); } /** @@ -43,46 +43,46 @@ function setupAwsProfile(config, callback) { * @private */ function _initiateAwsProfileSetup(config, awsProfileList, callback) { - // 1.confirm if using AWS profile from prompt - ui.confirmSettingAws((setUpError, setupChoice) => { - if (setUpError) { - return callback(setUpError); - } - if (!setupChoice) { - Messenger.getInstance().info(messages.SKIP_AWS_CONFIGURATION); - return callback(); - } - // 2.check if using environment variable AWS profile - _handleEnvironmentVariableAwsSetup(config, (envVarErr, isAwsProfile) => { - if (envVarErr) { - return callback(envVarErr); - } - if (isAwsProfile) { - return callback(null, isAwsProfile); - } - // 3.create new AWS profile or select and update the existing one - if (awsProfileList.length === 0) { - _createAwsProfileFlow(config, awsProfileList, (error, awsProfile) => callback(error, error === null ? awsProfile : error)); - } else { - ui.createNewOrSelectAWSProfile(awsProfileList, (err, awsProfile) => { - if (err) { - return callback(err); - } - if (awsProfile === 'Create new profile') { - _createAwsProfileFlow(config, awsProfileList, (error, newAwsProfile) => { - if (error) { - return callback(error); - } - callback(null, newAwsProfile); - }); - } else { - profileHelper.setupProfile(awsProfile, config.askProfile); - callback(null, awsProfile); - } - }); - } + // 1.confirm if using AWS profile from prompt + ui.confirmSettingAws((setUpError, setupChoice) => { + if (setUpError) { + return callback(setUpError); + } + if (!setupChoice) { + Messenger.getInstance().info(messages.SKIP_AWS_CONFIGURATION); + return callback(); + } + // 2.check if using environment variable AWS profile + _handleEnvironmentVariableAwsSetup(config, (envVarErr, isAwsProfile) => { + if (envVarErr) { + return callback(envVarErr); + } + if (isAwsProfile) { + return callback(null, isAwsProfile); + } + // 3.create new AWS profile or select and update the existing one + if (awsProfileList.length === 0) { + _createAwsProfileFlow(config, awsProfileList, (error, awsProfile) => callback(error, error === null ? awsProfile : error)); + } else { + ui.createNewOrSelectAWSProfile(awsProfileList, (err, awsProfile) => { + if (err) { + return callback(err); + } + if (awsProfile === "Create new profile") { + _createAwsProfileFlow(config, awsProfileList, (error, newAwsProfile) => { + if (error) { + return callback(error); + } + callback(null, newAwsProfile); + }); + } else { + profileHelper.setupProfile(awsProfile, config.askProfile); + callback(null, awsProfile); + } }); + } }); + }); } /** @@ -93,35 +93,35 @@ function _initiateAwsProfileSetup(config, awsProfileList, callback) { * @private */ function _createAwsProfileFlow(config, awsProfileList, callback) { - // 1.create .aws folders if necessary - try { - const awsCredentialsFile = path.join(os.homedir(), CONSTANTS.FILE_PATH.AWS.HIDDEN_FOLDER, CONSTANTS.FILE_PATH.AWS.CREDENTIAL_FILE); - fs.ensureFileSync(awsCredentialsFile); - fs.chmodSync(awsCredentialsFile, CONSTANTS.FILE_PERMISSION.USER_READ_WRITE); - } catch (error) { - return callback(error); + // 1.create .aws folders if necessary + try { + const awsCredentialsFile = path.join(os.homedir(), CONSTANTS.FILE_PATH.AWS.HIDDEN_FOLDER, CONSTANTS.FILE_PATH.AWS.CREDENTIAL_FILE); + fs.ensureFileSync(awsCredentialsFile); + fs.chmodSync(awsCredentialsFile, CONSTANTS.FILE_PERMISSION.USER_READ_WRITE); + } catch (error) { + return callback(error); + } + // 2.profile name settle down + _decideAwsProfileName(awsProfileList, (error, awsProfileName) => { + if (error) { + return callback(error); } - // 2.profile name settle down - _decideAwsProfileName(awsProfileList, (error, awsProfileName) => { - if (error) { - return callback(error); + // 3.create IAM user based on profile name + const iamUserName = `ask-cli-${stringUtils.filterNonAlphanumeric(awsProfileName)}`; + _openIamCreateUserPage(config.needBrowser, iamUserName, () => { + // 4.let users input their AWS user credentials + ui.addNewCredentials((err, credentialObject) => { + if (err) { + return callback(error); } - // 3.create IAM user based on profile name - const iamUserName = `ask-cli-${stringUtils.filterNonAlphanumeric(awsProfileName)}`; - _openIamCreateUserPage(config.needBrowser, iamUserName, () => { - // 4.let users input their AWS user credentials - ui.addNewCredentials((err, credentialObject) => { - if (err) { - return callback(error); - } - awsProfileHandler.addProfile(awsProfileName, credentialObject); - profileHelper.setupProfile(awsProfileName, config.askProfile); - Messenger.getInstance().info(`\nAWS profile "${awsProfileName}" was successfully created. \ + awsProfileHandler.addProfile(awsProfileName, credentialObject); + profileHelper.setupProfile(awsProfileName, config.askProfile); + Messenger.getInstance().info(`\nAWS profile "${awsProfileName}" was successfully created. \ The details are recorded in aws credentials file (.aws/credentials) located at your **HOME** folder.`); - callback(null, awsProfileName); - }); - }); + callback(null, awsProfileName); + }); }); + }); } /** @@ -130,22 +130,22 @@ The details are recorded in aws credentials file (.aws/credentials) located at y * @private */ function _handleEnvironmentVariableAwsSetup(config, callback) { - if (!_hasEnvironmentVariables()) { - return process.nextTick(() => { - callback(null, false); - }); - } - ui.selectEnvironmentVariables((err, selectEnvVarChoice) => { - if (err) { - return callback(err); - } - if (selectEnvVarChoice === 'No') { - callback(null, false); - } else { - profileHelper.setupProfile(CONSTANTS.PLACEHOLDER.ENVIRONMENT_VAR.AWS_CREDENTIALS, config.askProfile); - callback(null, CONSTANTS.PLACEHOLDER.ENVIRONMENT_VAR.AWS_CREDENTIALS); - } + if (!_hasEnvironmentVariables()) { + return process.nextTick(() => { + callback(null, false); }); + } + ui.selectEnvironmentVariables((err, selectEnvVarChoice) => { + if (err) { + return callback(err); + } + if (selectEnvVarChoice === "No") { + callback(null, false); + } else { + profileHelper.setupProfile(CONSTANTS.PLACEHOLDER.ENVIRONMENT_VAR.AWS_CREDENTIALS, config.askProfile); + callback(null, CONSTANTS.PLACEHOLDER.ENVIRONMENT_VAR.AWS_CREDENTIALS); + } + }); } /** @@ -153,9 +153,9 @@ function _handleEnvironmentVariableAwsSetup(config, callback) { * @private */ function _hasEnvironmentVariables() { - const accessKeyID = process.env.AWS_ACCESS_KEY_ID; - const accessSecretKey = process.env.AWS_SECRET_ACCESS_KEY; - return stringUtils.isNonBlankString(accessKeyID) && stringUtils.isNonBlankString(accessSecretKey); + const accessKeyID = process.env.AWS_ACCESS_KEY_ID; + const accessSecretKey = process.env.AWS_SECRET_ACCESS_KEY; + return stringUtils.isNonBlankString(accessKeyID) && stringUtils.isNonBlankString(accessSecretKey); } /** @@ -166,33 +166,33 @@ function _hasEnvironmentVariables() { * @private */ function _openIamCreateUserPage(isBrowser, userName, callback) { - const params = { - accessKey: true, - step: 'review', - userNames: userName, - permissionType: 'policies', - policies: [ - CONSTANTS.AWS.IAM.USER.POLICY_ARN.IAM_FULL, - CONSTANTS.AWS.IAM.USER.POLICY_ARN.CFN_FULL, - CONSTANTS.AWS.IAM.USER.POLICY_ARN.S3_FULL, - CONSTANTS.AWS.IAM.USER.POLICY_ARN.LAMBDA_FULL, - CONSTANTS.AWS.IAM.USER.POLICY_ARN.CLOUD_WATCH_FULL - ] - }; - const awsIamUrl = `${CONSTANTS.AWS.IAM.USER.NEW_USER_BASE_URL}${querystring.stringify(params)}`; - Messenger.getInstance().info(messages.AWS_CREATE_PROFILE_TITLE); - if (isBrowser) { - setTimeout(() => { - open(awsIamUrl); - callback(); - }, CONSTANTS.CONFIGURATION.OPEN_BROWSER_DELAY); - } else { - Messenger.getInstance().info(messages.AWS_CREATE_PROFILE_NO_BROWSER_OPEN_BROWSER); - Messenger.getInstance().info(` ${awsIamUrl}`); - process.nextTick(() => { - callback(); - }); - } + const params = { + accessKey: true, + step: "review", + userNames: userName, + permissionType: "policies", + policies: [ + CONSTANTS.AWS.IAM.USER.POLICY_ARN.IAM_FULL, + CONSTANTS.AWS.IAM.USER.POLICY_ARN.CFN_FULL, + CONSTANTS.AWS.IAM.USER.POLICY_ARN.S3_FULL, + CONSTANTS.AWS.IAM.USER.POLICY_ARN.LAMBDA_FULL, + CONSTANTS.AWS.IAM.USER.POLICY_ARN.CLOUD_WATCH_FULL, + ], + }; + const awsIamUrl = `${CONSTANTS.AWS.IAM.USER.NEW_USER_BASE_URL}${querystring.stringify(params)}`; + Messenger.getInstance().info(messages.AWS_CREATE_PROFILE_TITLE); + if (isBrowser) { + setTimeout(() => { + open(awsIamUrl); + callback(); + }, CONSTANTS.CONFIGURATION.OPEN_BROWSER_DELAY); + } else { + Messenger.getInstance().info(messages.AWS_CREATE_PROFILE_NO_BROWSER_OPEN_BROWSER); + Messenger.getInstance().info(` ${awsIamUrl}`); + process.nextTick(() => { + callback(); + }); + } } /** @@ -202,15 +202,15 @@ function _openIamCreateUserPage(isBrowser, userName, callback) { * @private */ function _decideAwsProfileName(awsProfileList, callback) { - if (awsProfileList.length === 0) { - // if the credential file is empty, CLI will name the first profile as 'ask_cli_default' - process.nextTick(() => callback(null, CONSTANTS.AWS_DEFAULT_PROFILE_NAME)); - } else { - ui.requestAwsProfileName(awsProfileList, (error, userInputName) => { - if (error) { - return callback(error); - } - callback(null, userInputName); - }); - } + if (awsProfileList.length === 0) { + // if the credential file is empty, CLI will name the first profile as 'ask_cli_default' + process.nextTick(() => callback(null, CONSTANTS.AWS_DEFAULT_PROFILE_NAME)); + } else { + ui.requestAwsProfileName(awsProfileList, (error, userInputName) => { + if (error) { + return callback(error); + } + callback(null, userInputName); + }); + } } diff --git a/lib/commands/configure/helper.js b/lib/commands/configure/helper.js index 729561eb..aa75a60e 100644 --- a/lib/commands/configure/helper.js +++ b/lib/commands/configure/helper.js @@ -1,12 +1,12 @@ -const AppConfig = require('@src/model/app-config'); -const Messenger = require('@src/view/messenger'); +const AppConfig = require("../../model/app-config"); +const Messenger = require("../../view/messenger"); -const askProfileSetupHelper = require('./ask-profile-setup-helper'); -const awsProfileSetupHelper = require('./aws-profile-setup-helper'); -const messages = require('./messages'); +const askProfileSetupHelper = require("./ask-profile-setup-helper"); +const awsProfileSetupHelper = require("./aws-profile-setup-helper"); +const messages = require("./messages"); module.exports = { - initiateAskProfileSetup + initiateAskProfileSetup, }; /** @@ -15,37 +15,40 @@ module.exports = { * @param {Function} callback */ function initiateAskProfileSetup(config, callback) { - Messenger.getInstance().warn(messages.LWA_TOKEN_SHARE_WARN_MESSAGE); - askProfileSetupHelper.setupAskToken(config, (accessTokenError, accessToken) => { - if (accessTokenError) { - return callback(accessTokenError); - } - AppConfig.getInstance().setToken(config.askProfile, accessToken); - Messenger.getInstance().info(`ASK Profile "${config.askProfile}" was successfully created. ` - + 'The details are recorded in ask-cli config file (.ask/cli_config) located at your **HOME** folder.'); - AppConfig.getInstance().write(); + Messenger.getInstance().warn(messages.LWA_TOKEN_SHARE_WARN_MESSAGE); + askProfileSetupHelper.setupAskToken(config, (accessTokenError, accessToken) => { + if (accessTokenError) { + return callback(accessTokenError); + } + AppConfig.getInstance().setToken(config.askProfile, accessToken); + Messenger.getInstance().info( + `ASK Profile "${config.askProfile}" was successfully created. ` + + "The details are recorded in ask-cli config file (.ask/cli_config) located at your **HOME** folder.", + ); + AppConfig.getInstance().write(); - askProfileSetupHelper.setupVendorId(config, (vendorIdError, vendorId) => { - if (vendorIdError) { - return callback(vendorIdError); - } - AppConfig.getInstance().setVendorId(config.askProfile, vendorId); - Messenger.getInstance().info(`Vendor ID set as ${vendorId}.\n`); - AppConfig.getInstance().write(); + askProfileSetupHelper.setupVendorId(config, (vendorIdError, vendorId) => { + if (vendorIdError) { + return callback(vendorIdError); + } + AppConfig.getInstance().setVendorId(config.askProfile, vendorId); + Messenger.getInstance().info(`Vendor ID set as ${vendorId}.\n`); + AppConfig.getInstance().write(); - Messenger.getInstance().info(messages.AWS_CONFIGURATION_MESSAGE); - Messenger.getInstance().warn(messages.AWS_SECRET_ACCESS_KEY_AND_ID_SHARE_WARN_MESSAGE); - awsProfileSetupHelper.setupAwsProfile(config, (awsProfileError, awsProfile) => { - if (awsProfileError) { - return callback(awsProfileError); - } - if (awsProfile) { - Messenger.getInstance().info(`AWS profile "${awsProfile}" was successfully ` - + `associated with your ASK profile "${config.askProfile}".\n`); - } - AppConfig.getInstance().setAwsProfile(config.askProfile, awsProfile); - callback(null, config.askProfile); - }); - }); + Messenger.getInstance().info(messages.AWS_CONFIGURATION_MESSAGE); + Messenger.getInstance().warn(messages.AWS_SECRET_ACCESS_KEY_AND_ID_SHARE_WARN_MESSAGE); + awsProfileSetupHelper.setupAwsProfile(config, (awsProfileError, awsProfile) => { + if (awsProfileError) { + return callback(awsProfileError); + } + if (awsProfile) { + Messenger.getInstance().info( + `AWS profile "${awsProfile}" was successfully ` + `associated with your ASK profile "${config.askProfile}".\n`, + ); + } + AppConfig.getInstance().setAwsProfile(config.askProfile, awsProfile); + callback(null, config.askProfile); + }); }); + }); } diff --git a/lib/commands/configure/index.js b/lib/commands/configure/index.js deleted file mode 100644 index 21921853..00000000 --- a/lib/commands/configure/index.js +++ /dev/null @@ -1,120 +0,0 @@ -const fs = require('fs-extra'); -const jsonfile = require('jsonfile'); -const os = require('os'); -const path = require('path'); - -const { AbstractCommand } = require('@src/commands/abstract-command'); -const optionModel = require('@src/commands/option-model'); -const AppConfig = require('@src/model/app-config'); -const CONSTANTS = require('@src/utils/constants'); -const stringUtils = require('@src/utils/string-utils'); -const Messenger = require('@src/view/messenger'); - -const helper = require('./helper'); -const messages = require('./messages'); -const ui = require('./ui'); - -class ConfigureCommand extends AbstractCommand { - name() { - return 'configure'; - } - - description() { - return 'helps to configure the credentials that ask-cli uses to authenticate the user to Amazon developer services'; - } - - requiredOptions() { - return []; - } - - optionalOptions() { - return ['no-browser', 'profile', 'debug']; - } - - handle(cmd, cb) { - Messenger.getInstance().info(messages.ASK_CLI_CONFIGURATION_MESSAGE); - let askProfileConfig; - try { - askProfileConfig = _ensureAppConfigInitiated(cmd); - } catch (appConfigError) { - Messenger.getInstance().error(appConfigError); - return cb(appConfigError); - } - - _initiateAskProfileSetup(askProfileConfig, (setupError, askProfile) => { - if (setupError) { - Messenger.getInstance().error(setupError); - return cb(setupError); - } - const appConfig = AppConfig.getInstance(); - Messenger.getInstance().info(messages.CONFIGURE_SETUP_SUCCESS_MESSAGE); - Messenger.getInstance().info(`ASK Profile: ${askProfile}`); - Messenger.getInstance().info(`AWS Profile: ${appConfig.getAwsProfile(askProfile)}`); - Messenger.getInstance().info(`Vendor ID: ${appConfig.getVendorId(askProfile)}`); - AppConfig.dispose(); - cb(); - }); - } -} - -/** - * Initiates ASK profile setup. - * @param {Object} askProfileConfig - * @param {Function} callback - * @private - */ -function _initiateAskProfileSetup(askProfileConfig, callback) { - if (askProfileConfig.isFirstTimeProfileCreation || askProfileConfig.askProfile) { - const profile = (askProfileConfig.askProfile || CONSTANTS.ASK_DEFAULT_PROFILE_NAME).trim(); - if (!stringUtils.validateSyntax('PROFILE_NAME', profile)) { - return callback(messages.PROFILE_NAME_VALIDATION_ERROR); - } - askProfileConfig.askProfile = profile; - return helper.initiateAskProfileSetup(askProfileConfig, (err, askProfile) => callback(err, askProfile)); - } - ui.createOrUpdateProfile(AppConfig.getInstance().getProfilesList(), (error, profile) => { - if (error) { - return callback(error); - } - askProfileConfig.askProfile = profile; - helper.initiateAskProfileSetup(askProfileConfig, (err, askProfile) => callback(err, askProfile)); - }); -} - -/** - * Ensures AppConfig is initiated properly before proceeding to further steps. - * @param {Object} cmd commander object. - * @private - */ -function _ensureAppConfigInitiated(cmd) { - const askFolderPath = path.join(os.homedir(), CONSTANTS.FILE_PATH.ASK.HIDDEN_FOLDER); - const configFilePath = path.join(askFolderPath, CONSTANTS.FILE_PATH.ASK.PROFILE_FILE); - if (!fs.existsSync(configFilePath)) { - fs.ensureDirSync(askFolderPath); - jsonfile.writeFileSync(configFilePath, { profiles: {} }, { spaces: CONSTANTS.CONFIGURATION.JSON_DISPLAY_INDENT, - mode: CONSTANTS.FILE_PERMISSION.USER_READ_WRITE }); - } - new AppConfig(configFilePath); - return _buildAskConfig(cmd, askFolderPath, configFilePath); -} - -/** - * Build configuration from input CLI arguments. - * @param {Object} cmd commander object. - * @param {String} askFolderPath ask folder path. - * @param {String} configFilePath cli_config file path. - * @private - */ -function _buildAskConfig(cmd, askFolderPath, configFilePath) { - return { - askFolderPath, - configFilePath, - isFirstTimeProfileCreation: AppConfig.getInstance().getProfilesList().length < 1, - askProfile: cmd.profile, - needBrowser: cmd.browser, - doDebug: cmd.debug - }; -} - -module.exports = ConfigureCommand; -module.exports.createCommand = new ConfigureCommand(optionModel).createCommand(); diff --git a/lib/commands/configure/index.ts b/lib/commands/configure/index.ts new file mode 100644 index 00000000..3717c780 --- /dev/null +++ b/lib/commands/configure/index.ts @@ -0,0 +1,126 @@ +import fs from "fs-extra"; +import jsonfile from "jsonfile"; +import os from "os"; +import path from "path"; +import {AbstractCommand} from "../abstract-command"; +import optionModel from "../option-model.json"; +import AppConfig from "../../model/app-config"; +import CONSTANTS from "../../utils/constants"; +import stringUtils from "../../utils/string-utils"; +import Messenger from "../../view/messenger"; +import helper from "./helper"; +import messages from "./messages"; +import ui from "./ui"; +import {OptionModel} from "../option-validator"; + +export default class ConfigureCommand extends AbstractCommand { + name() { + return "configure"; + } + + description() { + return "helps to configure the credentials that ask-cli uses to authenticate the user to Amazon developer services"; + } + + requiredOptions() { + return []; + } + + optionalOptions() { + return ["no-browser", "profile", "debug"]; + } + + async handle(cmd: Record): Promise { + Messenger.getInstance().info(messages.ASK_CLI_CONFIGURATION_MESSAGE); + try { + const askProfileConfig = _ensureAppConfigInitiated(cmd); + const askProfile = await _initiateAskProfileSetup(askProfileConfig); + + const appConfig = AppConfig.getInstance(); + Messenger.getInstance().info(messages.CONFIGURE_SETUP_SUCCESS_MESSAGE); + Messenger.getInstance().info(`ASK Profile: ${askProfile}`); + Messenger.getInstance().info(`AWS Profile: ${appConfig.getAwsProfile(askProfile)}`); + Messenger.getInstance().info(`Vendor ID: ${appConfig.getVendorId(askProfile)}`); + AppConfig.dispose(); + } catch (error) { + Messenger.getInstance().error(error); + throw error; + } + } +} + +/** + * Initiates ASK profile setup. + * @param {Object} askProfileConfig + * @param {Function} callback + * @private + */ +async function _initiateAskProfileSetup(askProfileConfig: Record): Promise { + if (askProfileConfig.isFirstTimeProfileCreation || askProfileConfig.askProfile) { + const profile = (askProfileConfig.askProfile || CONSTANTS.ASK_DEFAULT_PROFILE_NAME).trim(); + if (!stringUtils.validateSyntax("PROFILE_NAME", profile)) { + throw messages.PROFILE_NAME_VALIDATION_ERROR; + } + return new Promise((resolve, reject) => { + helper.initiateAskProfileSetup({...askProfileConfig, askProfile: profile}, (err: any, askProfile: string) => { + if (err) { + return reject(err); + } + resolve(askProfile); + }); + }); + } + return new Promise((resolve, reject) => { + ui.createOrUpdateProfile(AppConfig.getInstance().getProfilesList(), (error: any, profile: string) => { + if (error) { + return reject(error); + } + helper.initiateAskProfileSetup({...askProfileConfig, askProfile: profile}, (err: any, askProfile: string) => { + if (err) { + return reject(err); + } + resolve(askProfile); + }); + }); + }); +} + +/** + * Ensures AppConfig is initiated properly before proceeding to further steps. + * @param {Object} cmd commander object. + * @private + */ +function _ensureAppConfigInitiated(cmd: Record) { + const askFolderPath = path.join(os.homedir(), CONSTANTS.FILE_PATH.ASK.HIDDEN_FOLDER); + const configFilePath = path.join(askFolderPath, CONSTANTS.FILE_PATH.ASK.PROFILE_FILE); + if (!fs.existsSync(configFilePath)) { + fs.ensureDirSync(askFolderPath); + jsonfile.writeFileSync( + configFilePath, + {profiles: {}}, + {spaces: CONSTANTS.CONFIGURATION.JSON_DISPLAY_INDENT, mode: CONSTANTS.FILE_PERMISSION.USER_READ_WRITE}, + ); + } + new AppConfig(configFilePath); + return _buildAskConfig(cmd, askFolderPath, configFilePath); +} + +/** + * Build configuration from input CLI arguments. + * @param {Object} cmd commander object. + * @param {String} askFolderPath ask folder path. + * @param {String} configFilePath cli_config file path. + * @private + */ +function _buildAskConfig(cmd: Record, askFolderPath: string, configFilePath: string) { + return { + askFolderPath, + configFilePath, + isFirstTimeProfileCreation: AppConfig.getInstance().getProfilesList().length < 1, + askProfile: cmd.profile, + needBrowser: cmd.browser, + doDebug: cmd.debug, + }; +} + +export const createCommand = new ConfigureCommand(optionModel as OptionModel).createCommand(); diff --git a/lib/commands/configure/messages.js b/lib/commands/configure/messages.js index c8968e35..8083f008 100644 --- a/lib/commands/configure/messages.js +++ b/lib/commands/configure/messages.js @@ -1,30 +1,38 @@ /* eslint-disable max-len */ -module.exports.ASK_SIGN_IN_FAILURE_MESSAGE = 'Access not granted. Please verify your account credentials are correct.\n' -+ 'If this is your first time getting the error, please retry "ask configure" to ensure any browser-cached tokens are refreshed.'; +module.exports.ASK_SIGN_IN_FAILURE_MESSAGE = + "Access not granted. Please verify your account credentials are correct.\n" + + 'If this is your first time getting the error, please retry "ask configure" to ensure any browser-cached tokens are refreshed.'; module.exports.ASK_CLI_CONFIGURATION_MESSAGE = `This command will configure the ASK CLI with a profile associated with your Amazon developer credentials. ------------------------- Step 1 of 2 : ASK CLI Configuration -------------------------`; -module.exports.PROFILE_NAME_VALIDATION_ERROR = 'Invalid profile name. A profile name can contain upper and lowercase letters, numbers, hyphens, and underscores.'; +module.exports.PROFILE_NAME_VALIDATION_ERROR = + "Invalid profile name. A profile name can contain upper and lowercase letters, numbers, hyphens, and underscores."; module.exports.CONFIGURE_SETUP_SUCCESS_MESSAGE = `------------------------- Configuration Complete ------------------------- Here is the summary for the profile setup: `; -module.exports.VENDOR_INFO_FETCH_ERROR = 'Could not retrieve vendor data.'; +module.exports.VENDOR_INFO_FETCH_ERROR = "Could not retrieve vendor data."; -module.exports.VENDOR_ID_CREATE_INSTRUCTIONS = 'There is no Vendor ID associated with your account. To setup Vendor ID, please follow the instructions here: https://developer.amazon.com/en-US/docs/alexa/smapi/manage-credentials-with-ask-cli.html#vendor-id'; +module.exports.VENDOR_ID_CREATE_INSTRUCTIONS = + "There is no Vendor ID associated with your account. To setup Vendor ID, please follow the instructions here: https://developer.amazon.com/en-US/docs/alexa/smapi/manage-credentials-with-ask-cli.html#vendor-id"; -module.exports.AWS_CONFIGURATION_MESSAGE = '------------------------- Step 2 of 2 : Associate an AWS Profile with ASK CLI -------------------------'; +module.exports.AWS_CONFIGURATION_MESSAGE = + "------------------------- Step 2 of 2 : Associate an AWS Profile with ASK CLI -------------------------"; -module.exports.AWS_CREATE_PROFILE_TITLE = '\nComplete the IAM user creation with required permissions from the AWS console, then come back to the terminal.'; +module.exports.AWS_CREATE_PROFILE_TITLE = + "\nComplete the IAM user creation with required permissions from the AWS console, then come back to the terminal."; -module.exports.AWS_CREATE_PROFILE_NO_BROWSER_OPEN_BROWSER = 'Please open the following url in your browser:'; +module.exports.AWS_CREATE_PROFILE_NO_BROWSER_OPEN_BROWSER = "Please open the following url in your browser:"; -module.exports.ACCESS_SECRET_KEY_AND_ID_SETUP = '\nPlease fill in the "Access Key ID" and "Secret Access Key" from the IAM user creation final page.'; +module.exports.ACCESS_SECRET_KEY_AND_ID_SETUP = + '\nPlease fill in the "Access Key ID" and "Secret Access Key" from the IAM user creation final page.'; module.exports.SKIP_AWS_CONFIGURATION = `------------------------- Skipping the AWS profile association ------------------------- You will only be able to deploy your Alexa skill. To set up AWS credentials later, use the "ask configure" command towards the same profile again.`; -module.exports.LWA_TOKEN_SHARE_WARN_MESSAGE = 'ASK CLI uses authorization code to fetch LWA tokens. Do not share neither your authorization code nor access tokens.'; +module.exports.LWA_TOKEN_SHARE_WARN_MESSAGE = + "ASK CLI uses authorization code to fetch LWA tokens. Do not share neither your authorization code nor access tokens."; -module.exports.AWS_SECRET_ACCESS_KEY_AND_ID_SHARE_WARN_MESSAGE = 'ASK CLI will create an IAM user and generate corresponding access key id and secret access key. Do not share neither of them.'; +module.exports.AWS_SECRET_ACCESS_KEY_AND_ID_SHARE_WARN_MESSAGE = + "ASK CLI will create an IAM user and generate corresponding access key id and secret access key. Do not share neither of them."; diff --git a/lib/commands/configure/questions.js b/lib/commands/configure/questions.js index 907b5766..5760b2ea 100644 --- a/lib/commands/configure/questions.js +++ b/lib/commands/configure/questions.js @@ -1,96 +1,111 @@ -const CONSTANTS = require('@src/utils/constants'); -const stringUtils = require('@src/utils/string-utils'); +const CONSTANTS = require("../../utils/constants"); +const stringUtils = require("../../utils/string-utils"); module.exports = { - REQUEST_ASK_PROFILE_NAME: [{ - message: `Please provide a profile name or press enter to use ${CONSTANTS.ASK_DEFAULT_PROFILE_NAME} as the profile name: `, - type: 'input', - name: 'profile', - default: CONSTANTS.ASK_DEFAULT_PROFILE_NAME - }], - SELECT_VENDOR_ID: [{ - type: 'rawlist', - message: 'Your Amazon developer account has multiple Vendor IDs. Please choose the Vendor ID for the skills you want to manage.', - name: 'selectedVendor' - }], - CREATE_NEW_OR_OVERRIDE: [{ - type: 'list', - message: 'Please create a new profile or overwrite the existing profile.\n', - name: 'profile' - }], - REQUEST_AWS_PROFILE_NAME: existingProfiles => [{ - type: 'input', - name: 'awsProfileName', - message: 'Please provide your AWS profile name: ', - default: existingProfiles.includes(CONSTANTS.AWS_DEFAULT_PROFILE_NAME) ? null - : CONSTANTS.AWS_DEFAULT_PROFILE_NAME, - validate: (input) => { - if (!stringUtils.isNonBlankString(input)) { - return 'Profile name can not be blank string.'; - } - if (existingProfiles.includes(input.trim())) { - return `[${input}] already exists in existing AWS profiles. Please try again with another name.`; - } - return true; + REQUEST_ASK_PROFILE_NAME: [ + { + message: `Please provide a profile name or press enter to use ${CONSTANTS.ASK_DEFAULT_PROFILE_NAME} as the profile name: `, + type: "input", + name: "profile", + default: CONSTANTS.ASK_DEFAULT_PROFILE_NAME, + }, + ], + SELECT_VENDOR_ID: [ + { + type: "rawlist", + message: "Your Amazon developer account has multiple Vendor IDs. Please choose the Vendor ID for the skills you want to manage.", + name: "selectedVendor", + }, + ], + CREATE_NEW_OR_OVERRIDE: [ + { + type: "list", + message: "Please create a new profile or overwrite the existing profile.\n", + name: "profile", + }, + ], + REQUEST_AWS_PROFILE_NAME: (existingProfiles) => [ + { + type: "input", + name: "awsProfileName", + message: "Please provide your AWS profile name: ", + default: existingProfiles.includes(CONSTANTS.AWS_DEFAULT_PROFILE_NAME) ? null : CONSTANTS.AWS_DEFAULT_PROFILE_NAME, + validate: (input) => { + if (!stringUtils.isNonBlankString(input)) { + return "Profile name can not be blank string."; } - }], - CONFIRM_OVERRIDING_PROFILE: [{ - type: 'confirm', - name: 'overwrite', - default: true - }], - USE_ENVIRONMENT_VARIABLES: [{ - message: 'We have detected you have AWS environment variables. Would you like to setup your profile using those?', - type: 'list', - name: 'choice', - choices: ['Yes', 'No'] - }], - SET_UP_AWS_PROFILE: [{ - message: 'Do you want to link your AWS account in order to host your Alexa skills?', - type: 'confirm', - name: 'choice', - default: true - }], - SELECT_OR_CREATE_AWS_PROFILE: [{ - type: 'list', - name: 'chosenProfile', - message: 'Please choose from the following existing AWS profiles or create a new one.' - }], - REQUEST_ACCESS_SECRET_KEY_AND_ID: [ - { - type: 'input', - name: 'accessKeyId', - message: 'AWS Access Key ID: ', - validate(input) { - if (!input.trim()) { - return '"AWS Access Key ID" cannot be empty.'; - } - return true; - } - }, - { - type: 'password', - name: 'secretAccessKey', - message: 'AWS Secret Access Key: ', - validate(input) { - if (!input.trim()) { - return '"AWS Secret Access Key" cannot be empty.'; - } - return true; - } + if (existingProfiles.includes(input.trim())) { + return `[${input}] already exists in existing AWS profiles. Please try again with another name.`; } - ], - REQUEST_AUTH_CODE: [ - { - type: 'input', - name: 'authCode', - message: 'Please enter the Authorization Code: ', - validate: (value) => { - if (!stringUtils.isNonBlankString(value.trim())) { - return 'Please enter a valid Authorization Code.'; - } - return true; - } + return true; + }, + }, + ], + CONFIRM_OVERRIDING_PROFILE: [ + { + type: "confirm", + name: "overwrite", + default: true, + }, + ], + USE_ENVIRONMENT_VARIABLES: [ + { + message: "We have detected you have AWS environment variables. Would you like to setup your profile using those?", + type: "list", + name: "choice", + choices: ["Yes", "No"], + }, + ], + SET_UP_AWS_PROFILE: [ + { + message: "Do you want to link your AWS account in order to host your Alexa skills?", + type: "confirm", + name: "choice", + default: true, + }, + ], + SELECT_OR_CREATE_AWS_PROFILE: [ + { + type: "list", + name: "chosenProfile", + message: "Please choose from the following existing AWS profiles or create a new one.", + }, + ], + REQUEST_ACCESS_SECRET_KEY_AND_ID: [ + { + type: "input", + name: "accessKeyId", + message: "AWS Access Key ID: ", + validate(input) { + if (!input.trim()) { + return '"AWS Access Key ID" cannot be empty.'; } - ] + return true; + }, + }, + { + type: "password", + name: "secretAccessKey", + message: "AWS Secret Access Key: ", + validate(input) { + if (!input.trim()) { + return '"AWS Secret Access Key" cannot be empty.'; + } + return true; + }, + }, + ], + REQUEST_AUTH_CODE: [ + { + type: "input", + name: "authCode", + message: "Please enter the Authorization Code: ", + validate: (value) => { + if (!stringUtils.isNonBlankString(value.trim())) { + return "Please enter a valid Authorization Code."; + } + return true; + }, + }, + ], }; diff --git a/lib/commands/configure/ui.js b/lib/commands/configure/ui.js index 0c5edd58..909669f2 100644 --- a/lib/commands/configure/ui.js +++ b/lib/commands/configure/ui.js @@ -1,51 +1,57 @@ -const inquirer = require('inquirer'); -const Messenger = require('@src/view/messenger'); -const stringUtils = require('@src/utils/string-utils'); +const inquirer = require("inquirer"); +const Messenger = require("../../view/messenger"); +const stringUtils = require("../../utils/string-utils"); -const messages = require('./messages'); -const questions = require('./questions'); +const messages = require("./messages"); +const questions = require("./questions"); module.exports = { - createNewProfile, - chooseVendorId, - requestAwsProfileName, - confirmSettingAws, - selectEnvironmentVariables, - addNewCredentials, - createOrUpdateProfile, - createNewOrSelectAWSProfile, - getAuthCode, - profileFormatter + createNewProfile, + chooseVendorId, + requestAwsProfileName, + confirmSettingAws, + selectEnvironmentVariables, + addNewCredentials, + createOrUpdateProfile, + createNewOrSelectAWSProfile, + getAuthCode, + profileFormatter, }; /** -* Ask the auth code from the user. -* @param callback Authorization code -* @private -*/ + * Ask the auth code from the user. + * @param callback Authorization code + * @private + */ function getAuthCode(callback) { - inquirer.prompt(questions.REQUEST_AUTH_CODE).then((answer) => { - callback(null, answer.authCode); - }).catch((error) => { - callback(error); + inquirer + .prompt(questions.REQUEST_AUTH_CODE) + .then((answer) => { + callback(null, answer.authCode); + }) + .catch((error) => { + callback(error); }); } // ASK profile setup flow /** -* Requests for a new profile name. -* @param {Function} callback -*/ + * Requests for a new profile name. + * @param {Function} callback + */ function createNewProfile(callback) { - inquirer.prompt(questions.REQUEST_ASK_PROFILE_NAME).then((answer) => { - const newProfileName = answer.profile.trim(); - if (!stringUtils.validateSyntax('PROFILE_NAME', newProfileName)) { - return callback(messages.PROFILE_NAME_VALIDATION_ERROR); - } - callback(null, newProfileName); - }).catch((error) => { - callback(error); + inquirer + .prompt(questions.REQUEST_ASK_PROFILE_NAME) + .then((answer) => { + const newProfileName = answer.profile.trim(); + if (!stringUtils.validateSyntax("PROFILE_NAME", newProfileName)) { + return callback(messages.PROFILE_NAME_VALIDATION_ERROR); + } + callback(null, newProfileName); + }) + .catch((error) => { + callback(error); }); } @@ -56,14 +62,17 @@ function createNewProfile(callback) { * @param {Function} callback */ function chooseVendorId(VENDOR_PAGE_SIZE, vendorInfo, callback) { - const question = questions.SELECT_VENDOR_ID; - question[0].pageSize = VENDOR_PAGE_SIZE; - question[0].choices = _buildVendorJSONString(vendorInfo); - inquirer.prompt(question).then((answers) => { - const vendorId = answers.selectedVendor.substr(answers.selectedVendor.lastIndexOf(':') + 2); - callback(null, vendorId); - }).catch((error) => { - callback(error); + const question = questions.SELECT_VENDOR_ID; + question[0].pageSize = VENDOR_PAGE_SIZE; + question[0].choices = _buildVendorJSONString(vendorInfo); + inquirer + .prompt(question) + .then((answers) => { + const vendorId = answers.selectedVendor.substr(answers.selectedVendor.lastIndexOf(":") + 2); + callback(null, vendorId); + }) + .catch((error) => { + callback(error); }); } @@ -72,7 +81,7 @@ function chooseVendorId(VENDOR_PAGE_SIZE, vendorInfo, callback) { * @param {Object} vendorInfo | object encapsulating vendor name and ID. */ function _buildVendorJSONString(vendorInfo) { - return vendorInfo.map(vendor => `${vendor.name}: ${vendor.id}`); + return vendorInfo.map((vendor) => `${vendor.name}: ${vendor.id}`); } /** @@ -80,35 +89,38 @@ function _buildVendorJSONString(vendorInfo) { * @param {Function} callback */ function createOrUpdateProfile(profiles, callback) { - const profileList = profileFormatter(profiles); - const NUMBER_OF_PROFILES_PER_PAGE = 50; - const HEADER = 'Profile Associated AWS Profile'; - const CREATE_PROFILE_MESSAGE = 'Create new profile'; - profileList.splice(0, 0, new inquirer.Separator()); - profileList.splice(1, 0, CREATE_PROFILE_MESSAGE); - profileList.splice(2, 0, new inquirer.Separator()); - profileList.splice(3, 0, new inquirer.Separator(HEADER)); - const question = questions.CREATE_NEW_OR_OVERRIDE; - question[0].pageSize = NUMBER_OF_PROFILES_PER_PAGE; - question[0].choices = profileList; - inquirer.prompt(question).then((answers) => { - if (answers.profile === CREATE_PROFILE_MESSAGE) { - createNewProfile((error, profileName) => { - if (error) { - return callback(error); - } - callback(null, profileName); - }); - } else { - const profile = answers.profile.split(' ')[0].trim().replace(/\[/, '').replace(/\]/, ''); - if (!stringUtils.validateSyntax('PROFILE_NAME', profile)) { - callback(messages.PROFILE_NAME_VALIDATION_ERROR); - return; - } - callback(null, profile); + const profileList = profileFormatter(profiles); + const NUMBER_OF_PROFILES_PER_PAGE = 50; + const HEADER = "Profile Associated AWS Profile"; + const CREATE_PROFILE_MESSAGE = "Create new profile"; + profileList.splice(0, 0, new inquirer.Separator()); + profileList.splice(1, 0, CREATE_PROFILE_MESSAGE); + profileList.splice(2, 0, new inquirer.Separator()); + profileList.splice(3, 0, new inquirer.Separator(HEADER)); + const question = questions.CREATE_NEW_OR_OVERRIDE; + question[0].pageSize = NUMBER_OF_PROFILES_PER_PAGE; + question[0].choices = profileList; + inquirer + .prompt(question) + .then((answers) => { + if (answers.profile === CREATE_PROFILE_MESSAGE) { + createNewProfile((error, profileName) => { + if (error) { + return callback(error); + } + callback(null, profileName); + }); + } else { + const profile = answers.profile.split(" ")[0].trim().replace(/\[/, "").replace(/\]/, ""); + if (!stringUtils.validateSyntax("PROFILE_NAME", profile)) { + callback(messages.PROFILE_NAME_VALIDATION_ERROR); + return; } - }).catch((error) => { - callback(error); + callback(null, profile); + } + }) + .catch((error) => { + callback(error); }); } @@ -120,10 +132,13 @@ function createOrUpdateProfile(profiles, callback) { * @param {Function} callback */ function requestAwsProfileName(awsProfileList, callback) { - inquirer.prompt(questions.REQUEST_AWS_PROFILE_NAME(awsProfileList)).then((answer) => { - callback(null, answer.awsProfileName.trim()); - }).catch((error) => { - callback(error); + inquirer + .prompt(questions.REQUEST_AWS_PROFILE_NAME(awsProfileList)) + .then((answer) => { + callback(null, answer.awsProfileName.trim()); + }) + .catch((error) => { + callback(error); }); } @@ -132,10 +147,13 @@ function requestAwsProfileName(awsProfileList, callback) { * @param {Function} callback */ function confirmSettingAws(callback) { - inquirer.prompt(questions.SET_UP_AWS_PROFILE).then((answer) => { - callback(null, answer.choice); - }).catch((error) => { - callback(error); + inquirer + .prompt(questions.SET_UP_AWS_PROFILE) + .then((answer) => { + callback(null, answer.choice); + }) + .catch((error) => { + callback(error); }); } @@ -144,10 +162,13 @@ function confirmSettingAws(callback) { * @param {Function} callback */ function selectEnvironmentVariables(callback) { - inquirer.prompt(questions.USE_ENVIRONMENT_VARIABLES).then((answer) => { - callback(null, answer.choice); - }).catch((error) => { - callback(error); + inquirer + .prompt(questions.USE_ENVIRONMENT_VARIABLES) + .then((answer) => { + callback(null, answer.choice); + }) + .catch((error) => { + callback(error); }); } @@ -156,15 +177,18 @@ function selectEnvironmentVariables(callback) { * @param {Function} callback */ function addNewCredentials(callback) { - Messenger.getInstance().info(messages.ACCESS_SECRET_KEY_AND_ID_SETUP); - inquirer.prompt(questions.REQUEST_ACCESS_SECRET_KEY_AND_ID).then((answer) => { - const credentialObject = { - aws_access_key_id: answer.accessKeyId.trim(), - aws_secret_access_key: answer.secretAccessKey.trim() - }; - callback(null, credentialObject); - }).catch((error) => { - callback(error); + Messenger.getInstance().info(messages.ACCESS_SECRET_KEY_AND_ID_SETUP); + inquirer + .prompt(questions.REQUEST_ACCESS_SECRET_KEY_AND_ID) + .then((answer) => { + const credentialObject = { + aws_access_key_id: answer.accessKeyId.trim(), + aws_secret_access_key: answer.secretAccessKey.trim(), + }; + callback(null, credentialObject); + }) + .catch((error) => { + callback(error); }); } @@ -173,18 +197,21 @@ function addNewCredentials(callback) { * @param {Function} callback */ function createNewOrSelectAWSProfile(awsProfileList, callback) { - const AWS_DISPLAY_PAGE_SIZE = 25; - const CREATE_NEW_PROFILE = 'Create new profile'; - awsProfileList.push(new inquirer.Separator()); - awsProfileList.push(CREATE_NEW_PROFILE); - awsProfileList.push(new inquirer.Separator()); - const question = questions.SELECT_OR_CREATE_AWS_PROFILE; - question[0].pageSize = AWS_DISPLAY_PAGE_SIZE; - question[0].choices = awsProfileList; - inquirer.prompt(question).then((answer) => { - callback(null, answer.chosenProfile); - }).catch((error) => { - callback(error); + const AWS_DISPLAY_PAGE_SIZE = 25; + const CREATE_NEW_PROFILE = "Create new profile"; + awsProfileList.push(new inquirer.Separator()); + awsProfileList.push(CREATE_NEW_PROFILE); + awsProfileList.push(new inquirer.Separator()); + const question = questions.SELECT_OR_CREATE_AWS_PROFILE; + question[0].pageSize = AWS_DISPLAY_PAGE_SIZE; + question[0].choices = awsProfileList; + inquirer + .prompt(question) + .then((answer) => { + callback(null, answer.chosenProfile); + }) + .catch((error) => { + callback(error); }); } @@ -194,22 +221,22 @@ function createNewOrSelectAWSProfile(awsProfileList, callback) { * @private */ function profileFormatter(profileList) { - const FORMATTER_SPACING = 26; - if (!profileList || profileList.length === 0) { - return null; + const FORMATTER_SPACING = 26; + if (!profileList || profileList.length === 0) { + return null; + } + const formattedProfileList = []; + for (const profileObj of profileList) { + const formattedASKProfile = `[${profileObj.askProfile}]`; + let fillingSpace = " "; + if (formattedASKProfile.length <= FORMATTER_SPACING) { + fillingSpace = " ".repeat(FORMATTER_SPACING - formattedASKProfile.length); } - const formattedProfileList = []; - for (const profileObj of profileList) { - const formattedASKProfile = `[${profileObj.askProfile}]`; - let fillingSpace = ' '; - if (formattedASKProfile.length <= FORMATTER_SPACING) { - fillingSpace = ' '.repeat(FORMATTER_SPACING - formattedASKProfile.length); - } - if (!profileObj.awsProfile) { - formattedProfileList.push(`${formattedASKProfile}${fillingSpace}** NULL **`); - continue; - } - formattedProfileList.push(`${formattedASKProfile}${fillingSpace}"${profileObj.awsProfile}"`); + if (!profileObj.awsProfile) { + formattedProfileList.push(`${formattedASKProfile}${fillingSpace}** NULL **`); + continue; } - return formattedProfileList; + formattedProfileList.push(`${formattedASKProfile}${fillingSpace}"${profileObj.awsProfile}"`); + } + return formattedProfileList; } diff --git a/lib/commands/deploy/helper.js b/lib/commands/deploy/helper.js index ec9c242a..fe2a1e5d 100644 --- a/lib/commands/deploy/helper.js +++ b/lib/commands/deploy/helper.js @@ -1,27 +1,40 @@ -const SkillMetadataController = require('@src/controllers/skill-metadata-controller'); -const SkillCodeController = require('@src/controllers/skill-code-controller'); -const SkillInfrastructureController = require('@src/controllers/skill-infrastructure-controller'); -const CliError = require('@src/exceptions/cli-error'); -const ResourcesConfig = require('@src/model/resources-config'); -const profileHelper = require('@src/utils/profile-helper'); -const CONSTANTS = require('@src/utils/constants'); -const Messenger = require('@src/view/messenger'); +const SkillMetadataController = require("../../controllers/skill-metadata-controller"); +const SkillCodeController = require("../../controllers/skill-code-controller"); +const SkillInfrastructureController = require("../../controllers/skill-infrastructure-controller"); +const CliError = require("../../exceptions/cli-error"); +const ResourcesConfig = require("../../model/resources-config"); +const profileHelper = require("../../utils/profile-helper"); +const CONSTANTS = require("../../utils/constants"); +const Messenger = require("../../view/messenger"); +const acUtils = require("../../utils/ac-util"); module.exports = { - confirmProfile, - deploySkillMetadata, - buildSkillCode, - deploySkillInfrastructure, - enableSkill + confirmProfile, + deploySkillMetadata, + buildSkillCode, + deploySkillInfrastructure, + enableSkill, + getDeploymentType, }; function confirmProfile(profile) { - if (!ResourcesConfig.getInstance().getProfile(profile)) { - throw new CliError(`Profile [${profile}] does not exist. \ + if (!ResourcesConfig.getInstance().getProfile(profile)) { + throw new CliError(`Profile [${profile}] does not exist. \ Please configure it in your ${CONSTANTS.FILE_PATH.ASK_RESOURCES_JSON_CONFIG} file.`); - } + } + + Messenger.getInstance().info(`Deploy project for profile [${profile}]\n`); +} - Messenger.getInstance().info(`Deploy project for profile [${profile}]\n`); +/** + * Checks if the user's skill structure is ACDL, if so it returns alexa-conversations, + * otherwise it returns interaction-model. + */ +function getDeploymentType(profile) { + if (acUtils.isAcSkill(profile)) { + return CONSTANTS.DEPLOYMENT_TYPE.ALEXA_CONVERSATIONS; + } + return CONSTANTS.DEPLOYMENT_TYPE.INTERACTION_MODEL; } /** @@ -31,20 +44,20 @@ Please configure it in your ${CONSTANTS.FILE_PATH.ASK_RESOURCES_JSON_CONFIG} fil * @param {*} callback (error) */ function deploySkillMetadata(options, callback) { - let vendorId, skillMetaController; - const { profile, doDebug, ignoreHash } = options; - try { - vendorId = profileHelper.resolveVendorId(profile); - skillMetaController = new SkillMetadataController({ profile, doDebug }); - } catch (err) { - return callback(err); + let vendorId, skillMetaController; + const {profile, doDebug, ignoreHash} = options; + try { + vendorId = profileHelper.resolveVendorId(profile); + skillMetaController = new SkillMetadataController({profile, doDebug}); + } catch (err) { + return callback(err); + } + skillMetaController.deploySkillPackage(vendorId, ignoreHash, (deployErr) => { + if (deployErr) { + return callback(deployErr); } - skillMetaController.deploySkillPackage(vendorId, ignoreHash, (deployErr) => { - if (deployErr) { - return callback(deployErr); - } - callback(); - }); + callback(); + }); } /** @@ -55,13 +68,13 @@ function deploySkillMetadata(options, callback) { * @param {*} callback.uniqueCodeList [{ src, build{file, folder}}, buildFlow, regionsList }] */ function buildSkillCode(profile, doDebug, callback) { - const skillCodeController = new SkillCodeController({ profile, doDebug }); - skillCodeController.buildCode((buildErr, uniqueCodeList) => { - if (buildErr) { - return callback(buildErr); - } - callback(null, uniqueCodeList); - }); + const skillCodeController = new SkillCodeController({profile, doDebug}); + skillCodeController.buildCode((buildErr, uniqueCodeList) => { + if (buildErr) { + return callback(buildErr); + } + callback(null, uniqueCodeList); + }); } /** @@ -72,33 +85,44 @@ function buildSkillCode(profile, doDebug, callback) { * @param {*} callback (error) */ function deploySkillInfrastructure(profile, doDebug, ignoreHash, callback) { - const skillInfraController = new SkillInfrastructureController({ profile, doDebug, ignoreHash }); - skillInfraController.deployInfrastructure((deployError) => { - if (deployError) { - return callback(deployError); - } - callback(); - }); + const skillInfraController = new SkillInfrastructureController({profile, doDebug, ignoreHash}); + skillInfraController.deployInfrastructure((deployError) => { + if (deployError) { + return callback(deployError); + } + callback(); + }); } /** - * Funtion used to enable skill + * Function used to enable skill * @param {string} profile The profile name * @param {Boolean} doDebug The flag of debug or not * @param {Function} callback */ function enableSkill(profile, doDebug, callback) { - const skillMetaController = new SkillMetadataController({ profile, doDebug }); - Messenger.getInstance().info('\n==================== Enable Skill ===================='); - try { - skillMetaController.validateDomain(); - } catch (err) { - return callback(err); + const skillMetaController = new SkillMetadataController({profile, doDebug}); + Messenger.getInstance().info("\n==================== Enable Skill ===================="); + try { + skillMetaController.validateDomain(); + } catch (err) { + return callback(err); + } + skillMetaController.enableSkill((error) => { + if (error) { + return callback(error); } - skillMetaController.enableSkill((error) => { - if (error) { - return callback(error); - } - callback(); - }); + callback(); + }); +} + +/** + * Checks if the user's skill structure is ACDL, if so it returns alexa-conversations, + * otherwise it returns interaction-model. + */ +function getDeploymentType(profile) { + if (acUtils.isAcSkill(profile)) { + return CONSTANTS.DEPLOYMENT_TYPE.ALEXA_CONVERSATIONS; + } + return CONSTANTS.DEPLOYMENT_TYPE.INTERACTION_MODEL; } diff --git a/lib/commands/deploy/index.js b/lib/commands/deploy/index.js deleted file mode 100644 index 8c2eb3bc..00000000 --- a/lib/commands/deploy/index.js +++ /dev/null @@ -1,208 +0,0 @@ -const fs = require('fs-extra'); -const path = require('path'); - -const { AbstractCommand } = require('@src/commands/abstract-command'); -const optionModel = require('@src/commands/option-model'); -const CliError = require('@src/exceptions/cli-error'); -const CliFileNotFoundError = require('@src/exceptions/cli-file-not-found-error'); -const CliWarn = require('@src/exceptions/cli-warn'); -const ResourcesConfig = require('@src/model/resources-config'); -const Manifest = require('@src/model/manifest'); -const CONSTANTS = require('@src/utils/constants'); -const profileHelper = require('@src/utils/profile-helper'); -const stringUtils = require('@src/utils/string-utils'); -const Messenger = require('@src/view/messenger'); -const SpinnerView = require('@src/view/spinner-view'); - -const helper = require('./helper'); - -class DeployCommand extends AbstractCommand { - name() { - return 'deploy'; - } - - description() { - return 'deploy the skill project'; - } - - requiredOptions() { - return []; - } - - optionalOptions() { - return ['ignore-hash', 'target', 'profile', 'debug']; - } - - handle(cmd, cb) { - let profile; - try { - profile = profileHelper.runtimeProfile(cmd.profile); - new ResourcesConfig(path.join(process.cwd(), CONSTANTS.FILE_PATH.ASK_RESOURCES_JSON_CONFIG)); - Messenger.getInstance().info(`Deploy configuration loaded from ${CONSTANTS.FILE_PATH.ASK_RESOURCES_JSON_CONFIG}`); - helper.confirmProfile(profile); - this._filterAlexaHostedSkill(profile); - this._initiateManifestModel(profile); - } catch (err) { - if (err instanceof CliWarn) { - Messenger.getInstance().warn(err.message); - } else if (err instanceof CliFileNotFoundError) { - Messenger.getInstance().warn(err.message); - } else if (err instanceof CliError) { - Messenger.getInstance().error(err.message); - } else { - Messenger.getInstance().error(err); - } - return cb(err); - } - - const allowedTargets = Object.values(CONSTANTS.DEPLOY_TARGET); - if (cmd.target && !allowedTargets.includes(cmd.target)) { - const errMessage = `Target ${cmd.target} is not supported. Supported targets: ${allowedTargets}.`; - Messenger.getInstance().error(errMessage); - return cb(new CliError(errMessage)); - } - - const options = { profile, doDebug: cmd.debug, ignoreHash: cmd.ignoreHash, target: cmd.target }; - deployResources(options, (deployErr) => { - // Write updates back to resources file - if (deployErr) { - Messenger.getInstance().error(deployErr); - return cb(deployErr); - } - - ResourcesConfig.getInstance().write(); - Manifest.getInstance().write(); - - // Skipping enable logic if deploying with target flag - // since we may don't have the endpoint - if (cmd.target) { - return cb(); - } - // Post deploy logic - // call smapiClient to enable skill - helper.enableSkill(profile, cmd.debug, (enableError) => { - if (enableError instanceof CliWarn) { - Messenger.getInstance().warn(enableError); - return cb(); - } - if (enableError) { - Messenger.getInstance().error(enableError); - return cb(enableError); - } - cb(); - }); - }); - } - - _filterAlexaHostedSkill(profile) { - const deployerType = ResourcesConfig.getInstance().getSkillInfraType(profile); - if (deployerType === CONSTANTS.DEPLOYER_TYPE.HOSTED.NAME) { - throw new CliWarn('Alexa hosted skills can be deployed by performing a git push.\n' - + 'The master branch gets deployed to skill\'s development stage\n' - + 'The prod branch gets deployed to skill\'s live stage\n' - + 'Please run "git push" at the proper branch to deploy hosted skill to your targeted stage.'); - } - } - - _initiateManifestModel(profile) { - const skillPackageSrc = ResourcesConfig.getInstance().getSkillMetaSrc(profile); - if (!stringUtils.isNonBlankString(skillPackageSrc)) { - throw new CliError('Skill package src is not found in ask-resources.json.'); - } - if (!fs.existsSync(skillPackageSrc)) { - throw new CliError(`The skillMetadata src file ${skillPackageSrc} does not exist.`); - } - const manifestPath = path.join(skillPackageSrc, CONSTANTS.FILE_PATH.SKILL_PACKAGE.MANIFEST); - new Manifest(manifestPath); - } -} - -/** - * The deploy function used to deploy all skill related resources - * This steps includes the deploy of skillMeta, skillCode and skillInfra using the deployDelegate plugin - * @param {String} profile The profile name - * @param {Boolean} doDebug The flag of debug or not - * @param {Boolean} ignoreHash The flag to ignore difference between local and remote version - * @param {Function} callback - */ -function deployResources(options, callback) { - const { profile, doDebug, target, ignoreHash } = options; - _deploySkillMetadata(options, (err) => { - if (err) { - return callback(err); - } - - if (target && target !== CONSTANTS.DEPLOY_TARGET.SKILL_INFRASTRUCTURE) { - return callback(); - } - - if (!ResourcesConfig.getInstance().getSkillId(profile)) { - const errorMessage = `Unable to deploy target ${target} when the skillId has not been created yet. ` - + 'Please deploy your skillMetadata first by running “ask deploy” command.'; - return callback(new CliError(errorMessage)); - } - - // Skill Code - const regionsList = ResourcesConfig.getInstance().getCodeRegions(profile); - if (!regionsList || regionsList.length === 0) { - return callback(); - } - Messenger.getInstance().info('\n==================== Build Skill Code ===================='); - helper.buildSkillCode(profile, doDebug, (buildErr, uniqueCodeList) => { - if (buildErr) { - return callback(buildErr); - } - Messenger.getInstance().info('Skill code built successfully.'); - uniqueCodeList.forEach((codeProperty) => { - const buildFilePath = codeProperty.build.file; - Messenger.getInstance().info(`Code for region ${codeProperty.regionsList.join('+')} built to ${buildFilePath} successfully \ -with build flow ${codeProperty.buildFlow}.`); - }); - - // Skill Infrastructure - const infraType = ResourcesConfig.getInstance().getSkillInfraType(profile); - if (!stringUtils.isNonBlankString(infraType)) { - return callback(); - } - Messenger.getInstance().info('\n==================== Deploy Skill Infrastructure ===================='); - helper.deploySkillInfrastructure(profile, doDebug, ignoreHash, (infraErr) => { - if (infraErr) { - return callback(infraErr); - } - Messenger.getInstance().info(`Skill infrastructures deployed successfully through ${infraType}.`); - callback(); - }); - }); - }); -} - -function _deploySkillMetadata(options, callback) { - const { profile, target } = options; - if (target && target !== CONSTANTS.DEPLOY_TARGET.SKILL_METADATA) { - return callback(); - } - // Skill Metadata - Messenger.getInstance().info('==================== Deploy Skill Metadata ===================='); - const skillMetaSpinner = new SpinnerView(); - skillMetaSpinner.start('Uploading the entire skill package (it may take few minutes to build the skill metadata)...'); - helper.deploySkillMetadata(options, (metaErr) => { - skillMetaSpinner.terminate(); - if (metaErr && metaErr !== 'The hash of current skill package folder does not change compared to the last deploy hash result, ' - + 'CLI will skip the deploy of skill package.') { - return callback(metaErr); - } - if (metaErr) { - // this case is the warning message of the same hash skip, deploy will continue - Messenger.getInstance().warn(metaErr); - } else { - ResourcesConfig.getInstance().write(); - Messenger.getInstance().info('Skill package deployed successfully.'); - } - Messenger.getInstance().info(`Skill ID: ${ResourcesConfig.getInstance().getSkillId(profile)}`); - - return callback(); - }); -} - -module.exports = DeployCommand; -module.exports.createCommand = new DeployCommand(optionModel).createCommand(); diff --git a/lib/commands/deploy/index.ts b/lib/commands/deploy/index.ts new file mode 100644 index 00000000..81b97861 --- /dev/null +++ b/lib/commands/deploy/index.ts @@ -0,0 +1,251 @@ +import fs from "fs-extra"; +import path from "path"; +import {AbstractCommand} from "../abstract-command"; +import optionModel from "../option-model.json"; +import CliError from "../../exceptions/cli-error"; +import CliFileNotFoundError from "../../exceptions/cli-file-not-found-error"; +import CliWarn from "../../exceptions/cli-warn"; +import ResourcesConfig from "../../model/resources-config"; +import Manifest from "../../model/manifest"; +import CONSTANTS from "../../utils/constants"; +import profileHelper from "../../utils/profile-helper"; +import stringUtils from "../../utils/string-utils"; +import Messenger from "../../view/messenger"; +import ui from "./ui"; +import helper from "./helper"; +import {OptionModel} from "../option-validator"; +import {isAcSkill} from "../../utils/ac-util"; + +export default class DeployCommand extends AbstractCommand { + name() { + return "deploy"; + } + + description() { + return "deploy the skill project"; + } + + requiredOptions() { + return []; + } + + optionalOptions() { + return ["ignore-hash", "target", "profile", "debug"]; + } + + async handle(cmd: Record): Promise { + let profile: string; + try { + profile = profileHelper.runtimeProfile(cmd.profile); + new ResourcesConfig(path.join(process.cwd(), CONSTANTS.FILE_PATH.ASK_RESOURCES_JSON_CONFIG)); + Messenger.getInstance().info(`Deploy configuration loaded from ${CONSTANTS.FILE_PATH.ASK_RESOURCES_JSON_CONFIG}`); + helper.confirmProfile(profile); + this._filterAlexaHostedSkill(profile); + this._initiateManifestModel(profile); + } catch (err) { + if (err instanceof CliWarn) { + Messenger.getInstance().warn(err.message); + } else if (err instanceof CliFileNotFoundError) { + Messenger.getInstance().warn(err.message); + } else if (err instanceof CliError) { + Messenger.getInstance().error(err.message); + } else { + Messenger.getInstance().error(err); + } + throw err; + } + + const allowedTargets = Object.values(CONSTANTS.DEPLOY_TARGET); + if (cmd.target && !allowedTargets.includes(cmd.target)) { + const errMessage = `Target ${cmd.target} is not supported. Supported targets: ${allowedTargets}.`; + Messenger.getInstance().error(errMessage); + throw new CliError(errMessage); + } + const options = {profile, doDebug: cmd.debug, ignoreHash: cmd.ignoreHash, target: cmd.target}; + + return new Promise((resolve, reject) => { + ui.confirmDeploymentIfNeeded(profile, (err: any, confirmResult: boolean) => { + if (err) { + Messenger.getInstance().error(err); + return reject(err); + } + + if (!confirmResult) { + Messenger.getInstance().info("Deployment cancelled."); + return resolve(); + } + deployResources(options) + .then(() => { + const deploymentType = helper.getDeploymentType(profile); + + // Save the deployment type to ask states + ResourcesConfig.getInstance().setSkillMetaLastDeployType(profile, deploymentType); + + // Write updates back to resources file + ResourcesConfig.getInstance().write(); + Manifest.getInstance().write(); + + // Skipping enable logic if deploying with target flag + // since we may don't have the endpoint + if (cmd.target) { + return resolve(); + } + // Post deploy logic + // call smapiClient to enable skill + helper.enableSkill(profile, cmd.debug, (enableError: any) => { + if (enableError instanceof CliWarn) { + Messenger.getInstance().warn(enableError); + return resolve(); + } + if (enableError) { + Messenger.getInstance().error(enableError); + return reject(enableError); + } + return resolve(); + }); + }) + .catch((err) => { + Messenger.getInstance().error(err); + return reject(err); + }); + }); + }); + } + + _filterAlexaHostedSkill(profile: string) { + const deployerType = ResourcesConfig.getInstance().getSkillInfraType(profile); + if (deployerType === CONSTANTS.DEPLOYER_TYPE.HOSTED.NAME) { + throw new CliWarn( + "Alexa hosted skills can be deployed by performing a git push.\n" + + "The master branch gets deployed to skill's development stage\n" + + "The prod branch gets deployed to skill's live stage\n" + + 'Please run "git push" at the proper branch to deploy hosted skill to your targeted stage.', + ); + } + } + + _initiateManifestModel(profile: string) { + const skillPackageSrc = ResourcesConfig.getInstance().getSkillMetaSrc(profile); + if (!stringUtils.isNonBlankString(skillPackageSrc)) { + throw new CliError("Skill package src is not found in ask-resources.json."); + } + if (!fs.existsSync(skillPackageSrc)) { + throw new CliError(`The skillMetadata src file ${skillPackageSrc} does not exist.`); + } + + // check whether it is a AC skill + if (isAcSkill(profile) === true) { + // if it's AC skill, check if the build/skill-package exists + const buildPackageSrc = path.join("build", skillPackageSrc); + if (!fs.existsSync(buildPackageSrc)) { + throw new CliError( + `The directory specified, ${buildPackageSrc}, does not exist. Please compile your AC skill before deploying it.`, + ); + } + } + const manifestPath = path.join(skillPackageSrc, CONSTANTS.FILE_PATH.SKILL_PACKAGE.MANIFEST); + new Manifest(manifestPath); + } +} + +/** + * The deploy function used to deploy all skill related resources + * This steps includes the deploy of skillMeta, skillCode and skillInfra using the deployDelegate plugin + * @param {String} profile The profile name + * @param {Boolean} doDebug The flag of debug or not + * @param {Boolean} ignoreHash The flag to ignore difference between local and remote version + * @param {Function} callback + */ +async function deployResources(options: Record): Promise { + const {profile, doDebug, target, ignoreHash} = options; + await _deploySkillMetadata(options); + + if (target && target !== CONSTANTS.DEPLOY_TARGET.SKILL_INFRASTRUCTURE) { + return; + } + + if (!ResourcesConfig.getInstance().getSkillId(profile)) { + const errorMessage = + `Unable to deploy target ${target} when the skillId has not been created yet. ` + + "Please deploy your skillMetadata first by running “ask deploy” command."; + throw new CliError(errorMessage); + } + + // Skill Code + const regionsList = ResourcesConfig.getInstance().getCodeRegions(profile); + if (!regionsList || regionsList.length === 0) { + return; + } + Messenger.getInstance().info("\n==================== Build Skill Code ===================="); + return new Promise((resolve, reject) => { + helper.buildSkillCode(profile, doDebug, (buildErr: any, uniqueCodeList: any[]) => { + if (buildErr) { + return reject(buildErr); + } + Messenger.getInstance().info("Skill code built successfully."); + uniqueCodeList.forEach((codeProperty) => { + const buildFilePath = codeProperty.build.file; + Messenger.getInstance().info(`Code for region ${codeProperty.regionsList.join("+")} built to ${buildFilePath} successfully \ +with build flow ${codeProperty.buildFlow}.`); + }); + + // Skill Infrastructure + const infraType = ResourcesConfig.getInstance().getSkillInfraType(profile); + if (!stringUtils.isNonBlankString(infraType)) { + return resolve(); + } + Messenger.getInstance().info("\n==================== Deploy Skill Infrastructure ===================="); + helper.deploySkillInfrastructure(profile, doDebug, ignoreHash, (infraErr: any) => { + if (infraErr) { + return reject(infraErr); + } + Messenger.getInstance().info(`\nSkill infrastructures deployed successfully through ${infraType}.`); + resolve(); + }); + }); + }); +} + +async function _deploySkillMetadata(options: Record): Promise { + const {profile, target} = options; + if (target && target !== CONSTANTS.DEPLOY_TARGET.SKILL_METADATA) { + return; + } + + const isAcdlSkill = isAcSkill(profile); + const acMsg = "Uploading the entire skill package and building the models. For Alexa Conversations it can take 20-60 minutes..."; + const imMsg = "Uploading the entire skill package and building the models. Normally it takes a few minutes..."; + const startMsg = isAcdlSkill ? acMsg : imMsg; + + if (isAcdlSkill) { + Messenger.getInstance().warn(CONSTANTS.ACDL_BETA_MESSAGE + "\n"); + } + + // Skill Metadata + Messenger.getInstance().info("==================== Deploy Skill Metadata ===================="); + Messenger.getInstance().info(startMsg); + return new Promise((resolve, reject) => { + helper.deploySkillMetadata(options, (metaErr: any) => { + if ( + metaErr && + metaErr !== + "The hash of current skill package folder does not change compared to the last deploy hash result, " + + "CLI will skip the deploy of skill package." + ) { + return reject(metaErr); + } + if (metaErr) { + // this case is the warning message of the same hash skip, deploy will continue + Messenger.getInstance().warn(metaErr); + } else { + ResourcesConfig.getInstance().write(); + Messenger.getInstance().info("Skill package deployed and all models built successfully."); + } + Messenger.getInstance().info(`Skill ID: ${ResourcesConfig.getInstance().getSkillId(profile)}`); + + return resolve(); + }); + }); +} + +export const createCommand = new DeployCommand(optionModel as OptionModel).createCommand(); diff --git a/lib/commands/deploy/ui.js b/lib/commands/deploy/ui.js index e69de29b..ba26169b 100644 --- a/lib/commands/deploy/ui.js +++ b/lib/commands/deploy/ui.js @@ -0,0 +1,44 @@ +const inquirer = require("inquirer"); +const acUtils = require("../../utils/ac-util"); +const ResourcesConfig = require("../../model/resources-config"); +const CONSTANTS = require("../../utils/constants"); + +module.exports = { + confirmDeploymentIfNeeded, +}; + +/** + * Confirms the deployment before deploying the skill. + * + * Confirmation is rendered when the skill project is Alexa Conversations, and the + * last deployment type in ask-states is undefined or not Alexa Conversations. + */ +function confirmDeploymentIfNeeded(profile, callback) { + const lastDeployType = ResourcesConfig.getInstance().getSkillMetaLastDeployType(profile); + const isAcSkill = acUtils.isAcSkill(profile); + + // If last deployment was Alexa Conversations, then this prompt has already been answered + const isPromptNeeded = isAcSkill && lastDeployType !== CONSTANTS.DEPLOYMENT_TYPE.ALEXA_CONVERSATIONS; + + if (isPromptNeeded) { + inquirer + .prompt([ + { + message: + "Skills with ACDL are not yet compatible with the https://developer.amazon.com, " + + "hence this skill will be disabled on the Developer Console. Would you like to proceed?", + type: "confirm", + name: "confirmation", + default: false, + }, + ]) + .then((answer) => { + callback(null, answer.confirmation); + }) + .catch((error) => { + callback(error); + }); + } else { + callback(null, true); + } +} diff --git a/lib/commands/dialog/helper.js b/lib/commands/dialog/helper.js deleted file mode 100644 index 12ff7ea0..00000000 --- a/lib/commands/dialog/helper.js +++ /dev/null @@ -1,62 +0,0 @@ -const R = require('ramda'); - -module.exports = { - validateDialogArgs -}; - -/** - * Validates if a skill is enabled for simulation. Calls Skill Management apis (SMAPI) to achieve this. - * @param {*} dialogMode encapsulates configuration required validate skill information - * @param {*} callback - */ -function validateDialogArgs(dialogMode, callback) { - const { smapiClient, skillId, stage, locale } = dialogMode; - - smapiClient.skill.manifest.getManifest(skillId, stage, (err, response) => { - if (err) { - return callback(err); - } - if (response.statusCode !== 200) { - return callback(smapiErrorMsg('get-manifest', response)); - } - const apis = R.view(R.lensPath(['body', 'manifest', 'apis']), response); - if (!apis) { - return callback('Ensure "manifest.apis" object exists in the skill manifest.'); - } - - const apisKeys = Object.keys(apis); - if (!apisKeys || apisKeys.length !== 1) { - return callback('Dialog command only supports custom skill type.'); - } - - if (apisKeys[0] !== 'custom') { - return callback(`Dialog command only supports custom skill type, but current skill is a "${apisKeys[0]}" type.`); - } - - const locales = R.view(R.lensPath(['body', 'manifest', 'publishingInformation', 'locales']), response); - if (!locales) { - return callback('Ensure the "manifest.publishingInformation.locales" exists in the skill manifest before simulating your skill.'); - } - - if (!R.view(R.lensProp(locale), locales)) { - return callback( - `Locale ${locale} was not found for your skill. ` - + 'Ensure the locale you want to simulate exists in your publishingInformation.' - ); - } - - smapiClient.skill.getSkillEnablement(skillId, stage, (enableErr, enableResponse) => { - if (enableErr) { - return callback(enableErr); - } - if (enableResponse.statusCode > 300) { - return callback(smapiErrorMsg('get-skill-enablement', enableResponse)); - } - callback(); - }); - }); -} - -function smapiErrorMsg(operation, res) { - return `SMAPI ${operation} request error: ${res.statusCode} - ${res.body.message}`; -} diff --git a/lib/commands/dialog/helper.ts b/lib/commands/dialog/helper.ts new file mode 100644 index 00000000..e4afe8f2 --- /dev/null +++ b/lib/commands/dialog/helper.ts @@ -0,0 +1,49 @@ +import {ISmapiClient, isSmapiError, SmapiResponseError} from "../../clients/smapi-client"; + +/** + * Validates if a skill is enabled for simulation. Calls Skill Management apis (SMAPI) to achieve this. + * @param {*} dialogMode encapsulates configuration required validate skill information + * @param {*} callback + */ +export async function validateDialogArgs(dialogMode: {smapiClient: ISmapiClient; skillId: string; stage: string; locale: string}) { + const {smapiClient, skillId, stage, locale} = dialogMode; + + const response = await smapiClient.skill.manifest.getManifest(skillId, stage); + + if (isSmapiError(response)) { + throw smapiErrorMsg("get-manifest", response); + } + + const apis = response.body.manifest?.apis; + if (!apis) { + throw 'Ensure "manifest.apis" object exists in the skill manifest.'; + } + + const apisKeys = Object.keys(apis); + if (!apisKeys || apisKeys.length !== 1) { + throw "Dialog command only supports custom skill type."; + } + + if (apisKeys[0] !== "custom") { + throw `Dialog command only supports custom skill type, but current skill is a "${apisKeys[0]}" type.`; + } + + const locales = response.body.manifest?.publishingInformation?.locales; + if (!locales) { + throw 'Ensure the "manifest.publishingInformation.locales" exists in the skill manifest before simulating your skill.'; + } + + if (!locales[locale]) { + throw `Locale ${locale} was not found for your skill. Ensure the locale you want to simulate exists in your publishingInformation.`; + } + + const enableResponse = await smapiClient.skill.getSkillEnablement(skillId, stage); + + if (isSmapiError(enableResponse)) { + throw smapiErrorMsg("get-skill-enablement", enableResponse); + } +} + +function smapiErrorMsg(operation: string, res: SmapiResponseError) { + return `SMAPI ${operation} request error: ${res.statusCode} - ${res.body.message}`; +} diff --git a/lib/commands/dialog/index.js b/lib/commands/dialog/index.js deleted file mode 100644 index 245ca48b..00000000 --- a/lib/commands/dialog/index.js +++ /dev/null @@ -1,154 +0,0 @@ -const path = require('path'); - -const SmapiClient = require('@src/clients/smapi-client'); -const { AbstractCommand } = require('@src/commands/abstract-command'); -const optionModel = require('@src/commands/option-model'); -const CliError = require('@src/exceptions/cli-error'); -const DialogReplayFile = require('@src/model/dialog-replay-file'); -const ResourcesConfig = require('@src/model/resources-config'); -const jsonView = require('@src/view/json-view'); -const CONSTANTS = require('@src/utils/constants'); -const profileHelper = require('@src/utils/profile-helper'); -const Messenger = require('@src/view/messenger'); -const SpinnerView = require('@src/view/spinner-view'); -const stringUtils = require('@src/utils/string-utils'); - -const InteractiveMode = require('./interactive-mode'); -const ReplayMode = require('./replay-mode'); - -const helper = require('./helper'); - -class DialogCommand extends AbstractCommand { - name() { - return 'dialog'; - } - - description() { - return 'simulate your skill via an interactive dialog with Alexa'; - } - - requiredOptions() { - return []; - } - - optionalOptions() { - return ['skill-id', 'locale', 'stage', 'replay', 'save-skill-io', 'simulation-type', 'profile', 'debug']; - } - - handle(cmd, cb) { - let dialogMode; - this._getDialogConfig(cmd, (err, config) => { - if (err) { - Messenger.getInstance().error(err); - return cb(err); - } - dialogMode = this._dialogModeFactory(config); - const spinner = new SpinnerView(); - spinner.start('Checking if skill is ready to simulate...'); - helper.validateDialogArgs(dialogMode, (dialogArgsValidationError) => { - if (dialogArgsValidationError) { - spinner.terminate(SpinnerView.TERMINATE_STYLE.FAIL, 'Failed to validate command options'); - Messenger.getInstance().error(dialogArgsValidationError); - return cb(dialogArgsValidationError); - } - spinner.terminate(); - dialogMode.start((controllerError) => { - if (controllerError) { - Messenger.getInstance().error(controllerError); - return cb(controllerError); - } - cb(); - }); - }); - }); - } - - /** - * Function processes dialog arguments and returns a consolidated object. - * @param {Object} cmd encapsulates arguments provided to the dialog command. - * @return { skillId, locale, stage, profile, debug, replayFile, smapiClient, userInputs } - */ - _getDialogConfig(cmd, callback) { - const debug = Boolean(cmd.debug); - let { skillId, locale, stage, profile } = cmd; - const { saveSkillIo } = cmd; - profile = profileHelper.runtimeProfile(profile); - stage = stage || CONSTANTS.SKILL.STAGE.DEVELOPMENT; - let firstLocaleFromManifest; - let userInputs; - const smapiClient = new SmapiClient({ profile, doDebug: debug }); - if (cmd.replay) { - let dialogReplayConfig; - try { - dialogReplayConfig = new DialogReplayFile(cmd.replay); - } catch (err) { - return callback(err); - } - skillId = dialogReplayConfig.getSkillId(); - if (!stringUtils.isNonBlankString(skillId)) { - return process.nextTick(callback(new CliError('Replay file must contain skillId'))); - } - locale = dialogReplayConfig.getLocale(); - if (!stringUtils.isNonBlankString(locale)) { - return process.nextTick(callback(new CliError('Replay file must contain locale'))); - } - try { - userInputs = this._validateUserInputs(dialogReplayConfig.getUserInput()); - } catch (err) { - return callback(err); - } - } else { - if (!stringUtils.isNonBlankString(skillId)) { - try { - new ResourcesConfig(path.join(process.cwd(), CONSTANTS.FILE_PATH.ASK_RESOURCES_JSON_CONFIG)); - skillId = ResourcesConfig.getInstance().getSkillId(profile); - } catch (err) { - return process.nextTick(callback(new CliError('Failed to read project resource file. ' - + 'Please run the command within a ask-cli project.'))); - } - if (!stringUtils.isNonBlankString(skillId)) { - return process.nextTick(callback(new CliError('Failed to obtain skill-id from project ' - + `resource file ${CONSTANTS.FILE_PATH.ASK_RESOURCES_JSON_CONFIG}`))); - } - } - } - smapiClient.skill.manifest.getManifest(skillId, stage, (err, res) => { - if (err) { - return callback(err); - } - if (res.statusCode >= 300) { - const error = jsonView.toString(res.body); - return callback(error); - } - [firstLocaleFromManifest] = Object.keys(res.body.manifest.publishingInformation.locales); - if (!locale && !process.env.ASK_DEFAULT_DEVICE_LOCALE && firstLocaleFromManifest) { - Messenger.getInstance().info(`Defaulting locale to the first value from the skill manifest: ${firstLocaleFromManifest}`); - } - locale = locale || process.env.ASK_DEFAULT_DEVICE_LOCALE || firstLocaleFromManifest; - const simulationType = stringUtils.isNonBlankString(cmd.simulationType) ? cmd.simulationType : undefined; - callback(null, { skillId, locale, stage, profile, debug, replay: cmd.replay, saveSkillIo, smapiClient, userInputs, simulationType }); - }); - } - - _dialogModeFactory(config) { - if (config.replay) { - return new ReplayMode(config); - } - return new InteractiveMode(config); - } - - _validateUserInputs(userInputs) { - const validatedInputs = []; - userInputs.forEach((input) => { - const trimmedInput = input.trim(); - if (!stringUtils.isNonBlankString(trimmedInput)) { - throw new CliError("Replay file's userInput cannot contain empty string."); - } - validatedInputs.push(trimmedInput); - }); - return validatedInputs; - } -} - -module.exports = DialogCommand; -module.exports.createCommand = new DialogCommand(optionModel).createCommand(); diff --git a/lib/commands/dialog/index.ts b/lib/commands/dialog/index.ts new file mode 100644 index 00000000..f0ac9d6e --- /dev/null +++ b/lib/commands/dialog/index.ts @@ -0,0 +1,163 @@ +import * as path from "path"; + +import {isSmapiError, SmapiClientLateBound} from "../../clients/smapi-client"; +import {AbstractCommand} from "../../commands/abstract-command"; +import * as optionModel from "../../commands/option-model.json"; +import CliError from "../../exceptions/cli-error"; +import DialogReplayFile from "../../model/dialog-replay-file"; +import ResourcesConfig from "../../model/resources-config"; +import * as jsonView from "../../view/json-view"; +import * as CONSTANTS from "../../utils/constants"; +import * as profileHelper from "../../utils/profile-helper"; +import Messenger from "../../view/messenger"; +import SpinnerView from "../../view/spinner-view"; +import * as stringUtils from "../../utils/string-utils"; + +import {InteractiveMode} from "./interactive-mode"; +import {ReplayMode} from "./replay-mode"; +import {validateDialogArgs} from "./helper"; +import {OptionModel} from "../option-validator"; + +export class DialogCommand extends AbstractCommand { + private messenger: Messenger; + constructor(private smapiClient: SmapiClientLateBound, optionModel: OptionModel) { + super(optionModel); + this.messenger = Messenger.getInstance(); + } + + name() { + return "dialog"; + } + + description() { + return "simulate your skill via an interactive dialog with Alexa"; + } + + requiredOptions() { + return []; + } + + optionalOptions() { + return ["skill-id", "locale", "stage", "replay", "save-skill-io", "profile", "debug"]; + } + + async handle(cmd: Record): Promise { + try { + const dialogMode = await this._dialogModeFactory(cmd); + const spinner = new SpinnerView(); + spinner.start("Checking if skill is ready to simulate..."); + + try { + await validateDialogArgs(dialogMode); + } catch (err) { + spinner.terminate(SpinnerView.TERMINATE_STYLE.FAIL, "Failed to validate command options"); + throw err; + } + + spinner.terminate(); + await dialogMode.start(); + } catch (err) { + this.messenger.error(err); + throw err; + } + } + + /** + * Function processes dialog arguments and returns a consolidated object. + * @param {Object} cmd encapsulates arguments provided to the dialog command. + * @return { skillId, locale, stage, profile, debug, replayFile, smapiClient, userInputs } + */ + async _getDialogConfig(cmd: Record) { + const {skillId: cmdSkillId, locale: cmdLocale, stage: cmdStage, profile: cmdProfile} = cmd; + const {saveSkillIo, debug} = cmd; + const profile = profileHelper.runtimeProfile(cmdProfile); + const stage = cmdStage || CONSTANTS.SKILL.STAGE.DEVELOPMENT; + const smapiClient = this.smapiClient.withConfiguration({ + profile, + doDebug: !!cmd.debug, + }); + + const {skillId = cmdSkillId, locale = cmdLocale, userInputs} = this._resolvedArguments(cmd, profile); + + const manifestResult = await smapiClient.skill.manifest.getManifest(skillId, stage); + if (isSmapiError(manifestResult)) { + throw jsonView.toString(manifestResult.body); + } + const [firstLocaleFromManifest] = Object.keys(manifestResult.body.manifest?.publishingInformation?.locales || {}); + if (!locale && !process.env.ASK_DEFAULT_DEVICE_LOCALE && firstLocaleFromManifest) { + this.messenger.info(`Defaulting locale to the first value from the skill manifest: ${firstLocaleFromManifest}`); + } + return { + skillId, + locale: locale || process.env.ASK_DEFAULT_DEVICE_LOCALE || firstLocaleFromManifest, + stage, + profile, + debug, + replay: cmd.replay, + saveSkillIo, + smapiClient, + userInputs, + }; + } + + _resolvedArguments(cmd: Record, profile: string): {skillId?: string; locale?: string; userInputs?: string[]} { + const {skillId: cmdSkillId} = cmd; + if (cmd.replay) { + const dialogReplayConfig = new DialogReplayFile(cmd.replay); + const skillId = dialogReplayConfig.getSkillId(); + if (!stringUtils.isNonBlankString(skillId)) { + throw new CliError("Replay file must contain skillId"); + } + const locale = dialogReplayConfig.getLocale(); + if (!stringUtils.isNonBlankString(locale)) { + throw new CliError("Replay file must contain locale"); + } + + return {userInputs: this._validateUserInputs(dialogReplayConfig.getUserInput()), skillId, locale}; + } else if (!stringUtils.isNonBlankString(cmdSkillId)) { + const skillId = this._getSkillIdFromProfile(profile); + + return {skillId}; + } + + return {}; + } + + _getSkillIdFromProfile(profile: string) { + let skillId; + try { + new ResourcesConfig(path.join(process.cwd(), CONSTANTS.FILE_PATH.ASK_RESOURCES_JSON_CONFIG)); + skillId = ResourcesConfig.getInstance().getSkillId(profile); + } catch (err) { + throw new CliError("Failed to read project resource file. " + "Please run the command within a ask-cli project."); + } + + if (!stringUtils.isNonBlankString(skillId)) { + const askStatesFilePath = path.join(process.cwd(), CONSTANTS.FILE_PATH.HIDDEN_ASK_FOLDER, CONSTANTS.FILE_PATH.ASK_STATES_JSON_CONFIG); + throw new CliError(`Failed to obtain skill-id from project file ${askStatesFilePath}`); + } + + return skillId; + } + + async _dialogModeFactory(cmd: any): Promise { + const config = await this._getDialogConfig(cmd); + if (config.replay) { + return new ReplayMode(config); + } else { + return new InteractiveMode(config); + } + } + + _validateUserInputs(userInputs: string[]) { + return userInputs.map((input) => { + const trimmedInput = input.trim(); + if (!stringUtils.isNonBlankString(trimmedInput)) { + throw new CliError("Replay file's userInput cannot contain empty string."); + } + return trimmedInput; + }); + } +} + +export const createCommand = new DialogCommand(new SmapiClientLateBound(), optionModel as OptionModel).createCommand(); diff --git a/lib/commands/dialog/interactive-mode.js b/lib/commands/dialog/interactive-mode.js deleted file mode 100644 index cf09f284..00000000 --- a/lib/commands/dialog/interactive-mode.js +++ /dev/null @@ -1,37 +0,0 @@ -const chalk = require('chalk'); - -const DialogReplView = require('@src/view/dialog-repl-view'); -const DialogController = require('@src/controllers/dialog-controller'); - -const SPECIAL_COMMANDS_HEADER = 'Use ".record " or ".record --append-quit" to save list of utterances to a file.\n' -+ 'You can exit the interactive mode by entering ".quit" or "ctrl + c".'; -module.exports = class InteractiveMode extends DialogController { - constructor(config) { - super(config); - this.header = config.header || 'Welcome to ASK Dialog\n' - + 'In interactive mode, type your utterance text onto the console and hit enter\n' - + 'Alexa will then evaluate your input and give a response!\n'; - } - - start(callback) { - let interactiveReplView; - try { - interactiveReplView = new DialogReplView({ - prompt: chalk.yellow.bold('User > '), - header: this.header + SPECIAL_COMMANDS_HEADER, - footer: 'Goodbye!', - evalFunc: (input, replCallback) => { - this.evaluateUtterance(input, interactiveReplView, replCallback); - }, - }); - } catch (error) { - return callback(error); - } - - this.setupSpecialCommands(interactiveReplView, (error) => { - if (error) { - return callback(error); - } - }); - } -}; diff --git a/lib/commands/dialog/interactive-mode.ts b/lib/commands/dialog/interactive-mode.ts new file mode 100644 index 00000000..58106067 --- /dev/null +++ b/lib/commands/dialog/interactive-mode.ts @@ -0,0 +1,43 @@ +import chalk from "chalk"; + +import {DialogReplView} from "../../view/dialog-repl-view"; +import {DialogController, DialogControllerProps} from "../../controllers/dialog-controller"; + +const SPECIAL_COMMANDS_HEADER = + 'Use ".record " or ".record --append-quit" to save list of utterances to a file.\n' + + 'You can exit the interactive mode by entering ".quit" or "ctrl + c".'; + +export interface InteractiveModeProps extends DialogControllerProps { + header?: string; +} + +export class InteractiveMode extends DialogController { + header: string; + + constructor(config: InteractiveModeProps) { + super(config); + this.header = + config.header || + "Welcome to ASK Dialog\n" + + "In interactive mode, type your utterance text onto the console and hit enter\n" + + "Alexa will then evaluate your input and give a response!\n"; + } + + async start(): Promise { + try { + const interactiveReplView = new DialogReplView({ + prompt: chalk.yellow.bold("User > "), + header: this.header + SPECIAL_COMMANDS_HEADER, + footer: "Goodbye!", + evalFunc: (input, replCallback) => { + this.evaluateUtterance(input, interactiveReplView) + .then((x) => replCallback(null, x)) + .catch((x) => replCallback(x, null)); + }, + }); + await this.setupSpecialCommands(interactiveReplView); + } catch (error) { + throw error; + } + } +} diff --git a/lib/commands/dialog/replay-mode.js b/lib/commands/dialog/replay-mode.js deleted file mode 100644 index 44e0044b..00000000 --- a/lib/commands/dialog/replay-mode.js +++ /dev/null @@ -1,63 +0,0 @@ -const chalk = require('chalk'); -const { Readable } = require('stream'); - -const DialogController = require('@src/controllers/dialog-controller'); -const DialogReplView = require('@src/view/dialog-repl-view'); -const InteractiveMode = require('./interactive-mode'); - -module.exports = class ReplayMode extends DialogController { - constructor(config) { - super(config); - this.config = config; - this.userInputs = config.userInputs; - this.replay = config.replay; - } - - start(callback) { - const replayInputStream = new Readable({ read() {} }); - let replayReplView; - try { - replayReplView = new DialogReplView({ - prompt: chalk.yellow.bold('User > '), - header: this._getHeader(), - footer: 'Goodbye!', - inputStream: replayInputStream, - evalFunc: (replayInput, replayCallback) => { - this._evaluateInput(replayInput, replayReplView, replayInputStream, replayCallback, callback); - } - }); - } catch (error) { - return callback(error); - } - - this.setupSpecialCommands(replayReplView, (error) => { - if (error) { - return callback(error); - } - }); - replayInputStream.push(`${this.userInputs.shift()}\n`, 'utf8'); - } - - _getHeader() { - return 'Welcome to ASK Dialog\n' - + `Replaying a multi turn conversation with Alexa from ${this.replay}\n` - + 'Alexa will then evaluate your input and give a response!'; - } - - _evaluateInput(replayInput, replayReplView, replayInputStream, replayCallback, callback) { - this.evaluateUtterance(replayInput, replayReplView, () => { - if (this.userInputs.length > 0) { - replayCallback(); - replayInputStream.push(`${this.userInputs.shift()}\n`, 'utf8'); - } else { - replayReplView.clearSpecialCommands(); - replayReplView.close(); - this.config.header = 'Switching to interactive dialog.\n' - + 'To automatically quit after replay, append \'.quit\' to the userInput of your replay file.\n'; - this.config.newSession = false; - const interactiveReplView = new InteractiveMode(this.config); - interactiveReplView.start(callback); - } - }); - } -}; diff --git a/lib/commands/dialog/replay-mode.ts b/lib/commands/dialog/replay-mode.ts new file mode 100644 index 00000000..ba7bdcf7 --- /dev/null +++ b/lib/commands/dialog/replay-mode.ts @@ -0,0 +1,72 @@ +import chalk from "chalk"; +import {Readable} from "stream"; + +import {DialogController, DialogControllerProps} from "../../controllers/dialog-controller"; +import {DialogReplView} from "../../view/dialog-repl-view"; +import {InteractiveMode} from "./interactive-mode"; + +export interface ReplayModeProps extends DialogControllerProps { + userInputs: any; + replay: any; + header?: any; +} + +export class ReplayMode extends DialogController { + config; + userInputs; + replay; + + constructor(config: ReplayModeProps) { + super(config); + this.config = config; + this.userInputs = config.userInputs; + this.replay = config.replay; + } + + async start(): Promise { + const replayInputStream = new Readable({read() {}}); + const replayReplView = new DialogReplView({ + prompt: chalk.yellow.bold("User > "), + header: this._getHeader(), + footer: "Goodbye!", + inputStream: replayInputStream, + evalFunc: (replayInput, replayCallback) => { + this._evaluateInput(replayInput, replayReplView, replayInputStream, replayCallback); + }, + }); + replayInputStream.push(`${this.userInputs.shift()}\n`, "utf8"); + await this.setupSpecialCommands(replayReplView); + } + + _getHeader() { + return ( + "Welcome to ASK Dialog\n" + + `Replaying a multi turn conversation with Alexa from ${this.replay}\n` + + "Alexa will then evaluate your input and give a response!" + ); + } + + async _evaluateInput( + replayInput: any, + replayReplView: any, + replayInputStream: any, + replayCallback: (err: Error | null, result: any) => void, + ): Promise { + try { + await this.evaluateUtterance(replayInput, replayReplView); + } catch (err) {} + + if (this.userInputs.length > 0) { + replayCallback(null, undefined); + replayInputStream.push(`${this.userInputs.shift()}\n`, "utf8"); + } else { + replayReplView.clearSpecialCommands(); + replayReplView.close(); + this.config.header = + "Switching to interactive dialog.\n" + "To automatically quit after replay, append '.quit' to the userInput of your replay file.\n"; + this.config.newSession = false; + const interactiveReplView = new InteractiveMode(this.config); + await interactiveReplView.start(); + } + } +} diff --git a/lib/commands/init/helper.js b/lib/commands/init/helper.js index 56505ef7..0dbb6ae3 100644 --- a/lib/commands/init/helper.js +++ b/lib/commands/init/helper.js @@ -1,26 +1,26 @@ -const fs = require('fs-extra'); -const path = require('path'); -const R = require('ramda'); +const fs = require("fs-extra"); +const path = require("path"); +const R = require("ramda"); -const SkillInfrastructureController = require('@src/controllers/skill-infrastructure-controller'); -const CliWarn = require('@src/exceptions/cli-warn'); -const AskResources = require('@src/model/resources-config/ask-resources'); -const AskStates = require('@src/model/resources-config/ask-states'); -const ResourcesConfig = require('@src/model/resources-config'); -const stringUtils = require('@src/utils/string-utils'); -const CONSTANTS = require('@src/utils/constants'); -const Messenger = require('@src/view/messenger'); +const SkillInfrastructureController = require("../../controllers/skill-infrastructure-controller"); +const CliWarn = require("../../exceptions/cli-warn"); +const AskResources = require("../../model/resources-config/ask-resources"); +const AskStates = require("../../model/resources-config/ask-states"); +const ResourcesConfig = require("../../model/resources-config"); +const stringUtils = require("../../utils/string-utils"); +const CONSTANTS = require("../../utils/constants"); +const Messenger = require("../../view/messenger"); -const ui = require('./ui'); +const ui = require("./ui"); module.exports = { - preInitCheck, - getSkillIdUserInput, - getSkillMetadataUserInput, - getSkillCodeUserInput, - getSkillInfraUserInput, - previewAndWriteAskResources, - bootstrapSkillInfra + preInitCheck, + getSkillIdUserInput, + getSkillMetadataUserInput, + getSkillCodeUserInput, + getSkillInfraUserInput, + previewAndWriteAskResources, + bootstrapSkillInfra, }; /** @@ -30,31 +30,31 @@ module.exports = { * @param {Function} callback (err) */ function preInitCheck(rootPath, profile, callback) { - ui.showInitInstruction(profile); - _attemptGetAskResources(rootPath, (attemptErr) => { - callback(attemptErr); - }); + ui.showInitInstruction(profile); + _attemptGetAskResources(rootPath, (attemptErr) => { + callback(attemptErr); + }); } function _attemptGetAskResources(rootPath, callback) { - const askResourcesPath = path.join(rootPath, CONSTANTS.FILE_PATH.ASK_RESOURCES_JSON_CONFIG); - if (fs.existsSync(askResourcesPath)) { - ui.confirmOverwrite((confirmErr, isConfirmed) => { - if (confirmErr) { - return callback(confirmErr); - } - if (!isConfirmed) { - return callback( - new CliWarn(`Please modify the existing ${CONSTANTS.FILE_PATH.ASK_RESOURCES_JSON_CONFIG} file or choose to overwrite.`) - ); - } - callback(); - }); - } else { - process.nextTick(() => { - callback(); - }); - } + const askResourcesPath = path.join(rootPath, CONSTANTS.FILE_PATH.ASK_RESOURCES_JSON_CONFIG); + if (fs.existsSync(askResourcesPath)) { + ui.confirmOverwrite((confirmErr, isConfirmed) => { + if (confirmErr) { + return callback(confirmErr); + } + if (!isConfirmed) { + return callback( + new CliWarn(`Please modify the existing ${CONSTANTS.FILE_PATH.ASK_RESOURCES_JSON_CONFIG} file or choose to overwrite.`), + ); + } + callback(); + }); + } else { + process.nextTick(() => { + callback(); + }); + } } /** @@ -62,10 +62,10 @@ function _attemptGetAskResources(rootPath, callback) { * @param {Function} callback (err, skillId) */ function getSkillIdUserInput(callback) { - ui.getSkillId((skillIdErr, skillId) => { - callback(skillIdErr, !skillIdErr ? skillId : null); - // TODO: use hosted-skill controller to check if the skillId is for hosted skill - }); + ui.getSkillId((skillIdErr, skillId) => { + callback(skillIdErr, !skillIdErr ? skillId : null); + // TODO: use hosted-skill controller to check if the skillId is for hosted skill + }); } /** @@ -73,9 +73,9 @@ function getSkillIdUserInput(callback) { * @param {Function} callback (err, {src}) */ function getSkillMetadataUserInput(callback) { - ui.getSkillMetaSrc((skillMetaErr, skillMetaSrc) => { - callback(skillMetaErr, !skillMetaErr ? { src: skillMetaSrc } : null); - }); + ui.getSkillMetaSrc((skillMetaErr, skillMetaSrc) => { + callback(skillMetaErr, !skillMetaErr ? {src: skillMetaSrc} : null); + }); } /** @@ -83,17 +83,17 @@ function getSkillMetadataUserInput(callback) { * @param {Function} callback (err, {src}) */ function getSkillCodeUserInput(callback) { - ui.getCodeSrcForRegion(CONSTANTS.ALEXA.REGION.DEFAULT, (defaultRegionErr, defaultSrc) => { - if (defaultRegionErr) { - return callback(defaultRegionErr); - } - if (defaultSrc === '') { - return callback(); // return null if user inputs empty string - } - const skillCode = {}; - skillCode[CONSTANTS.ALEXA.REGION.DEFAULT] = { src: defaultSrc }; - callback(null, skillCode); - }); + ui.getCodeSrcForRegion(CONSTANTS.ALEXA.REGION.DEFAULT, (defaultRegionErr, defaultSrc) => { + if (defaultRegionErr) { + return callback(defaultRegionErr); + } + if (defaultSrc === "") { + return callback(); // return null if user inputs empty string + } + const skillCode = {}; + skillCode[CONSTANTS.ALEXA.REGION.DEFAULT] = {src: defaultSrc}; + callback(null, skillCode); + }); } /** @@ -101,18 +101,18 @@ function getSkillCodeUserInput(callback) { * @param {Function} callback (err, {type, userConfig}) */ function getSkillInfraUserInput(callback) { - ui.getSkillInfra((deployerErr, infraSettings) => { - if (deployerErr) { - return callback(deployerErr); - } - const skillInfra = {}; - skillInfra.type = infraSettings.isUsingCfn ? '@ask-cli/cfn-deployer' : '@ask-cli/lambda-deployer'; - skillInfra.userConfig = { - runtime: infraSettings.runtime, - handler: infraSettings.handler - }; - callback(null, skillInfra); - }); + ui.getSkillInfra((deployerErr, infraSettings) => { + if (deployerErr) { + return callback(deployerErr); + } + const skillInfra = {}; + skillInfra.type = infraSettings.isUsingCfn ? "@ask-cli/cfn-deployer" : "@ask-cli/lambda-deployer"; + skillInfra.userConfig = { + runtime: infraSettings.runtime, + handler: infraSettings.handler, + }; + callback(null, skillInfra); + }); } /** @@ -123,49 +123,49 @@ function getSkillInfraUserInput(callback) { * @param {Function} callback (err) */ function previewAndWriteAskResources(rootPath, userInput, profile, callback) { - const { askResources, askStates } = _assembleAskResources(userInput, profile); - ui.showPreviewAndConfirm(rootPath, { askResources, askStates }, (confirmErr, isConfirmed) => { - if (confirmErr) { - return callback(confirmErr); - } - if (!isConfirmed) { - return callback(new CliWarn('Project init aborted.')); - } - try { - const askResourcesFilePath = path.join(rootPath, CONSTANTS.FILE_PATH.ASK_RESOURCES_JSON_CONFIG); - const askHiddenFolder = path.join(rootPath, CONSTANTS.FILE_PATH.HIDDEN_ASK_FOLDER); - const askStatesFilePath = path.join(askHiddenFolder, CONSTANTS.FILE_PATH.ASK_STATES_JSON_CONFIG); - fs.removeSync(askResourcesFilePath); - AskResources.withContent(askResourcesFilePath, askResources); - fs.removeSync(askHiddenFolder); - AskStates.withContent(askStatesFilePath, askStates); - } catch (writeErr) { - return callback(writeErr); - } - callback(); - }); + const {askResources, askStates} = _assembleAskResources(userInput, profile); + ui.showPreviewAndConfirm(rootPath, {askResources, askStates}, (confirmErr, isConfirmed) => { + if (confirmErr) { + return callback(confirmErr); + } + if (!isConfirmed) { + return callback(new CliWarn("Project init aborted.")); + } + try { + const askResourcesFilePath = path.join(rootPath, CONSTANTS.FILE_PATH.ASK_RESOURCES_JSON_CONFIG); + const askHiddenFolder = path.join(rootPath, CONSTANTS.FILE_PATH.HIDDEN_ASK_FOLDER); + const askStatesFilePath = path.join(askHiddenFolder, CONSTANTS.FILE_PATH.ASK_STATES_JSON_CONFIG); + fs.removeSync(askResourcesFilePath); + AskResources.withContent(askResourcesFilePath, askResources); + fs.removeSync(askHiddenFolder); + AskStates.withContent(askStatesFilePath, askStates); + } catch (writeErr) { + return callback(writeErr); + } + callback(); + }); } function _assembleAskResources(userInput, profile) { - const askResourcesJson = R.clone(AskResources.BASE); - const askStatesJson = R.clone(AskStates.BASE); - const askProfileResources = { skillMetadata: userInput.skillMeta }; - const askProfileStates = { skillId: userInput.skillId }; - if (userInput.skillCode) { - askProfileResources.code = userInput.skillCode; - } - if (userInput.skillInfra) { - askProfileResources.skillInfrastructure = userInput.skillInfra; - askProfileStates.skillInfrastructure = { - [userInput.skillInfra.type]: { - deployState: {} - } - }; - } - return { - askResources: R.set(R.lensPath(['profiles', profile]), askProfileResources, askResourcesJson), - askStates: R.set(R.lensPath(['profiles', profile]), askProfileStates, askStatesJson) + const askResourcesJson = R.clone(AskResources.BASE); + const askStatesJson = R.clone(AskStates.BASE); + const askProfileResources = {skillMetadata: userInput.skillMeta}; + const askProfileStates = {skillId: userInput.skillId}; + if (userInput.skillCode) { + askProfileResources.code = userInput.skillCode; + } + if (userInput.skillInfra) { + askProfileResources.skillInfrastructure = userInput.skillInfra; + askProfileStates.skillInfrastructure = { + [userInput.skillInfra.type]: { + deployState: {}, + }, }; + } + return { + askResources: R.set(R.lensPath(["profiles", profile]), askProfileResources, askResourcesJson), + askStates: R.set(R.lensPath(["profiles", profile]), askProfileStates, askStatesJson), + }; } /** @@ -176,25 +176,25 @@ function _assembleAskResources(userInput, profile) { * @param {Function} callback {err} */ function bootstrapSkillInfra(rootPath, profile, doDebug, callback) { - const askResourcesFilePath = path.join(rootPath, CONSTANTS.FILE_PATH.ASK_RESOURCES_JSON_CONFIG); - new ResourcesConfig(askResourcesFilePath); - const deployerType = ResourcesConfig.getInstance().getSkillInfraType(profile); - if (!stringUtils.isNonBlankString(deployerType)) { - return process.nextTick(() => { - callback(); - }); - } - // bootstrap after deployer gets selected - const ddFolderPath = deployerType.startsWith('@ask-cli/') ? deployerType.replace('@ask-cli/', '') : deployerType; - const deployerPath = path.join(rootPath, CONSTANTS.FILE_PATH.SKILL_INFRASTRUCTURE.INFRASTRUCTURE, ddFolderPath); - fs.ensureDirSync(deployerPath); - const skillInfraController = new SkillInfrastructureController({ profile, doDebug }); - skillInfraController.bootstrapInfrastructures(deployerPath, (bootstrapErr) => { - if (bootstrapErr) { - return callback(bootstrapErr); - } - ResourcesConfig.getInstance().write(); - Messenger.getInstance().info(`Project bootstrap from deployer "${deployerType}" succeeded.`); - callback(); + const askResourcesFilePath = path.join(rootPath, CONSTANTS.FILE_PATH.ASK_RESOURCES_JSON_CONFIG); + new ResourcesConfig(askResourcesFilePath); + const deployerType = ResourcesConfig.getInstance().getSkillInfraType(profile); + if (!stringUtils.isNonBlankString(deployerType)) { + return process.nextTick(() => { + callback(); }); + } + // bootstrap after deployer gets selected + const ddFolderPath = deployerType.startsWith("@ask-cli/") ? deployerType.replace("@ask-cli/", "") : deployerType; + const deployerPath = path.join(rootPath, CONSTANTS.FILE_PATH.SKILL_INFRASTRUCTURE.INFRASTRUCTURE, ddFolderPath); + fs.ensureDirSync(deployerPath); + const skillInfraController = new SkillInfrastructureController({profile, doDebug}); + skillInfraController.bootstrapInfrastructures(deployerPath, (bootstrapErr) => { + if (bootstrapErr) { + return callback(bootstrapErr); + } + ResourcesConfig.getInstance().write(); + Messenger.getInstance().info(`Project bootstrap from deployer "${deployerType}" succeeded.`); + callback(); + }); } diff --git a/lib/commands/init/index.js b/lib/commands/init/index.js deleted file mode 100644 index c4d11c30..00000000 --- a/lib/commands/init/index.js +++ /dev/null @@ -1,222 +0,0 @@ -const path = require('path'); -const R = require('ramda'); - -const SmapiClient = require('@src/clients/smapi-client'); -const { AbstractCommand } = require('@src/commands/abstract-command'); -const optionModel = require('@src/commands/option-model'); -const HostedSkillController = require('@src/controllers/hosted-skill-controller'); -const CliWarn = require('@src/exceptions/cli-warn'); -const CONSTANTS = require('@src/utils/constants'); -const profileHelper = require('@src/utils/profile-helper'); -const stringUtils = require('@src/utils/string-utils'); -const jsonView = require('@src/view/json-view'); -const Messenger = require('@src/view/messenger'); - -const helper = require('./helper'); -const ui = require('./ui'); - -class InitCommand extends AbstractCommand { - name() { - return 'init'; - } - - description() { - return 'setup a new or existing Alexa skill project'; - } - - requiredOptions() { - return []; - } - - optionalOptions() { - return ['hosted-skill-id', 'profile', 'debug']; - } - - handle(cmd, cb) { - let profile; - try { - profile = profileHelper.runtimeProfile(cmd.profile); - } catch (err) { - Messenger.getInstance().error(err); - return cb(err); - } - - const rootPath = process.cwd(); - if (!cmd.hostedSkillId) { - initNonHostedSkill(rootPath, cmd, profile, (nhsErr) => { - cb(nhsErr); - }); - } else { - initAlexaHostedSkill(rootPath, cmd, profile, (ahsErr) => { - cb(ahsErr); - }); - } - } -} - -function initAlexaHostedSkill(rootPath, cmd, profile, cb) { - const smapiClient = new SmapiClient({ profile, doDebug: cmd.debug }); - const hostedSkillController = new HostedSkillController({ profile, doDebug: cmd.debug }); - _getSkillName(smapiClient, cmd.hostedSkillId, (nameErr, skillName) => { - if (nameErr) { - Messenger.getInstance().error(nameErr); - return cb(nameErr); - } - _confirmProjectFolderName(skillName, (confirmErr, folderName) => { - if (confirmErr) { - Messenger.getInstance().error(confirmErr); - return cb(confirmErr); - } - const projectPath = path.join(rootPath, folderName); - - hostedSkillController.updateAskSystemScripts((scriptErr) => { - if (scriptErr) { - Messenger.getInstance().error(scriptErr); - return cb(scriptErr); - } - hostedSkillController.clone(cmd.hostedSkillId, skillName, projectPath, (cloneErr) => { - if (cloneErr) { - Messenger.getInstance().error(cloneErr); - return cb(cloneErr); - } - hostedSkillController.updateSkillPrePushScript(folderName, (hooksErr) => { - if (hooksErr) { - Messenger.getInstance().error(hooksErr); - return cb(hooksErr); - } - Messenger.getInstance().info(`\n${skillName} successfully initialized.\n`); - cb(); - }); - }); - }); - }); - }); -} - -function initNonHostedSkill(rootPath, cmd, profile, cb) { - helper.preInitCheck(rootPath, profile, (preCheckErr) => { - if (preCheckErr) { - if (preCheckErr instanceof CliWarn) { - Messenger.getInstance().warn(preCheckErr.message); - } else { - Messenger.getInstance().error(preCheckErr); - } - return cb(preCheckErr); - } - _collectAskResources((inputErr, userInput) => { - if (inputErr) { - Messenger.getInstance().error(inputErr); - return cb(inputErr); - } - helper.previewAndWriteAskResources(rootPath, userInput, profile, (previewErr) => { - if (previewErr) { - if (previewErr instanceof CliWarn) { - Messenger.getInstance().warn(previewErr.message); - } else { - Messenger.getInstance().error(previewErr); - } - return cb(previewErr); - } - helper.bootstrapSkillInfra(rootPath, profile, cmd.debug, (postErr) => { - if (postErr) { - Messenger.getInstance().error(postErr); - return cb(postErr); - } - Messenger.getInstance().info('\nSuccess! Run "ask deploy" to deploy your skill.'); - cb(); - }); - }); - }); - }); -} - -/** - * List of QAs to collect users' ask-resources configurations - * @param {Function} callback (err, userInput) - * userInput { skillId, skillMeta, skillCode, skillInfra } each resource object has the same structure as ask-resources config - */ -function _collectAskResources(callback) { - helper.getSkillIdUserInput((skillIdErr, skillId) => { - if (skillIdErr) { - return callback(skillIdErr); - } - helper.getSkillMetadataUserInput((metaErr, skillMeta) => { - if (metaErr) { - return callback(metaErr); - } - helper.getSkillCodeUserInput((codeErr, skillCode) => { - if (codeErr) { - return callback(codeErr); - } - if (!skillCode) { - // return to skip skillInfra setting if skill code is not provided - return callback(null, { skillId, skillMeta }); - } - helper.getSkillInfraUserInput((infraErr, skillInfra) => { - if (infraErr) { - return callback(infraErr); - } - callback(null, { skillId, skillMeta, skillCode, skillInfra }); - }); - }); - }); - }); -} - -/** - * To get skill name by calling skill's getManifest api - * @param {Object} smapiClient SMAPI client to make request - * @param {string} skillId The skill ID - * @param {callback} callback { error, response } - */ -function _getSkillName(smapiClient, skillId, callback) { - _getSkillManifest(smapiClient, skillId, (manifestErr, manifest) => { - if (manifestErr) { - return callback(manifestErr); - } - const locales = R.view(R.lensPath(['manifest', 'publishingInformation', 'locales']), manifest); - if (!locales) { - return callback('No skill name found.'); - } - const name = locales['en-US'] ? locales['en-US'].name : Object.keys(locales)[0].name; - callback(null, name); - }); -} - -/** - * To call getManifest api and return skill manifest - * @param {Object} smapiClient SMAPI client to make request - * @param {string} skillId The skill ID - * @param {callback} callback { error, response } - */ -function _getSkillManifest(smapiClient, skillId, callback) { - smapiClient.skill.manifest.getManifest(skillId, CONSTANTS.SKILL.STAGE.DEVELOPMENT, (err, res) => { - if (err) { - return callback(err); - } - if (res.statusCode >= 300) { - const error = jsonView.toString(res.body); - return callback(error); - } - callback(null, res.body); - }); -} - -/** - * To confirm the project folder name with users, - * the default folder name is generated from the skillName - * @param {string} skillName The skill name - * @param {string} callback callback { error, response } - */ -function _confirmProjectFolderName(skillName, callback) { - const suggestedProjectName = stringUtils.filterNonAlphanumeric(skillName); - ui.getProjectFolderName(suggestedProjectName, (getFolderNameErr, folderName) => { - if (getFolderNameErr) { - return callback(getFolderNameErr); - } - callback(null, folderName); - }); -} - -module.exports = InitCommand; -module.exports.createCommand = new InitCommand(optionModel).createCommand(); diff --git a/lib/commands/init/index.ts b/lib/commands/init/index.ts new file mode 100644 index 00000000..d9bdd2c1 --- /dev/null +++ b/lib/commands/init/index.ts @@ -0,0 +1,215 @@ +import path from "path"; +import SmapiClient, {ISmapiClient, isSmapiError} from "../../clients/smapi-client"; +import {AbstractCommand} from "../abstract-command"; +import optionModel from "../option-model.json"; +import HostedSkillController from "../../controllers/hosted-skill-controller"; +import CliWarn from "../../exceptions/cli-warn"; +import CONSTANTS from "../../utils/constants"; +import profileHelper from "../../utils/profile-helper"; +import stringUtils from "../../utils/string-utils"; +import jsonView from "../../view/json-view"; +import Messenger from "../../view/messenger"; +import helper from "./helper"; +import ui from "./ui"; +import {OptionModel} from "../option-validator"; +import {v1} from "ask-smapi-model"; + +export default class InitCommand extends AbstractCommand { + name() { + return "init"; + } + + description() { + return "setup a new or existing Alexa skill project"; + } + + requiredOptions() { + return []; + } + + optionalOptions() { + return ["hosted-skill-id", "profile", "debug"]; + } + + async handle(cmd: Record) { + let profile; + try { + profile = profileHelper.runtimeProfile(cmd.profile); + } catch (err) { + Messenger.getInstance().error(err); + throw err; + } + + const rootPath = process.cwd(); + if (!cmd.hostedSkillId) { + await initNonHostedSkill(rootPath, cmd, profile); + } else { + await initAlexaHostedSkill(rootPath, cmd, profile); + } + } +} + +async function initAlexaHostedSkill(rootPath: string, cmd: Record, profile: string): Promise { + const smapiClient = new SmapiClient({profile, doDebug: cmd.debug}); + const hostedSkillController = new HostedSkillController({profile, doDebug: cmd.debug}); + try { + const skillName = await _getSkillName(smapiClient, cmd.hostedSkillId); + const folderName = await _confirmProjectFolderName(skillName); + + const projectPath = path.join(rootPath, folderName); + + return new Promise((resolve, reject) => { + hostedSkillController.updateAskSystemScripts((scriptErr: any) => { + if (scriptErr) { + Messenger.getInstance().error(scriptErr); + return reject(scriptErr); + } + hostedSkillController.clone(cmd.hostedSkillId, skillName, projectPath, (cloneErr: any) => { + if (cloneErr) { + Messenger.getInstance().error(cloneErr); + return reject(cloneErr); + } + hostedSkillController.updateSkillPrePushScript(folderName, (hooksErr: any) => { + if (hooksErr) { + Messenger.getInstance().error(hooksErr); + return reject(hooksErr); + } + Messenger.getInstance().info(`\n${skillName} successfully initialized.\n`); + resolve(); + }); + }); + }); + }); + } catch (err) { + Messenger.getInstance().error(err); + throw err; + } +} + +async function initNonHostedSkill(rootPath: string, cmd: Record, profile: string): Promise { + return new Promise((resolve, reject) => { + helper.preInitCheck(rootPath, profile, (preCheckErr: any) => { + if (preCheckErr) { + if (preCheckErr instanceof CliWarn) { + Messenger.getInstance().warn(preCheckErr.message); + } else { + Messenger.getInstance().error(preCheckErr); + } + return reject(preCheckErr); + } + _collectAskResources() + .then((userInput) => { + helper.previewAndWriteAskResources(rootPath, userInput, profile, (previewErr: any) => { + if (previewErr) { + if (previewErr instanceof CliWarn) { + Messenger.getInstance().warn(previewErr.message); + } else { + Messenger.getInstance().error(previewErr); + } + return reject(previewErr); + } + helper.bootstrapSkillInfra(rootPath, profile, cmd.debug, (postErr: any) => { + if (postErr) { + Messenger.getInstance().error(postErr); + return reject(postErr); + } + Messenger.getInstance().info('\nSuccess! Run "ask deploy" to deploy your skill.'); + resolve(); + }); + }); + }) + .catch((inputErr) => { + Messenger.getInstance().error(inputErr); + return reject(inputErr); + }); + }); + }); +} + +/** + * List of QAs to collect users' ask-resources configurations + */ +async function _collectAskResources(): Promise<{skillId: string; skillMeta: any; skillCode?: any; skillInfra?: string}> { + return new Promise((resolve, reject) => { + helper.getSkillIdUserInput((skillIdErr?: any, skillId?: string) => { + if (skillIdErr) { + return reject(skillIdErr); + } + helper.getSkillMetadataUserInput((metaErr?: any, skillMeta?: any) => { + if (metaErr) { + return reject(metaErr); + } + helper.getSkillCodeUserInput((codeErr?: any, skillCode?: any) => { + if (codeErr) { + return reject(codeErr); + } + if (!skillCode) { + // return to skip skillInfra setting if skill code is not provided + return resolve({skillId: skillId!, skillMeta}); + } + helper.getSkillInfraUserInput((infraErr?: any, skillInfra?: any) => { + if (infraErr) { + return reject(infraErr); + } + resolve({skillId: skillId!, skillMeta, skillCode, skillInfra}); + }); + }); + }); + }); + }); +} + +/** + * To get skill name by calling skill's getManifest api + * @param {Object} smapiClient SMAPI client to make request + * @param {string} skillId The skill ID + * @param {callback} callback { error, response } + */ +async function _getSkillName(smapiClient: ISmapiClient, skillId: string) { + const manifest = await _getSkillManifest(smapiClient, skillId); + const locales = manifest?.manifest?.publishingInformation?.locales; + if (!locales) { + throw "No skill name found."; + } + return locales["en-US"] ? locales["en-US"].name : (Object.values(locales)[0]).name; +} + +/** + * To call getManifest api and return skill manifest + * @param {Object} smapiClient SMAPI client to make request + * @param {string} skillId The skill ID + * @param {callback} callback { error, response } + */ +async function _getSkillManifest(smapiClient: ISmapiClient, skillId: string): Promise { + return new Promise((resolve, reject) => { + smapiClient.skill.manifest.getManifest(skillId, CONSTANTS.SKILL.STAGE.DEVELOPMENT, (err, res) => { + if (err || !res) { + return reject(err); + } + if (isSmapiError(res)) { + return reject(jsonView.toString(res.body)); + } + resolve(res.body); + }); + }); +} + +/** + * To confirm the project folder name with users, + * the default folder name is generated from the skillName + * @param {string} skillName The skill name + * @param {string} callback callback { error, response } + */ +async function _confirmProjectFolderName(skillName: string): Promise { + const suggestedProjectName = stringUtils.filterNonAlphanumeric(skillName); + return new Promise((resolve, reject) => { + ui.getProjectFolderName(suggestedProjectName, (getFolderNameErr?: any, folderName?: string) => { + if (getFolderNameErr) { + return reject(getFolderNameErr); + } + return resolve(folderName!); + }); + }); +} + +export const createCommand = new InitCommand(optionModel as OptionModel).createCommand(); diff --git a/lib/commands/init/ui.js b/lib/commands/init/ui.js index 343f2cd3..a6c6c568 100644 --- a/lib/commands/init/ui.js +++ b/lib/commands/init/ui.js @@ -1,26 +1,26 @@ -const fs = require('fs'); -const inquirer = require('inquirer'); -const path = require('path'); +const fs = require("fs"); +const inquirer = require("inquirer"); +const path = require("path"); -const CONSTANTS = require('@src/utils/constants'); -const stringUtils = require('@src/utils/string-utils'); -const JsonView = require('@src/view/json-view'); -const Messenger = require('@src/view/messenger'); -const prompts = require('@src/view/prompt-view'); +const CONSTANTS = require("../../utils/constants"); +const stringUtils = require("../../utils/string-utils"); +const JsonView = require("../../view/json-view"); +const Messenger = require("../../view/messenger"); +const prompts = require("../../view/prompt-view"); module.exports = { - showInitInstruction, - confirmOverwrite, - getSkillId, - getSkillMetaSrc, - getCodeSrcForRegion, - getSkillInfra, - showPreviewAndConfirm, - getProjectFolderName: prompts.getProjectFolderName + showInitInstruction, + confirmOverwrite, + getSkillId, + getSkillMetaSrc, + getCodeSrcForRegion, + getSkillInfra, + showPreviewAndConfirm, + getProjectFolderName: prompts.getProjectFolderName, }; function showInitInstruction(profile) { - const initInstruction = `\ + const initInstruction = `\ This utility will walk you through creating an ask-resources.json file to help deploy your skill. This only covers the most common attributes and will suggest sensible defaults using AWS Lambda as your endpoint. @@ -37,123 +37,151 @@ different profile. Press ^C at any time to quit. `; - Messenger.getInstance().info(initInstruction); + Messenger.getInstance().info(initInstruction); } function confirmOverwrite(callback) { - inquirer.prompt([{ + inquirer + .prompt([ + { message: `${CONSTANTS.FILE_PATH.ASK_RESOURCES_JSON_CONFIG} already exists in current directory. Do you want to overwrite it? `, - type: 'confirm', + type: "confirm", default: true, - name: 'isOverwriteConfirmed' - }]).then((answer) => { - callback(null, answer.isOverwriteConfirmed); - }).catch((error) => { - callback(error); + name: "isOverwriteConfirmed", + }, + ]) + .then((answer) => { + callback(null, answer.isOverwriteConfirmed); + }) + .catch((error) => { + callback(error); }); } function getSkillId(callback) { - inquirer.prompt([{ - message: 'Skill Id (leave empty to create one): ', - type: 'input', - name: 'skillId' - }]).then((answer) => { - callback(null, answer.skillId.trim()); - }).catch((error) => { - callback(error); + inquirer + .prompt([ + { + message: "Skill Id (leave empty to create one): ", + type: "input", + name: "skillId", + }, + ]) + .then((answer) => { + callback(null, answer.skillId.trim()); + }) + .catch((error) => { + callback(error); }); } function getSkillMetaSrc(callback) { - inquirer.prompt([{ - message: 'Skill package path: ', - type: 'input', - default: './skill-package', - name: 'skillMetaSrc', + inquirer + .prompt([ + { + message: "Skill package path: ", + type: "input", + default: "./skill-package", + name: "skillMetaSrc", validate: (input) => { - if (!stringUtils.isNonBlankString(input)) { - return 'Path for skill package cannot be empty.'; - } - if (!fs.existsSync(input)) { - return 'File path does not exist.'; - } - return true; - } - }]).then((answer) => { - callback(null, answer.skillMetaSrc); - }).catch((error) => { - callback(error); + if (!stringUtils.isNonBlankString(input)) { + return "Path for skill package cannot be empty."; + } + if (!fs.existsSync(input)) { + return "File path does not exist."; + } + return true; + }, + }, + ]) + .then((answer) => { + callback(null, answer.skillMetaSrc); + }) + .catch((error) => { + callback(error); }); } function getCodeSrcForRegion(region, callback) { - inquirer.prompt([{ + inquirer + .prompt([ + { message: `Lambda code path for ${region} region (leave empty to not deploy Lambda): `, - type: 'input', - default: './lambda', - name: 'skillCodeSrc', + type: "input", + default: "./lambda", + name: "skillCodeSrc", validate: (input) => { - if (stringUtils.isNonBlankString(input) && !fs.existsSync(input)) { - return 'File path does not exist.'; - } - return true; - } - }]).then((answer) => { - callback(null, answer.skillCodeSrc.trim()); - }).catch((error) => { - callback(error); + if (stringUtils.isNonBlankString(input) && !fs.existsSync(input)) { + return "File path does not exist."; + } + return true; + }, + }, + ]) + .then((answer) => { + callback(null, answer.skillCodeSrc.trim()); + }) + .catch((error) => { + callback(error); }); } function getSkillInfra(callback) { - inquirer.prompt([ - { - message: 'Use AWS CloudFormation to deploy Lambda? ', - type: 'confirm', - default: true, - name: 'isUsingCfn' - }, - { - message: 'Lambda runtime: ', - type: 'input', - default: 'nodejs12.x', - name: 'runtime' - }, - { - message: 'Lambda handler: ', - type: 'input', - default: 'index.handler', - name: 'handler' - } - ]).then((answer) => { - callback(null, { - isUsingCfn: answer.isUsingCfn, - runtime: answer.runtime, - handler: answer.handler - }); - }).catch((error) => { - callback(error); + inquirer + .prompt([ + { + message: "Use AWS CloudFormation to deploy Lambda? ", + type: "confirm", + default: true, + name: "isUsingCfn", + }, + { + message: "Lambda runtime: ", + type: "input", + default: "nodejs16.x", + name: "runtime", + }, + { + message: "Lambda handler: ", + type: "input", + default: "index.handler", + name: "handler", + }, + ]) + .then((answer) => { + callback(null, { + isUsingCfn: answer.isUsingCfn, + runtime: answer.runtime, + handler: answer.handler, + }); + }) + .catch((error) => { + callback(error); }); } function showPreviewAndConfirm(rootPath, resourcesConfig, callback) { - const { askResources, askStates } = resourcesConfig; - Messenger.getInstance().info(` + const {askResources, askStates} = resourcesConfig; + Messenger.getInstance().info(` Writing to ${path.join(rootPath, CONSTANTS.FILE_PATH.ASK_RESOURCES_JSON_CONFIG)}: ${JsonView.toString(askResources)} Writing to ${path.join(rootPath, CONSTANTS.FILE_PATH.HIDDEN_ASK_FOLDER, CONSTANTS.FILE_PATH.ASK_STATES_JSON_CONFIG)}: ${JsonView.toString(askStates)} `); - inquirer.prompt([{ - message: 'Does this look correct? ', - type: 'confirm', + inquirer + .prompt([ + { + message: "Does this look correct? ", + type: "confirm", default: true, - name: 'confirmPreview' - }]).then((answer) => { - callback(null, answer.confirmPreview); - }).catch((error) => { - callback(error); + name: "confirmPreview", + }, + ]) + .then((answer) => { + callback(null, answer.confirmPreview); + }) + .catch((error) => { + callback(error); }); } diff --git a/lib/commands/new/helper.js b/lib/commands/new/helper.js deleted file mode 100644 index a70277ea..00000000 --- a/lib/commands/new/helper.js +++ /dev/null @@ -1,128 +0,0 @@ -const fs = require('fs-extra'); -const path = require('path'); - -const GitClient = require('@src/clients/git-client'); -const SkillInfrastructureController = require('@src/controllers/skill-infrastructure-controller'); -const Manifest = require('@src/model/manifest'); -const ResourcesConfig = require('@src/model/resources-config'); -const CONSTANTS = require('@src/utils/constants'); -const stringUtils = require('@src/utils/string-utils'); - -module.exports = { - downloadTemplateFromGit, - loadSkillProjectModel, - updateSkillProjectWithUserSettings, - initializeDeployDelegate, - bootstrapProject -}; - -/** - * Download the template from git - * @param {Object} userInput user input initialization setting - * @param {Function} callback (error, projectFolderPath) - */ -function downloadTemplateFromGit(userInput, doDebug, callback) { - const projectFolderPath = path.join(process.cwd(), userInput.projectFolderName); - const gitClient = new GitClient(projectFolderPath, { showOutput: !!doDebug, showCommand: !!doDebug }); - const branch = userInput.templateInfo.templateBranch || CONSTANTS.TEMPLATES.TEMPLATE_BRANCH_NAME; - gitClient.clone(userInput.templateInfo.templateUrl, branch, projectFolderPath); - callback(null, projectFolderPath); -} - -/** - * Validate if ask-resources config and skill.json exist in the skill package template - * @param {String} projectPath path for the skill project - * @param {String} profile ask-cli profile - */ -function loadSkillProjectModel(projectPath, profile) { - new ResourcesConfig(path.join(projectPath, CONSTANTS.FILE_PATH.ASK_RESOURCES_JSON_CONFIG)); - - const skillMetaSrc = ResourcesConfig.getInstance().getSkillMetaSrc(profile); - if (!stringUtils.isNonBlankString(skillMetaSrc)) { - throw new Error('[Error]: Invalid skill project structure. Please set the "src" field in skillMetada resource.'); - } - const skillPackageSrc = path.isAbsolute(skillMetaSrc) ? skillMetaSrc : path.join(projectPath, skillMetaSrc); - if (!fs.existsSync(skillPackageSrc)) { - throw new Error(`[Error]: Invalid skill package src. Attempt to get the skill package but doesn't exist: ${skillPackageSrc}.`); - } - const manifestPath = path.join(skillPackageSrc, 'skill.json'); - if (!fs.existsSync(manifestPath)) { - throw new Error(`[Error]: Invalid skill project structure. Please make sure skill.json exists in ${skillPackageSrc}.`); - } - new Manifest(manifestPath); -} - -/** - * Filter the downloaded skill project by - * 1.Remove the .git folder to avoid obfuscated git history - * 2.Update skill name in the skill.json - * @param {String} skillName the skill name - * @param {String} projectPath the project file path - * @param {String} profile ask-cli profile - */ -function updateSkillProjectWithUserSettings(skillName, projectPath, profile) { - // update skill name - Manifest.getInstance().setSkillName(skillName); - // update ask-resources config with profile name - const defaultProfileObject = ResourcesConfig.getInstance().getProfile('default'); - ResourcesConfig.getInstance().setProfile('default', undefined); - ResourcesConfig.getInstance().setProfile(profile, defaultProfileObject); - // remove .git folder - const hiddenGitFolder = path.join(projectPath, '.git'); - fs.removeSync(hiddenGitFolder); -} - -/** - * To initialize Deploy Engine or not by selected deployment type - * @param {String} deployerType the deployer type from userInput - * @param {String} infrastructurePath the root path for current deploy delegate's files in skill's project - * @param {String} profile ask-cli profile - * @param {Boolean} doDebug - * @param {callback} callback { error, ddType } return the selected deploy delegate type - */ -function initializeDeployDelegate(deployerType, projectFolderPath, profile, doDebug, callback) { - // no need to bootstrap if it's self-hosted - if (!deployerType) { - return callback(); - } - // no need to bootstrap as the project is already configured with deployerType - let ddType = ResourcesConfig.getInstance().getSkillInfraType(profile); - if (stringUtils.isNonBlankString(ddType) && deployerType === ddType) { - return callback(null, ddType); - } - // bootstrap when deployerType is not set from the template - const infrastructurePath = path.join(projectFolderPath, CONSTANTS.FILE_PATH.SKILL_INFRASTRUCTURE.INFRASTRUCTURE); - bootstrapProject(deployerType, infrastructurePath, profile, doDebug, (bootstrapErr) => { - if (bootstrapErr) { - return callback(bootstrapErr); - } - ddType = ResourcesConfig.getInstance().getSkillInfraType(profile); - callback(null, ddType); - }); -} - -/** - * Trigger the bootstrap process from the selected deploy delegate - * @param {String} deployerType the type of the deployer - * @param {String} infrastructurePath the root path for current deploy delegate's files in skill's project - * @param {String} profile ask-cli profile - * @param {Boolean} doDebug - * @param {Function} callback (error) - */ -function bootstrapProject(deployerType, infrastructurePath, profile, doDebug, callback) { - // 1.Initiate ask-resources config for skillInfrastructure field - const ddFolderPath = deployerType.startsWith('@ask-cli/') ? deployerType.replace('@ask-cli/', '') : deployerType; - const workspacePath = path.join(infrastructurePath, stringUtils.filterNonAlphanumeric(ddFolderPath)); - fs.ensureDirSync(workspacePath); - ResourcesConfig.getInstance().setSkillInfraType(profile, deployerType); - ResourcesConfig.getInstance().setSkillInfraDeployState(profile, {}); - - // 2.Bootstrap skill project with deploy delegate logic - const skillInfraController = new SkillInfrastructureController({ profile, doDebug }); - skillInfraController.bootstrapInfrastructures(workspacePath, (bootstrapErr) => { - if (bootstrapErr) { - return callback(bootstrapErr); - } - callback(); - }); -} diff --git a/lib/commands/new/helper.ts b/lib/commands/new/helper.ts new file mode 100644 index 00000000..6d2a671b --- /dev/null +++ b/lib/commands/new/helper.ts @@ -0,0 +1,133 @@ +import fs from "fs-extra"; +import path from "path"; +import {NewSkillDeployerType, NewSkillUserInput} from "."; +import GitClient from "../../clients/git-client"; +import SkillInfrastructureController from "../../controllers/skill-infrastructure-controller"; +import {uiCallback} from "../../model/callback"; +import Manifest from "../../model/manifest"; +import ResourcesConfig from "../../model/resources-config"; +import {TEMPLATES, FILE_PATH, DEPLOYER_TYPE} from "../../utils/constants"; +import stringUtils from "../../utils/string-utils"; + +/** + * Download the template from git + * @param {Object} userInput user input initialization setting + * @param {uiCallback} callback (error, projectFolderPath) + */ +export function downloadTemplateFromGit(userInput: NewSkillUserInput, doDebug: boolean, callback: uiCallback): void { + const projectFolderPath = path.join(process.cwd(), userInput.projectFolderName!); + const gitClient = new GitClient(projectFolderPath, {showOutput: !!doDebug, showCommand: !!doDebug}); + const branch = userInput.templateInfo?.templateBranch || TEMPLATES.TEMPLATE_DEFAULT_BRANCH_NAME; + gitClient.clone(userInput.templateInfo?.templateUrl!, branch, projectFolderPath); + callback(null, projectFolderPath); +} + +/** + * Validate if ask-resources config and skill.json exist in the skill package template + * @param {String} projectPath path for the skill project + * @param {String} profile ask-cli profile + */ +export function loadSkillProjectModel(projectPath: string, profile: string): void { + new ResourcesConfig(path.join(projectPath, FILE_PATH.ASK_RESOURCES_JSON_CONFIG)); + + const skillMetaSrc = ResourcesConfig.getInstance().getSkillMetaSrc(profile); + if (!stringUtils.isNonBlankString(skillMetaSrc)) { + throw new Error('[Error]: Invalid skill project structure. Please set the "src" field in skillMetadata resource.'); + } + const skillPackageSrc = path.isAbsolute(skillMetaSrc) ? skillMetaSrc : path.join(projectPath, skillMetaSrc); + if (!fs.existsSync(skillPackageSrc)) { + throw new Error(`[Error]: Invalid skill package src. Attempt to get the skill package but doesn't exist: ${skillPackageSrc}.`); + } + const manifestPath = path.join(skillPackageSrc, "skill.json"); + if (!fs.existsSync(manifestPath)) { + throw new Error(`[Error]: Invalid skill project structure. Please make sure skill.json exists in ${skillPackageSrc}.`); + } + new Manifest(manifestPath); +} + +/** + * Filter the downloaded skill project by + * 1.Remove the .git folder to avoid obfuscated git history + * 2.Update skill name in the skill.json + * @param {String} skillName the skill name + * @param {String} projectPath the project file path + * @param {String} profile ask-cli profile + */ +export function updateSkillProjectWithUserSettings(skillName: string, projectPath: string, profile: string): void { + // update skill name + Manifest.getInstance().setSkillName(skillName); + // update ask-resources config with profile name + const defaultProfileObject = ResourcesConfig.getInstance().getProfile("default"); + ResourcesConfig.getInstance().setProfile("default", undefined); + ResourcesConfig.getInstance().setProfile(profile, defaultProfileObject); + // remove .git folder + const hiddenGitFolder = path.join(projectPath, ".git"); + fs.removeSync(hiddenGitFolder); +} + +/** + * To initialize Deploy Engine or not by selected deployment type + * @param {NewSkillDeployerType} deployerType the deployer type from userInput + * @param {String} infrastructurePath the root path for current deploy delegate's files in skill's project + * @param {String} profile ask-cli profile + * @param {Boolean} doDebug + * @param {uiCallback} callback { error, ddType } return the selected deploy delegate type + */ +export function initializeDeployDelegate( + deployerType: NewSkillDeployerType | undefined, + projectFolderPath: string, + profile: string, + doDebug: boolean, + callback: uiCallback, +): void { + // no need to bootstrap if it's self-hosted + if (!deployerType || deployerType === DEPLOYER_TYPE.SELF_HOSTED.NAME) { + callback(null); + return; + } + // no need to bootstrap as the project is already configured with deployerType + let ddType = ResourcesConfig.getInstance().getSkillInfraType(profile); + if (stringUtils.isNonBlankString(ddType) && deployerType === ddType) { + callback(null, ddType); + return; + } + // bootstrap when deployerType is not set from the template + const infrastructurePath = path.join(projectFolderPath, FILE_PATH.SKILL_INFRASTRUCTURE.INFRASTRUCTURE); + bootstrapProject(deployerType, infrastructurePath, profile, doDebug, (bootstrapErr: Error) => { + if (bootstrapErr) { + callback(bootstrapErr); + } else { + ddType = ResourcesConfig.getInstance().getSkillInfraType(profile); + callback(null, ddType); + } + }); +} + +/** + * Trigger the bootstrap process from the selected deploy delegate + * @param {NewSkillDeployerType} deployerType the type of the deployer + * @param {String} infrastructurePath the root path for current deploy delegate's files in skill's project + * @param {String} profile ask-cli profile + * @param {Boolean} doDebug + * @param {Function} callback (error) + */ +export function bootstrapProject( + deployerType: NewSkillDeployerType, + infrastructurePath: string, + profile: string, + doDebug: boolean, + callback: Function, +): void { + // 1.Initiate ask-resources config for skillInfrastructure field + const ddFolderPath = deployerType.startsWith("@ask-cli/") ? deployerType.replace("@ask-cli/", "") : deployerType; + const workspacePath = path.join(infrastructurePath, stringUtils.filterNonAlphanumeric(ddFolderPath)); + fs.ensureDirSync(workspacePath); + ResourcesConfig.getInstance().setSkillInfraType(profile, deployerType); + ResourcesConfig.getInstance().setSkillInfraDeployState(profile, {}); + + // 2.Bootstrap skill project with deploy delegate logic + const skillInfraController = new SkillInfrastructureController({profile, doDebug}); + skillInfraController.bootstrapInfrastructures(workspacePath, (bootstrapErr: Error) => { + bootstrapErr ? callback(bootstrapErr) : callback(null); + }); +} diff --git a/lib/commands/new/hosted-skill-helper.js b/lib/commands/new/hosted-skill-helper.js deleted file mode 100644 index 1d1095fd..00000000 --- a/lib/commands/new/hosted-skill-helper.js +++ /dev/null @@ -1,256 +0,0 @@ -const fs = require('fs'); -const open = require('open'); -const path = require('path'); -const portScanner = require('portscanner'); -const { URL, URLSearchParams } = require('url'); - -const CONSTANTS = require('@src/utils/constants'); -const LocalHostServer = require('@src/utils/local-host-server'); -const stringUtils = require('@src/utils/string-utils'); -const Messenger = require('@src/view/messenger'); -const SpinnerView = require('@src/view/spinner-view'); -const SkillMetadataController = require('@src/controllers/skill-metadata-controller'); - -const permissionStatusMap = new Map(); -permissionStatusMap.set(CONSTANTS.HOSTED_SKILL.PERMISSION_CHECK_RESULT.NEW_USER_REGISTRATION_REQUIRED, - 'Failed to validate CAPTCHA. Please try again.'); -permissionStatusMap.set(CONSTANTS.HOSTED_SKILL.PERMISSION_CHECK_RESULT.RESOURCE_LIMIT_EXCEEDED, - 'Your hosted skills account is limited to a certain number of new hosted skills per minute. ' - + 'Please try again later.'); -permissionStatusMap.set(CONSTANTS.HOSTED_SKILL.PERMISSION_CHECK_RESULT.ALLOWED, null); - -module.exports = { - validateUserQualification, - createHostedSkill -}; - -/** - * To manage check permission and captcha validation for first time user - * @param {string} vendorId The vendor ID - * @param {Object} hostedSkillController The controller containing hosted skill main functionalities - * @param {callback} callback { error, response } - */ -function validateUserQualification(vendorId, hostedSkillController, callback) { - _checkPermission(hostedSkillController, vendorId, false, (error, actionUrl) => { - if (error) { - return callback(error); - } - if (!actionUrl) { - return callback(); - } - _solveCaptcha(vendorId, actionUrl, (captchaValidateError) => { - if (captchaValidateError) { - return callback(captchaValidateError); - } - // confirm captcha has been solved - _checkPermission(hostedSkillController, vendorId, true, (reCheckPermissionError) => { - if (reCheckPermissionError) { - return callback(reCheckPermissionError); - } - Messenger.getInstance().info('CAPTCHA validation was successfully completed. You are able to create a Alexa hosted skill.'); - return callback(); - }); - }); - }); -} - -/** - * To create an Alexa hosted skill and clone it into local machine - * @param {Object} hostedSkillController The controller containing hosted skill main functionalities - * @param {Object} userInput The user input { deploymentType, language, projectFolderName, skillName } - * @param {string} vendorId The vendor ID - * @param {callback} callback { error, response } - */ -function createHostedSkill(hostedSkillController, userInput, vendorId, callback) { - const rootPath = process.cwd(); - const projectPath = path.join(rootPath, userInput.projectFolderName); - const { profile, doDebug } = hostedSkillController; - const skillMetadataController = new SkillMetadataController({ profile, doDebug }); - if (fs.existsSync(projectPath)) { - return callback(`${projectPath} directory already exists.`); - } - const manifest = _updateManifest(userInput); - const input = { - vendorId, - manifest, - runtime: userInput.language, - region: userInput.region - }; - - const listenSpinner = new SpinnerView(); - listenSpinner.start('Creating your Alexa hosted skill. It will take about a minute.'); - hostedSkillController.createSkill(input, (createErr, skillId) => { - listenSpinner.terminate(); - if (createErr) { - if (!skillId) { - return callback(createErr); - } - hostedSkillController.deleteSkill(skillId, callback(createErr)); - } - hostedSkillController.updateAskSystemScripts((scriptErr) => { - if (scriptErr) { - return callback(scriptErr); - } - hostedSkillController.clone(skillId, userInput.skillName, projectPath, (cloneErr) => { - if (cloneErr) { - return callback(cloneErr); - } - skillMetadataController.enableSkill((enableErr) => { - if (enableErr) { - return callback(enableErr); - } - hostedSkillController.updateSkillPrePushScript(userInput.projectFolderName, (hooksErr) => { - if (hooksErr) { - return callback(hooksErr); - } - callback(null, skillId); - }); - }); - }); - }); - }); -} - -/** - * To update hosted skill manifest template with user input - * and return the manifest object. - * @param {Object} userInput The skill name - */ -function _updateManifest(userInput) { - const { skillName, locale } = userInput; - const manifest = CONSTANTS.HOSTED_SKILL.MANIFEST; - - manifest.publishingInformation.locales[locale] = {}; - manifest.publishingInformation.locales[locale].name = skillName; - - return manifest; -} - -/** - * Check user's permission to access hosted skill and handle error messages - * @param {Object} hostedSkillController The controller containing hosted skill main functionalities - * @param {boolean} isReCheck the recheck flag - * @param {callback} callback { error, response } - */ -function _checkPermission(hostedSkillController, vendorId, isReCheck, callback) { - hostedSkillController.getHostedSkillPermission(vendorId, CONSTANTS.HOSTED_SKILL.PERMISSION_ENUM.NEW_SKILL, - (permissionError, permissionRes) => { - if (permissionError) { - return callback(permissionError); - } - - if (!isReCheck - && permissionRes.status === CONSTANTS.HOSTED_SKILL.PERMISSION_CHECK_RESULT.NEW_USER_REGISTRATION_REQUIRED) { - Messenger.getInstance().info('CAPTCHA validation is required for a new hosted skill user.'); - return callback(null, permissionRes.actionUrl); - } - - const errorMessage = permissionStatusMap.get(permissionRes.status); - if (errorMessage) { - return callback(errorMessage); - } - return callback(); - }); -} - -/** - * To navigate user to the captcha validation page - * @param {string} vendorId The Vendor ID - * @param {string} captchaUrl The captcha url - * @param {callback} callback { error, response } - */ -function _solveCaptcha(vendorId, captchaUrl, callback) { - Messenger.getInstance().info('Go to the CAPTCHA page, confirm that you are signed into the correct developer account, and solve the CAPTCHA.\n' - + 'If your browser does not open the page, quit this process, paste the following url into your browser, ' - + `and complete the CAPTCHA.\n${captchaUrl}`); - - portScanner.checkPortStatus(CONSTANTS.LOCALHOST_PORT, (err, status) => { - if (err) { - callback(err); - } else { - if (status === 'closed') { - _openLoginUrlWithRedirectLink(captchaUrl, vendorId); - _listenResponseFromCaptchaServer(CONSTANTS.LOCALHOST_PORT, (error) => { - callback(error); - }); - } else { - callback(`${CONSTANTS.LOCALHOST_PORT} port on localhost has been occupied, ` - + 'ask-cli cannot start a local server for receiving authorization code.\n' - + `Please either abort any processes running on port ${CONSTANTS.LOCALHOST_PORT} ` - + 'or add `--no-browser` flag to the command as an alternative approach.'); - } - } - }); -} - -/** - * Build and open the url that navigates user to captcha validation page after login. - * @param captcha the validation url - * @param vendorId the vendor Id - */ -function _openLoginUrlWithRedirectLink(captchaUrl, vendorId) { - const envVarSignInHost = process.env.ASK_LWA_AUTHORIZE_HOST; - const loginUrl = new URL(envVarSignInHost && stringUtils.isNonBlankString(envVarSignInHost) - ? envVarSignInHost + CONSTANTS.HOSTED_SKILL.SIGNIN_PATH : CONSTANTS.LWA.SIGNIN_URL); - - loginUrl.search = new URLSearchParams([ - ['openid.ns', 'http://specs.openid.net/auth/2.0'], - ['openid.mode', 'checkid_setup'], - ['openid.claimed_id', 'http://specs.openid.net/auth/2.0/identifier_select'], - ['openid.identity', 'http://specs.openid.net/auth/2.0/identifier_select'], - ['openid.assoc_handle', 'amzn_dante_us'], - ['openid.return_to', `${captchaUrl}?vendor_id=${vendorId}&redirect_url=http://127.0.0.1:9090/captcha`], - ['openid.pape.max_auth_age', 7200] - ]).toString(); - open(loginUrl.href); -} - -/** - * Start a local server and listen the response from the captcha validation server, - * then extract validation result from it. - * @param PORT - * @param callback with error - */ -function _listenResponseFromCaptchaServer(PORT, callback) { - const listenSpinner = new SpinnerView(); - const server = new LocalHostServer(PORT); - server.create(handleServerRequest); - server.listen(() => { - listenSpinner.start(` Listening on http://localhost:${PORT}...`); - }); - server.registerEvent('connection', (socket) => { - socket.unref(); - }); - - function handleServerRequest(request, response) { - response.on('close', () => { - request.socket.destroy(); - }); - listenSpinner.terminate(); - server.destroy(); - if (request.url.startsWith('/captcha?success')) { - response.end('CAPTCHA validation was successful. Please close the browser and return to the command line interface.'); - callback(); - } else if (request.url.startsWith('/captcha?error')) { - const errorMsg = 'Failed to validate the CAPTCHA with internal service error. Please try again later.'; - response.statusCode = 500; - response.end(errorMsg); - callback(errorMsg); - } else if (request.url.startsWith('/captcha?vendorId')) { - const errorMsg = 'The Vendor ID in the browser session does not match the one associated with your CLI profile. \n' - + 'Please sign into the correct developer account in your browser before completing the CAPTCHA.'; - response.statusCode = 400; - response.end(errorMsg); - callback(errorMsg); - } else if (request.url.startsWith('/favicon.ico')) { - request.socket.destroy(); - response.statusCode = 204; - response.end(); - } else { - const errorMsg = 'Failed to validate the CAPTCHA. Please try again.'; - response.statusCode = 404; - response.end(errorMsg); - callback(errorMsg); - } - } -} diff --git a/lib/commands/new/hosted-skill-helper.ts b/lib/commands/new/hosted-skill-helper.ts new file mode 100644 index 00000000..bfb0a0f4 --- /dev/null +++ b/lib/commands/new/hosted-skill-helper.ts @@ -0,0 +1,263 @@ +import fs from "fs"; +import open from "open"; +import path from "path"; +import {URL, URLSearchParams} from "url"; +import {HOSTED_SKILL, LOCALHOST_PORT, LWA} from "../../utils/constants"; +import LocalHostServer from "../../utils/local-host-server"; +import stringUtils from "../../utils/string-utils"; +import Messenger from "../../view/messenger"; +import SpinnerView from "../../view/spinner-view"; +import SkillMetadataController from "../../controllers/skill-metadata-controller"; +import HostedSkillController from "../../controllers/hosted-skill-controller"; +import {callbackError, uiCallback} from "../../model/callback"; +import {Socket} from "node:net"; +import {IncomingMessage, ServerResponse} from "http"; +import portScanner, {Status} from "portscanner"; +import {NewSkillUserInput} from "."; + +const permissionStatusMap = new Map(); +permissionStatusMap.set( + HOSTED_SKILL.PERMISSION_CHECK_RESULT.NEW_USER_REGISTRATION_REQUIRED, + new Error("Failed to validate CAPTCHA. Please try again."), +); +permissionStatusMap.set( + HOSTED_SKILL.PERMISSION_CHECK_RESULT.RESOURCE_LIMIT_EXCEEDED, + new Error("Your hosted skills account is limited to a certain number of new hosted skills per minute. Please try again later."), +); +permissionStatusMap.set(HOSTED_SKILL.PERMISSION_CHECK_RESULT.ALLOWED, undefined); + +/** + * To manage check permission and captcha validation for first time user + * @param {string} vendorId The vendor ID + * @param {Object} hostedSkillController The controller containing hosted skill main functionalities + * @param {callback} callback { error, response } + */ +export function validateUserQualification(vendorId: string, hostedSkillController: HostedSkillController, callback: uiCallback): void { + _checkPermission(hostedSkillController, vendorId, false, (error: callbackError, actionUrl: string) => { + if (error) { + callback(error); + } else { + !actionUrl + ? callback(null) + : _solveCaptcha(vendorId, actionUrl, (captchaValidateError) => { + captchaValidateError + ? callback(captchaValidateError) + : _checkPermission(hostedSkillController, vendorId, true, (reCheckPermissionError: callbackError) => { + if (reCheckPermissionError) { + callback(reCheckPermissionError); + } else { + Messenger.getInstance().info( + "CAPTCHA validation was successfully completed. You are able to create a Alexa hosted skill.", + ); + callback(null); + } + }); + }); + } + }); +} + +/** + * To create an Alexa hosted skill and clone it into local machine + * @param {Object} hostedSkillController The controller containing hosted skill main functionalities + * @param {NewSkillUserInput} userInput The user input { deploymentType, language, projectFolderName, skillName } + * @param {string} vendorId The vendor ID + * @param {callback} callback { error, response } + */ +export function createHostedSkill( + hostedSkillController: HostedSkillController, + userInput: NewSkillUserInput, + vendorId: string, + callback: uiCallback, +): void { + const rootPath = process.cwd(); + const projectPath = path.join(rootPath, userInput.projectFolderName!); + if (fs.existsSync(projectPath)) { + callback(new Error(`${projectPath} directory already exists.`)); + } else { + const {profile, doDebug} = hostedSkillController; + const skillMetadataController = new SkillMetadataController({profile, doDebug}); + const manifest = _updateManifest(userInput); + const input = { + vendorId, + manifest, + runtime: userInput.language, + region: userInput.region, + }; + const listenSpinner = new SpinnerView(); + listenSpinner.start("Creating your Alexa hosted skill. It will take about a minute."); + hostedSkillController.createSkill(input, (createErr: callbackError, skillId: string) => { + listenSpinner.terminate(); + if (createErr) { + !skillId ? callback(createErr) : hostedSkillController.deleteSkill(skillId, callback(createErr)); + } else { + hostedSkillController.updateAskSystemScripts((scriptErr: callbackError) => { + scriptErr + ? callback(scriptErr) + : hostedSkillController.clone(skillId, userInput.skillName!, projectPath, (cloneErr: callbackError) => { + cloneErr + ? callback(cloneErr) + : skillMetadataController.enableSkill((enableErr: callbackError) => { + enableErr + ? callback(enableErr) + : hostedSkillController.updateSkillPrePushScript(userInput.projectFolderName!, (hooksErr: callbackError) => { + hooksErr ? callback(hooksErr) : callback(null, skillId); + }); + }); + }); + }); + } + }); + } +} + +/** + * To update hosted skill manifest template with user input + * and return the manifest object. + * @param {Object} userInput object containing skillName + * @returns {Manifest} an updated manifest including default apis and updated publishingInformation + */ +function _updateManifest(userInput: NewSkillUserInput): {publishingInformation: any; apis: any} { + const skillName = userInput.skillName; + const locale: string = userInput.locale || HOSTED_SKILL.DEFAULT_LOCALE; + const manifest: {publishingInformation: any; apis: any} = HOSTED_SKILL.MANIFEST; + + manifest.publishingInformation.locales[locale] = {}; + manifest.publishingInformation.locales[locale].name = skillName; + + return manifest; +} + +/** + * Check user's permission to access hosted skill and handle error messages + * @param {Object} hostedSkillController The controller containing hosted skill main functionalities + * @param {boolean} isReCheck the recheck flag + * @param {callback} callback { error, response } + */ +function _checkPermission(hostedSkillController: HostedSkillController, vendorId: string, isReCheck: boolean, callback: uiCallback): void { + hostedSkillController.getHostedSkillPermission( + vendorId, + HOSTED_SKILL.PERMISSION_ENUM.NEW_SKILL, + (permissionError: callbackError, permissionRes: any) => { + if (permissionError) { + callback(permissionError); + } else if (!isReCheck && permissionRes.status === HOSTED_SKILL.PERMISSION_CHECK_RESULT.NEW_USER_REGISTRATION_REQUIRED) { + Messenger.getInstance().info("CAPTCHA validation is required for a new hosted skill user."); + callback(null, permissionRes.actionUrl); + } else { + callback(permissionStatusMap.get(permissionRes.status) || null); + } + }, + ); +} + +/** + * To navigate user to the captcha validation page + * @param {string} vendorId The Vendor ID + * @param {string} captchaUrl The captcha url + * @param {callback} callback { error, response } + */ +function _solveCaptcha(vendorId: string, captchaUrl: string, callback: uiCallback): void { + Messenger.getInstance().info( + "Go to the CAPTCHA page, confirm that you are signed into the correct developer account, and solve the CAPTCHA.\n" + + "If your browser does not open the page, quit this process, paste the following url into your browser, " + + `and complete the CAPTCHA.\n${captchaUrl}`, + ); + + portScanner.checkPortStatus(Number.parseInt(LOCALHOST_PORT), (err: Error | null, status: Status) => { + if (err) { + callback(err); + } else { + if (status === "closed") { + _openLoginUrlWithRedirectLink(captchaUrl, vendorId); + _listenResponseFromCaptchaServer(LOCALHOST_PORT, (error: callbackError) => { + callback(error); + }); + } else { + callback( + new Error( + `${LOCALHOST_PORT} port on localhost has been occupied, ` + + "ask-cli cannot start a local server for receiving authorization code.\n" + + `Please either abort any processes running on port ${LOCALHOST_PORT} ` + + "or add `--no-browser` flag to the command as an alternative approach.", + ), + ); + } + } + }); +} + +/** + * Build and open the url that navigates user to captcha validation page after login. + * @param captcha the validation url + * @param vendorId the vendor Id + */ +function _openLoginUrlWithRedirectLink(captchaUrl: string, vendorId: string): void { + const envVarSignInHost = process.env.ASK_LWA_AUTHORIZE_HOST; + const loginUrl = new URL( + envVarSignInHost && stringUtils.isNonBlankString(envVarSignInHost) ? envVarSignInHost + HOSTED_SKILL.SIGNIN_PATH : LWA.SIGNIN_URL, + ); + + loginUrl.search = new URLSearchParams([ + ["openid.ns", "http://specs.openid.net/auth/2.0"], + ["openid.mode", "checkid_setup"], + ["openid.claimed_id", "http://specs.openid.net/auth/2.0/identifier_select"], + ["openid.identity", "http://specs.openid.net/auth/2.0/identifier_select"], + ["openid.assoc_handle", "amzn_dante_us"], + ["openid.return_to", `${captchaUrl}?vendor_id=${vendorId}&redirect_url=http://127.0.0.1:9090/captcha`], + ["openid.pape.max_auth_age", "7200"], + ]).toString(); + open(loginUrl.href); +} + +/** + * Start a local server and listen the response from the captcha validation server, + * then extract validation result from it. + * @param PORT + * @param callback with error + */ +function _listenResponseFromCaptchaServer(PORT: string, callback: uiCallback): void { + const listenSpinner = new SpinnerView(); + const server = new LocalHostServer(PORT); + server.create(handleServerRequest); + server.listen(() => { + listenSpinner.start(` Listening on http://localhost:${PORT}...`); + }); + server.registerEvent("connection", (socket: Socket) => { + socket.unref(); + }); + + function handleServerRequest(request: IncomingMessage, response: ServerResponse) { + response.on("close", () => { + request.socket.destroy(); + }); + listenSpinner.terminate(); + server.destroy(); + + if (request.url?.startsWith("/captcha?success")) { + response.end("CAPTCHA validation was successful. Please close the browser and return to the command line interface."); + callback(null); + } else if (request.url?.startsWith("/captcha?error")) { + const errorMsg = "Failed to validate the CAPTCHA with internal service error. Please try again later."; + response.statusCode = 500; + response.end(errorMsg); + callback(new Error(errorMsg)); + } else if (request.url?.startsWith("/captcha?vendorId")) { + const errorMsg = + "The Vendor ID in the browser session does not match the one associated with your CLI profile. \n" + + "Please sign into the correct developer account in your browser before completing the CAPTCHA."; + response.statusCode = 400; + response.end(errorMsg); + callback(new Error(errorMsg)); + } else if (request.url?.startsWith("/favicon.ico")) { + request.socket.destroy(); + response.statusCode = 204; + response.end(); + } else { + const errorMsg = "Failed to validate the CAPTCHA. Please try again."; + response.statusCode = 404; + response.end(errorMsg); + callback(new Error(errorMsg)); + } + } +} diff --git a/lib/commands/new/index.js b/lib/commands/new/index.js deleted file mode 100644 index e73ee6b6..00000000 --- a/lib/commands/new/index.js +++ /dev/null @@ -1,120 +0,0 @@ -const { AbstractCommand } = require('@src/commands/abstract-command'); -const optionModel = require('@src/commands/option-model'); -const HostedSkillController = require('@src/controllers/hosted-skill-controller'); -const Manifest = require('@src/model/manifest'); -const ResourcesConfig = require('@src/model/resources-config'); -const CONSTANTS = require('@src/utils/constants'); -const profileHelper = require('@src/utils/profile-helper'); -const Messenger = require('@src/view/messenger'); - -const helper = require('./helper'); -const hostedHelper = require('./hosted-skill-helper'); -const wizardHelper = require('./wizard-helper'); - -class NewCommand extends AbstractCommand { - name() { - return 'new'; - } - - description() { - return 'create a new skill project from Alexa skill templates'; - } - - requiredOptions() { - return []; - } - - optionalOptions() { - return ['templateUrl', 'templateBranch', 'profile', 'debug']; - } - - handle(cmd, cb) { - let profile, vendorId; - try { - profile = profileHelper.runtimeProfile(cmd.profile); - vendorId = profileHelper.resolveVendorId(profile); - } catch (err) { - Messenger.getInstance().error(err); - return cb(err); - } - // 0. collect user input and then create a skill(hosted skill or non hosted skill) - Messenger.getInstance().info('Please follow the wizard to start your Alexa skill project ->'); - wizardHelper.collectUserCreationProjectInfo(cmd, (initErr, userInput) => { - if (initErr) { - Messenger.getInstance().error(initErr); - return cb(initErr); - } - if (!userInput) { - return cb(); - } - if (userInput.deploymentType === CONSTANTS.DEPLOYER_TYPE.HOSTED.NAME) { - createHostedSkill(cmd, profile, vendorId, userInput, (hostedErr) => { - if (hostedErr) { - Messenger.getInstance().error(hostedErr); - return cb(hostedErr); - } - cb(); - }); - } else { - createNonHostedSkill(cmd, profile, cmd.debug, userInput, (nonHostedErr) => { - if (nonHostedErr) { - Messenger.getInstance().error(nonHostedErr); - return cb(nonHostedErr); - } - cb(); - }); - } - }); - } -} - -function createHostedSkill(cmd, profile, vendorId, userInput, callback) { - const hostedSkillController = new HostedSkillController({ profile, doDebug: cmd.debug }); - hostedHelper.validateUserQualification(vendorId, hostedSkillController, (validateErr) => { - if (validateErr) { - return callback(validateErr); - } - hostedHelper.createHostedSkill(hostedSkillController, userInput, vendorId, (createErr, skillId) => { - if (createErr) { - return callback(createErr); - } - Messenger.getInstance().info(`Hosted skill provisioning finished. Skill-Id: ${skillId}`); - Messenger.getInstance().info(`Please follow the instructions at ${CONSTANTS.GIT_USAGE_HOSTED_SKILL_DOCUMENTATION}` - + ' to learn more about the usage of "git" for Hosted skill.'); - ResourcesConfig.getInstance().write(); - callback(); - }); - }); -} - -function createNonHostedSkill(cmd, profile, doDebug, userInput, callback) { - // 1.download skill project templates - helper.downloadTemplateFromGit(userInput, doDebug, (projectErr, projectFolderPath) => { - if (projectErr) { - return callback(projectErr); - } - Messenger.getInstance().info(`Project for skill "${userInput.skillName}" is successfully created at ${projectFolderPath}\n`); - try { - // 2.load involving M(Model) component (ResourcesConfig & Manifest) from the downloaded skill project with 'default' profile - helper.loadSkillProjectModel(projectFolderPath, 'default'); - // 3.remove git record and update skill name - helper.updateSkillProjectWithUserSettings(userInput.skillName, projectFolderPath, profile); - } catch (projErr) { - return callback(projErr); - } - // 4.bootstrap the skill project with deploy delegate if needed - helper.initializeDeployDelegate(userInput.deploymentType, projectFolderPath, profile, cmd.debug, (deployDelegateErr, deployerType) => { - if (deployDelegateErr) { - return callback(deployDelegateErr); - } - Messenger.getInstance().info(deployerType ? `Project initialized with deploy delegate "${deployerType}" successfully.` - : 'Project initialized successfully.'); - ResourcesConfig.getInstance().write(); - Manifest.getInstance().write(); - callback(); - }); - }); -} - -module.exports = NewCommand; -module.exports.createCommand = new NewCommand(optionModel).createCommand(); diff --git a/lib/commands/new/index.ts b/lib/commands/new/index.ts new file mode 100644 index 00000000..0ee32596 --- /dev/null +++ b/lib/commands/new/index.ts @@ -0,0 +1,172 @@ +import {AbstractCommand} from "../abstract-command"; +import optionModel from "../option-model.json"; +import HostedSkillController from "../../controllers/hosted-skill-controller"; +import Manifest from "../../model/manifest"; +import ResourcesConfig from "../../model/resources-config"; +import {HOSTED_SKILL, DEPLOYER_TYPE, GIT_USAGE_HOSTED_SKILL_DOCUMENTATION} from "../../utils/constants"; +import profileHelper from "../../utils/profile-helper"; +import Messenger from "../../view/messenger"; +import * as helper from "./helper"; +import * as hostedHelper from "./hosted-skill-helper"; +import * as wizardHelper from "./wizard-helper"; +import {OptionModel} from "../option-validator"; + +export type NewSkillCodeLanguage = "NodeJS" | "Python" | "Java"; +export const CODE_LANGUAGE_NODEJS: NewSkillCodeLanguage = "NodeJS"; +export const CODE_LANGUAGE_PYTHON: NewSkillCodeLanguage = "Python"; +export const CODE_LANGUAGE_JAVA: NewSkillCodeLanguage = "Java"; +export type NewSkillDeployerType = string; +export type NewSkillDeployerTypeInfo = { + OPTION_NAME: string; + NAME: string; + DESCRIPTION: string; +}; +export type NewSkillModelingStackTypes = "Interaction Model" | "Alexa Conversations"; +export const MODELING_STACK_IM: NewSkillModelingStackTypes = "Interaction Model"; +export const MODELING_STACK_IM_DESCRIPTION: string = + "The Interaction Model stack enables you to define the user interactions with a combination of utterances, intents, and slots."; +export const MODELING_STACK_AC: NewSkillModelingStackTypes = "Alexa Conversations"; +export const MODELING_STACK_AC_DESCRIPTION: string = + "Alexa Conversations (AC) uses deep learning to manage the dialog flow. User utterances, APL, and APLA documents train the skill model to create natural, human-like Alexa voice experiences."; +export type NewSkillTemplateInfo = { + templateUrl?: string; + templateName?: string; + templateBranch?: string; +}; +export type NewSkillRegion = keyof typeof HOSTED_SKILL.REGIONS; +export type NewSkillUserInput = { + language?: NewSkillCodeLanguage; + deploymentType?: NewSkillDeployerType; + locale?: string; + region?: NewSkillRegion; + templateInfo?: NewSkillTemplateInfo; + skillName?: string; + projectFolderName?: string; + modelingStack?: NewSkillModelingStackTypes; +}; + +export default class NewCommand extends AbstractCommand { + name() { + return "new"; + } + + description() { + return "create a new skill project from Alexa skill templates"; + } + + requiredOptions() { + return []; + } + + optionalOptions() { + return ["templateUrl", "templateBranch", "profile", "debug"]; + } + + async handle(cmd: Record): Promise { + let profile: string, vendorId: string; + try { + profile = profileHelper.runtimeProfile(cmd.profile); + vendorId = profileHelper.resolveVendorId(profile); + } catch (err) { + Messenger.getInstance().error(err); + throw err; + } + // 0. collect user input and then create a skill(hosted skill or non hosted skill) + Messenger.getInstance().info("Please follow the wizard to start your Alexa skill project ->"); + return new Promise((resolve, reject) => { + wizardHelper.collectUserCreationProjectInfo(cmd, (initErr: Error | null, userInput?: NewSkillUserInput) => { + if (initErr) { + Messenger.getInstance().error(initErr); + return reject(initErr); + } + if (!userInput) { + return resolve(); + } + if (userInput.deploymentType === DEPLOYER_TYPE.HOSTED.NAME) { + createHostedSkill(cmd, profile, vendorId, userInput) + .then(resolve) + .catch((hostedErr) => { + Messenger.getInstance().error(hostedErr); + return reject(hostedErr); + }); + } else { + createNonHostedSkill(cmd, profile, cmd.debug, userInput) + .then(resolve) + .catch((nonHostedErr) => { + Messenger.getInstance().error(nonHostedErr); + return reject(nonHostedErr); + }); + } + }); + }); + } +} + +function createHostedSkill(cmd: Record, profile: string, vendorId: string, userInput: NewSkillUserInput): Promise { + return new Promise((resolve, reject) => { + const hostedSkillController = new HostedSkillController({profile, doDebug: cmd.debug}); + hostedHelper.validateUserQualification(vendorId, hostedSkillController, (validateErr: any) => { + if (validateErr) { + return reject(validateErr); + } + hostedHelper.createHostedSkill(hostedSkillController, userInput, vendorId, (createErr: any, skillId: string) => { + if (createErr) { + return reject(createErr); + } + Messenger.getInstance().info(`Hosted skill provisioning finished. Skill-Id: ${skillId}`); + Messenger.getInstance().info( + `Please follow the instructions at ${GIT_USAGE_HOSTED_SKILL_DOCUMENTATION}` + + ' to learn more about the usage of "git" for Hosted skill.', + ); + ResourcesConfig.getInstance().write(); + resolve(); + }); + }); + }); +} + +function createNonHostedSkill(cmd: Record, profile: string, doDebug: boolean, userInput: NewSkillUserInput): Promise { + return new Promise((resolve, reject) => { + // 1.download skill project templates + helper.downloadTemplateFromGit(userInput, doDebug, (projectErr: any, projectFolderPath: string) => { + if (projectErr) { + return reject(projectErr); + } + Messenger.getInstance().info(`Project for skill "${userInput.skillName}" is successfully created at ${projectFolderPath}\n`); + + if (userInput.deploymentType === DEPLOYER_TYPE.SELF_HOSTED.NAME) { + // nothing more to do for self hosted skills + resolve(); + } + + try { + // 2.load involving M(Model) component (ResourcesConfig & Manifest) from the downloaded skill project with 'default' profile + helper.loadSkillProjectModel(projectFolderPath, "default"); + // 3.remove git record and update skill name + helper.updateSkillProjectWithUserSettings(userInput.skillName!, projectFolderPath, profile); + } catch (projErr) { + return reject(projErr); + } + // 4.bootstrap the skill project with deploy delegate if needed + helper.initializeDeployDelegate( + userInput.deploymentType, + projectFolderPath, + profile, + cmd.debug, + (deployDelegateErr: any, deployerType: any) => { + if (deployDelegateErr) { + return reject(deployDelegateErr); + } + Messenger.getInstance().info( + deployerType ? `Project initialized with deploy delegate "${deployerType}" successfully.` : "Project initialized successfully.", + ); + ResourcesConfig.getInstance().write(); + Manifest.getInstance().write(); + resolve(); + }, + ); + }); + }); +} + +export const createCommand = new NewCommand(optionModel as OptionModel).createCommand(); diff --git a/lib/commands/new/template-helper.ts b/lib/commands/new/template-helper.ts new file mode 100644 index 00000000..359d6000 --- /dev/null +++ b/lib/commands/new/template-helper.ts @@ -0,0 +1,48 @@ +import httpClient from "../../clients/http-client"; +import R from "ramda"; +import {TEMPLATES, HTTP_REQUEST, DEPLOYER_TYPE} from "../../utils/constants"; +import {SampleTemplate, SampleTemplateFilterValues} from "../../model/sample-template"; +import {CODE_LANGUAGE_JAVA, CODE_LANGUAGE_NODEJS, CODE_LANGUAGE_PYTHON, MODELING_STACK_AC, MODELING_STACK_IM} from "."; + +export function getSampleTemplatesFromS3(doDebug: boolean): Promise { + return new Promise((resolve, reject) => { + const params = { + url: TEMPLATES.TEMPLATE_S3_SOURCE_URL, + method: HTTP_REQUEST.VERB.GET, + }; + httpClient.request(params, "TEMPLATE_S3_SOURCE_URL", doDebug, (error: Error | null, response: any) => { + if (error || !response.statusCode || response.statusCode !== 200) { + const msg = doDebug + ? "Failed to retrieve the skill sample templates." + : "Failed to retrieve the skill sample templates. Please run again with --debug to see the details."; + return reject(new Error(msg)); + } + resolve(R.view(R.lensPath(["templates"]), JSON.parse(response?.body))); + }); + }); +} + +export function convertUserInputToFilterValue(inputValue: string): SampleTemplateFilterValues { + switch (inputValue.toLowerCase()) { + case MODELING_STACK_IM.toLowerCase(): + return "im"; + case MODELING_STACK_AC.toLowerCase(): + return "ac"; + case CODE_LANGUAGE_NODEJS.toLowerCase(): + return "node"; + case CODE_LANGUAGE_PYTHON.toLowerCase(): + return "python"; + case CODE_LANGUAGE_JAVA.toLowerCase(): + return "java"; + case DEPLOYER_TYPE.LAMBDA.NAME.toLowerCase(): + return "lambda"; + case DEPLOYER_TYPE.CFN.NAME.toLowerCase(): + return "cfn"; + case DEPLOYER_TYPE.HOSTED.NAME.toLowerCase(): + return "hosted"; + case DEPLOYER_TYPE.SELF_HOSTED.NAME.toLowerCase(): + return "self"; + default: + throw new Error(`Unable to convert userInput '${inputValue}' to a sample template filter value.`); + } +} diff --git a/lib/commands/new/ui.js b/lib/commands/new/ui.js deleted file mode 100644 index fc321474..00000000 --- a/lib/commands/new/ui.js +++ /dev/null @@ -1,138 +0,0 @@ -const R = require('ramda'); -const chalk = require('chalk'); -const path = require('path'); -const inquirer = require('inquirer'); - -const CONSTANTS = require('@src/utils/constants'); -const stringUtils = require('@src/utils/string-utils'); -const prompts = require('@src/view/prompt-view'); - -const SKIP_DEPLOY_DELEGATE_SELECTION = 'self-hosted and manage your own hosting'; - -module.exports = { - getSkillName, - getSkillLocale, - getSkillDefaultRegion, - getProjectFolderName: prompts.getProjectFolderName, - selectSkillCodeLanguage, - getTargetTemplateName, - confirmUsingUnofficialTemplate, - getDeploymentType, - - SKIP_DEPLOY_DELEGATE_SELECTION -}; - -function getSkillName(url, callback) { - const defaultName = url ? path.basename(url, path.extname(url)) : CONSTANTS.HOSTED_SKILL.DEFAULT_SKILL_NAME; - inquirer.prompt([{ - message: 'Please type in your skill name: ', - type: 'input', - default: defaultName, - name: 'skillName', - validate: (input) => { - if (!stringUtils.isNonBlankString(input)) { - return 'Skill name can\'t be empty.'; - } - return true; - } - }]).then((answer) => { - callback(null, answer.skillName.trim()); - }).catch((error) => { - callback(error); - }); -} - -function getSkillLocale(callback) { - inquirer.prompt([{ - message: 'Choose the default locale for your skill: ', - type: 'list', - choices: CONSTANTS.HOSTED_SKILL.LOCALES, - name: 'locale', - pageSize: 5 - }]).then((answer) => { - callback(null, answer.locale); - }).catch((error) => { - callback(error); - }); -} - -function getSkillDefaultRegion(callback) { - inquirer.prompt([{ - message: 'Choose the default region for your skill: ', - type: 'list', - choices: Object.keys(CONSTANTS.HOSTED_SKILL.REGIONS), - name: 'region' - }]).then((answer) => { - callback(null, CONSTANTS.HOSTED_SKILL.REGIONS[answer.region]); - }).catch((error) => { - callback(error); - }); -} - -function selectSkillCodeLanguage(callback) { - inquirer.prompt([{ - type: 'list', - message: 'Choose the programming language you will use to code your skill: ', - name: 'language', - choices: Object.keys(CONSTANTS.TEMPLATES.PROJECT_BY_CODE_LANGUAGE) - }]).then((answer) => { - callback(null, answer.language.trim()); - }).catch((error) => { - callback(error); - }); -} - -function getTargetTemplateName(templateMap, callback) { - const templateList = R.keys(templateMap).map((templateName) => { - const description = templateMap[templateName].description || ''; - return `${templateName}\n ${chalk.gray(description)}`; - }); - inquirer.prompt([{ - type: 'list', - message: 'Choose a template to start with: ', - name: 'templateName', - choices: templateList, - pageSize: 30, - filter: input => input.replace(/\n.*/g, '') - }]).then((answer) => { - callback(null, answer.templateName); - }).catch((error) => { - callback(error); - }); -} - -function confirmUsingUnofficialTemplate(callback) { - inquirer.prompt([{ - message: 'Would you like to continue download the skill template? ', - type: 'confirm', - name: 'confirmation', - default: false - }]).then((answer) => { - callback(null, answer.confirmation); - }).catch((error) => { - callback(error); - }); -} - -function getDeploymentType(deployType, callback) { - const deployDelegateChoices = R.values(deployType).map( - (deployer) => `${deployer.OPTION_NAME}\n ${chalk.gray(deployer.DESCRIPTION)}` - ); - deployDelegateChoices.push(new inquirer.Separator()); - deployDelegateChoices.push(SKIP_DEPLOY_DELEGATE_SELECTION); - inquirer.prompt([{ - message: 'Choose a method to host your skill\'s backend resources: ', - type: 'list', - name: 'deployDelegate', - choices: deployDelegateChoices, - pageSize: 30, - filter: input => input.replace(/\n.*/g, '') - }]).then((answer) => { - if (answer.deployDelegate === SKIP_DEPLOY_DELEGATE_SELECTION) { - return callback(); - } - callback(null, R.find(R.propEq('OPTION_NAME', answer.deployDelegate))(R.values(deployType)).NAME); - }).catch((error) => { - callback(error); - }); -} diff --git a/lib/commands/new/ui.ts b/lib/commands/new/ui.ts new file mode 100644 index 00000000..b167c9b5 --- /dev/null +++ b/lib/commands/new/ui.ts @@ -0,0 +1,237 @@ +import {find, propEq, view, lensPath} from "ramda"; +import {gray} from "chalk"; +import path from "path"; +import inquirer from "inquirer"; +import {HOSTED_SKILL} from "../../utils/constants"; +import {callbackError, uiCallback} from "../../model/callback"; +import {isNonBlankString} from "../../utils/string-utils"; +import { + NewSkillDeployerTypeInfo, + MODELING_STACK_IM, + MODELING_STACK_AC, + NewSkillCodeLanguage, + MODELING_STACK_IM_DESCRIPTION, + MODELING_STACK_AC_DESCRIPTION, +} from "."; +import {SampleTemplate} from "../../model/sample-template"; + +/** + * Prompts the user to type a skill name and defaults to the name of the repo in the URL argument if provided. + * + * @param {string} url A url of the skill sample repository, used to determine the default skill name + * @param {uiCallback} callback function that will be called with the resulting value or error + */ +export function getSkillName(url: string | null, callback: uiCallback): void { + const defaultName = url ? path.basename(url, path.extname(url)) : HOSTED_SKILL.DEFAULT_SKILL_NAME; + inquirer + .prompt([ + { + message: "Please type in your skill name: ", + type: "input", + default: defaultName, + name: "skillName", + validate: (input) => { + if (!isNonBlankString(input)) { + return "Skill name can't be empty."; + } + return true; + }, + }, + ]) + .then((answer) => { + callback(null, answer.skillName.trim()); + }) + .catch((error) => { + callback(error); + }); +} + +/** + * Prompts for the default locale to use for the skill + * i.e. en-US, de-DE, fr-FR... + * + * @param {uiCallback} callback function that will be called with the resulting value or error + */ +export function getSkillLocale(callback: uiCallback): void { + inquirer + .prompt([ + { + message: "Choose the default locale for your skill: ", + type: "list", + choices: HOSTED_SKILL.LOCALES, + name: "locale", + pageSize: 5, + }, + ]) + .then((answer) => { + callback(null, answer.locale); + }) + .catch((error) => { + callback(error); + }); +} + +/** + * Prompts the user to select the default AWS Region to deploy the skill resources to + * ie. us-east-1 + * + * @param {uiCallback} callback function that will be called with the resulting value or error + */ +export function getSkillDefaultRegion(callback: uiCallback): void { + inquirer + .prompt([ + { + message: "Choose the default region for your skill: ", + type: "list", + choices: Object.keys(HOSTED_SKILL.REGIONS), + name: "region", + }, + ]) + .then((answer) => { + callback(null, (HOSTED_SKILL.REGIONS as any)[answer.region]); + }) + .catch((error) => { + callback(error); + }); +} + +/** + * Prompts the user to select what coding language to use for the sample skill + * i.e. NodeJs, Python, Java + * + * @param {NewSkillCodeLanguage[]} languages to offer as options + * @param {uiCallback} callback function that will be called with the resulting value or error + */ +export function selectSkillCodeLanguage(languages: NewSkillCodeLanguage[], callback: uiCallback): void { + inquirer + .prompt([ + { + type: "list", + message: "Choose the programming language you will use to code your skill: ", + name: "language", + choices: languages, + }, + ]) + .then((answer) => { + callback(null, answer.language.trim()); + }) + .catch((error) => { + callback(error); + }); +} + +/** + * Prompts the user to select what Template they want to clone + * + * @param {SampleTemplate[]} templateMap the list of templates to select from + * @param {uiCallback} callback function that will be called with the resulting value or error + */ +export function getTargetTemplateName( + templateMap: SampleTemplate[], + callback: (err: callbackError, sampleTemplate: SampleTemplate | undefined) => void, +): void { + inquirer + .prompt([ + { + type: "list", + message: "Choose a template to start with: ", + name: "templateName", + choices: templateMap.map((sampleTemplate) => `${String(sampleTemplate.name)}\n ${gray(sampleTemplate.desc)}`), + pageSize: 30, + filter: (input_1) => input_1.replace(/\n.*/g, ""), + }, + ]) + .then((answer) => { + callback( + null, + templateMap.find((sampletemplate) => sampletemplate.name === answer.templateName), + ); + }) + .catch((error) => { + callback(error, undefined); + }); +} + +/** + * Prompts the user to continue [yes or no] cloning the remote repo locally. + * ie. if the repository is not an official Amazon Alexa Skill sample template + * + * @param {uiCallback} callback function that will be called with the resulting value or error + */ +export function confirmUsingUnofficialTemplate(callback: uiCallback): void { + inquirer + .prompt([ + { + message: "Would you like to continue download the skill template? ", + type: "confirm", + name: "confirmation", + default: false, + }, + ]) + .then((answer) => { + callback(null, answer.confirmation); + }) + .catch((error) => { + callback(error); + }); +} + +/** + * Prompts the user to select a Deployment Type + * i.e. Lambda vs CloudFormation vs Alexa hosted vs self hosted + * + * @param {NewSkillDeployerTypeInfo[]} deployType An array of possible deployment types + * @param {uiCallback} callback function that will be called with the resulting value or error + */ +export function getDeploymentType(deployType: NewSkillDeployerTypeInfo[], callback: uiCallback): void { + const deployDelegateChoices = deployType.map((deployer) => `${deployer.OPTION_NAME}\n ${gray(deployer.DESCRIPTION)}`); + inquirer + .prompt([ + { + message: "Choose a method to host your skill's backend resources: ", + type: "list", + name: "deployDelegate", + choices: deployDelegateChoices, + pageSize: 30, + filter: (input) => input.replace(/\n.*/g, ""), + }, + ]) + .then((answer) => { + const selectedDeployDelegate = find(propEq("OPTION_NAME", answer.deployDelegate))(deployType); + callback(null, view(lensPath(["NAME"]), selectedDeployDelegate)); + }) + .catch((error) => { + callback(error); + }); +} + +/** + * Prompts the user to select the modeling stack type they want the samples to use + * i.e. Interaction Model vs Alexa Conversations + * + * @param {uiCallback} callback function that will be called with the resulting value or error + */ +export function getModelingStackType(callback: uiCallback): void { + const modelingStackChoices = [ + `${MODELING_STACK_IM}\n ${gray(MODELING_STACK_IM_DESCRIPTION)}`, + `${MODELING_STACK_AC}\n ${gray(MODELING_STACK_AC_DESCRIPTION)}`, + ]; + inquirer + .prompt([ + { + message: "Choose a modeling stack for your skill: ", + type: "list", + name: "modelingStack", + choices: modelingStackChoices, + default: MODELING_STACK_IM, + pageSize: 5, + filter: (input) => input.replace(/\n.*/g, ""), + }, + ]) + .then((answer) => { + callback(null, answer.modelingStack); + }) + .catch((error) => { + callback(error); + }); +} diff --git a/lib/commands/new/wizard-helper.js b/lib/commands/new/wizard-helper.js deleted file mode 100644 index 948f660e..00000000 --- a/lib/commands/new/wizard-helper.js +++ /dev/null @@ -1,217 +0,0 @@ -const httpClient = require('@src/clients/http-client'); -const DeployDelegate = require('@src/controllers/skill-infrastructure-controller/deploy-delegate'); -const Messenger = require('@src/view/messenger'); -const CONSTANTS = require('@src/utils/constants'); -const stringUtils = require('@src/utils/string-utils'); -const urlUtils = require('@src/utils/url-utils'); - -const ui = require('./ui'); - -module.exports = { - collectUserCreationProjectInfo -}; - -/** - * Ask for user input to create a project - * @param {Object} cmd command object - * @param {Function} callback | error - * | userInput | language - * | deploymentType - * | templateInfo | templateUrl - * | templateName - * | skillName - * | projectFolderName - */ -function collectUserCreationProjectInfo(cmd, callback) { - const userInput = {}; - _getSkillCodeLanguage(cmd, (languageErr, language) => { - if (languageErr) { - return callback(languageErr); - } - userInput.language = language; - ui.getDeploymentType(CONSTANTS.DEPLOYER_TYPE, (deploymentErr, deploymentType) => { - if (deploymentErr) { - return callback(deploymentErr); - } - userInput.deploymentType = deploymentType; - - _getSkillLocale(userInput, (localeErr, locale) => { - if (localeErr) { - return callback(localeErr); - } - userInput.locale = locale; - _getSkillDefaultRegion(userInput, (regionErr, region) => { - if (regionErr) { - return callback(regionErr); - } - userInput.region = region; - _getTemplateInfo(cmd, userInput, (templateErr, templateInfo) => { - if (templateErr) { - return callback(templateErr); - } - if (!templateInfo) { - return callback(); - } - userInput.templateInfo = templateInfo; - ui.getSkillName(userInput.templateInfo.templateUrl, (getSkillNameErr, skillName) => { - if (getSkillNameErr) { - return callback(getSkillNameErr); - } - userInput.skillName = skillName; - const suggestedProjectName = stringUtils.filterNonAlphanumeric(skillName); - ui.getProjectFolderName(suggestedProjectName, (getFolderNameErr, folderName) => { - if (getFolderNameErr) { - return callback(getFolderNameErr); - } - userInput.projectFolderName = folderName; - callback(null, userInput); - }); - }); - }); - }); - }); - }); - }); -} - -function _getSkillCodeLanguage(cmd, callback) { - if (cmd.templateUrl) { - return callback(); - } - ui.selectSkillCodeLanguage((err, res) => callback(err || null, res)); -} - -function _getSkillLocale(userInput, callback) { - if (userInput.deploymentType !== CONSTANTS.DEPLOYER_TYPE.HOSTED.NAME) { - return callback(); - } - // FIX hard coding until backend for hosted skills supports all locales - callback(null, 'en-US'); - // ui.getSkillLocale((err, res) => callback(err || null, res)); -} - -function _getSkillDefaultRegion(userInput, callback) { - if (userInput.deploymentType !== CONSTANTS.DEPLOYER_TYPE.HOSTED.NAME) { - return callback(); - } - ui.getSkillDefaultRegion((err, res) => callback(err || null, res)); -} - -/** - * Get template info for non-hosted skill - * @param {Object} cmd command object - * @param {Object} userInput user input initialization setting - * @param {Function} callback (error, templateInfo { templateUrl, templateName}) - */ -function _getTemplateInfo(cmd, userInput, callback) { - if (userInput.deploymentType === CONSTANTS.DEPLOYER_TYPE.HOSTED.NAME) { - if (userInput.language === 'Java') { - return callback('Alexa hosted skills don\'t support Java currently.'); - } - if (cmd.templateUrl) { - return callback('No custom template allowed for an Alexa hosted skill.'); - } - process.nextTick(() => { - callback(null, { templateUrl: null, templateName: null, templateBranch: null }); - }); - } else { - if (cmd.templateUrl) { - return _newWithCustomTemplate(cmd.templateUrl, cmd.debug, (templateErr, templateInfo) => { - if (templateErr) { - return callback(templateErr); - } - if (!templateInfo) { - return callback(); - } - templateInfo.templateBranch = cmd.templateBranch; - return callback(null, templateInfo); - }); - } - _newWithOfficialTemplate(userInput.language, userInput.deploymentType, cmd.debug, (templateErr, templateInfo) => { - if (templateErr) { - return callback(templateErr); - } - callback(null, templateInfo); - }); - } -} - -/** - * Retrieve templates list by deployment type and language, then ask user to select a template - * @param {Boolean} doDebug ASK CLI debug mode - * @param {Function} callback (error, userInput{ skillName, projectFolderPath }) - */ -function _newWithOfficialTemplate(language, deploymentType, doDebug, callback) { - let templateIndexUrl; - if (!deploymentType) { - templateIndexUrl = CONSTANTS.TEMPLATES.PROJECT_BY_CODE_LANGUAGE[language].TEMPLATE_INDEX; - } else { - templateIndexUrl = DeployDelegate.builtin[deploymentType].templates.language_map[language]; - } - _retrieveTemplateIndexMap(templateIndexUrl, doDebug, (httpErr, templateIndexMap) => { - if (httpErr) { - return callback(httpErr); - } - ui.getTargetTemplateName(templateIndexMap, (templateNameErr, templateName) => { - if (templateNameErr) { - return callback(templateNameErr); - } - callback(null, { templateUrl: templateIndexMap[templateName].url, templateName }); - }); - }); -} - -/** - * Ask user's deployment type, create new skill project using the template provided by custom repository url - * @param {String} templateUrl url string for the custom template - * @param {Boolean} doDebug ASK CLI debug mode - * @param {Function} callback (error, userInput{ skillName, projectFolderPath }) - */ -function _newWithCustomTemplate(templateUrl, doDebug, callback) { - if (urlUtils.isValidUrl(templateUrl)) { - _confirmDownloadIfNotOfficialTemplate(templateUrl, (confirmErr, confirmResult) => { - if (confirmErr) { - return callback(confirmErr); - } - if (!confirmResult) { - return callback(); - } - callback(null, { templateUrl, templateName: null }); - }); - } else { - process.nextTick(() => { - callback(`The provided template url ${templateUrl} is not a valid url.`); - }); - } -} - -function _retrieveTemplateIndexMap(templateIndexUrl, doDebug, callback) { - const params = { - url: templateIndexUrl, - method: CONSTANTS.HTTP_REQUEST.VERB.GET - }; - httpClient.request(params, 'getTemplatesMap', doDebug, (error, response) => { - if (error) { - return callback(`Failed to retrieve the template list.\n${error}`); - } - if (response.statusCode !== 200) { - return callback(`Failed to retrieve the template list, please see the details from the error response. -${JSON.stringify(response, null, 2)}`); - } - const templateIndexMap = JSON.parse(response.body); - callback(null, templateIndexMap); - }); -} - -function _confirmDownloadIfNotOfficialTemplate(templateUrl, callback) { - if (urlUtils.isUrlOfficialTemplate(templateUrl)) { - return process.nextTick(() => { - callback(null, true); - }); - } - Messenger.getInstance().warn(`CLI is about to download the skill template from unofficial template ${templateUrl}. \ -Please make sure you understand the source code to best protect yourself from malicious usage.`); - ui.confirmUsingUnofficialTemplate((confirmErr, confirmResult) => { - callback(confirmErr, confirmErr ? null : confirmResult); - }); -} diff --git a/lib/commands/new/wizard-helper.ts b/lib/commands/new/wizard-helper.ts new file mode 100644 index 00000000..f13d4656 --- /dev/null +++ b/lib/commands/new/wizard-helper.ts @@ -0,0 +1,241 @@ +import Messenger from "../../view/messenger"; +import {DEPLOYER_TYPE} from "../../utils/constants"; +import stringUtils from "../../utils/string-utils"; +import urlUtils from "../../utils/url-utils"; +import * as ui from "./ui"; +import {convertUserInputToFilterValue, getSampleTemplatesFromS3} from "./template-helper"; +import {getProjectFolderName} from "../../view/prompt-view"; +import {callbackError} from "../../model/callback"; +import { + NewSkillCodeLanguage, + NewSkillDeployerType, + NewSkillDeployerTypeInfo, + NewSkillRegion, + NewSkillTemplateInfo, + NewSkillUserInput, + NewSkillModelingStackTypes, + MODELING_STACK_IM, + CODE_LANGUAGE_NODEJS, + CODE_LANGUAGE_PYTHON, + CODE_LANGUAGE_JAVA, +} from "."; +import {SampleTemplate, SampleTemplatesFilter} from "../../model/sample-template"; + +export type CollectUserCreationProjectInfoCallback = (err: Error | null, input: NewSkillUserInput | undefined) => void; + +/** + * Ask for user input to create a project + * @param {Object} cmd command object + * @param {CollectUserCreationProjectInfoCallback} callback callback providing the NewSkillUserInput to the caller + */ +export async function collectUserCreationProjectInfo( + cmd: Record, + callback: CollectUserCreationProjectInfoCallback, +): Promise { + const userInput: NewSkillUserInput = {}; + + try { + // Make sure the arguments are valid + if (cmd.templateUrl && !urlUtils.isValidUrl(cmd.templateUrl)) { + throw new Error(`The provided template url ${cmd.templateUrl} is not a valid url.`); + } + + // gets the sample templates from S3 + const sampleTemplates: SampleTemplate[] = []; + await getSampleTemplatesFromS3(cmd.doDebug).then((fullSamples) => { + sampleTemplates.push(...fullSamples); + }); + const sampleTemplateFilter: SampleTemplatesFilter = new SampleTemplatesFilter(sampleTemplates); + + // MODELING STACK TYPE + await promptForModelingStackType().then((modelingStack) => (userInput.modelingStack = modelingStack)); + sampleTemplateFilter.filter("stack", convertUserInputToFilterValue(userInput.modelingStack || MODELING_STACK_IM)); + + // CODE LANGUAGE + // ignore when template url supplied + if (!cmd.templateUrl) { + await promptForCodeLanguage(sampleTemplateFilter.getSampleTemplates()).then((language) => (userInput.language = language)); + sampleTemplateFilter.filter("lang", convertUserInputToFilterValue(userInput.language || CODE_LANGUAGE_NODEJS)); + } + + // DEPLOY TYPE + await promptForDeployerType(sampleTemplateFilter.getSampleTemplates()).then( + (deploymentType) => (userInput.deploymentType = deploymentType), + ); + sampleTemplateFilter.filter("deploy", convertUserInputToFilterValue(userInput.deploymentType || DEPLOYER_TYPE.CFN.NAME)); + + if (userInput.deploymentType === DEPLOYER_TYPE.HOSTED.NAME) { + // HOSTED SKILL LOCALE + // FIX hard coding until backend for hosted skills supports locales + userInput.locale = "en-US"; + + // HOSTED SKILL AWS REGION + await promptForSkillRegion().then((region) => (userInput.region = region)); + } else { + // NON HOSTED SKILL requires selecting a sample template from the list + // TEMPLATE INFO + await promptForTemplateInfo(cmd, sampleTemplateFilter.getSampleTemplates()).then( + (templateInfo) => (userInput.templateInfo = templateInfo), + ); + } + // SKILL NAME + await promptForSkillName(userInput.templateInfo?.templateUrl || null).then((skillName) => (userInput.skillName = skillName)); + + // PROJECT FOLDER NAME + await promptForProjectFolderName(userInput.skillName || "").then( + (projectFolderName) => (userInput.projectFolderName = projectFolderName), + ); + } catch (e) { + callback(e as Error, undefined); + return; + } + callback(null, userInput); +} + +/** + * A Promise that fetches and returns the NewSkillCodeLanguage the user wants to leverage + * + * @param {SampleTemplate[]} samples remaining sample templates to select from + * @returns {Promise} a Promise that will provide a NewSkillCodeLanguage + */ +function promptForCodeLanguage(samples: SampleTemplate[]): Promise { + return new Promise((resolve, reject) => { + const remainingLanguages: Set = new Set( + samples.map((sample) => { + switch (sample.lang) { + case "node": + return CODE_LANGUAGE_NODEJS; + case "python": + return CODE_LANGUAGE_PYTHON; + case "java": + return CODE_LANGUAGE_JAVA; + } + }), + ); + + ui.selectSkillCodeLanguage(Array.from(remainingLanguages), (error, language) => (error ? reject(error) : resolve(language))); + }); +} + +/** + * A Promise that fetches and returns the NewSkillDeployerType the user wants to leverage + * + * @param {boolean} hasTemplateUrl true or false if the templateUrl was specified as a command line argument + * @returns {Promise} a Promise that will provide a NewSkillDeployerType + */ +function promptForDeployerType(samples: SampleTemplate[]): Promise { + return new Promise((resolve, reject) => { + const remainingDeployerTypes: Set = new Set( + samples.map((sample) => { + switch (sample.deploy) { + case "lambda": + return DEPLOYER_TYPE.LAMBDA; + case "cfn": + return DEPLOYER_TYPE.CFN; + case "hosted": + return DEPLOYER_TYPE.HOSTED; + case "self": + return DEPLOYER_TYPE.SELF_HOSTED; + } + }), + ); + + ui.getDeploymentType(Array.from(remainingDeployerTypes), (error, deploymentType) => (error ? reject(error) : resolve(deploymentType))); + }); +} + +/** + * A Promise that fetches and returns the NewSkillModelingStackTypes the user wants the samples to use. + * i.e. interaction-model vs alexa-conversations + * + * @returns {Promise} a Promise that will provide a Modeling Stack + */ +function promptForModelingStackType(): Promise { + return new Promise((resolve, reject) => { + ui.getModelingStackType((error, modelingStack) => (error ? reject(error) : resolve(modelingStack))); + }); +} + +/** + * A Promise that fetches and returns the default AWS Region to use for deploying the Alexa hosted skill + * + * @returns {Promise} Promises to return the default AWS Region the user wants to deploy the skill to + */ +function promptForSkillRegion(): Promise { + return new Promise((resolve, reject) => { + ui.getSkillDefaultRegion((error, region) => (error ? reject(error) : resolve(region))); + }); +} + +/** + * A Promise that fetches and returns a string specifying the new skill name to use. + * + * if a templateUrl is provided the user will be presented with a potentially better suited + * skill name default option instead of the generic hello world + * + * @param {string | null} templateUrl the template url to use for attempting to get a skillname instead of the default hello world + */ +function promptForSkillName(templateUrl: string | null): Promise { + return new Promise((resolve, reject) => { + ui.getSkillName(templateUrl, (error, skillName) => (error ? reject(error) : resolve(skillName))); + }); +} + +/** + * A promise that fetches and returns a string specifying the new skill project folder name to use/create + * + * @param {string} skillName The name of the skill provided by the customer + * @returns {Promise} Promises to return the customer provided input string specifying the new skill project folder name to use/create + */ +function promptForProjectFolderName(skillName: string): Promise { + return new Promise((resolve, reject) => { + getProjectFolderName(stringUtils.filterNonAlphanumeric(skillName), (error, folderName) => + error ? reject(error) : resolve(folderName), + ); + }); +} + +/** + * A Promise that fetches the NewSkillTemplateInfo for non-hosted skill + * also confirms download for non Alexa official git repos + * + * @param {Record} cmd command object + * @param {SampleTemplate[]} samples the unfiltered skill samples templates to resolve + * @returns {Promise} a Promise that provides the New Skill Template Info + */ +async function promptForTemplateInfo(cmd: Record, samples: SampleTemplate[]): Promise { + return new Promise((resolve, reject) => { + if (!cmd.templateUrl) { + ui.getTargetTemplateName(samples, (err: callbackError, sampleTemplate: SampleTemplate | undefined) => { + err + ? reject(err) + : resolve({ + templateUrl: sampleTemplate?.url, + templateName: sampleTemplate?.name, + templateBranch: sampleTemplate?.branch, + }); + }); + + // handle when templateUrl is present in the the command line arguments + } else { + const templateInfoFromCmd: NewSkillTemplateInfo = { + templateUrl: cmd.templateUrl, + ...(cmd.templateName ? {templateName: cmd.templateName} : {}), + ...(cmd.templateBranch ? {templateBranch: cmd.templateBranch} : {}), + }; + + // no warnings/confirmation of download required for official alexa templates + if (urlUtils.isUrlOfficialTemplate(cmd.templateUrl)) { + resolve(templateInfoFromCmd); + } else { + Messenger.getInstance().warn( + `CLI is about to download the skill template from unofficial template ${cmd.templateUrl}. ` + + "Please make sure you understand the source code to best protect yourself from malicious usage.", + ); + ui.confirmUsingUnofficialTemplate((confirmErr, confirmResult) => { + confirmErr || !confirmResult ? reject(confirmErr) : resolve(templateInfoFromCmd); + }); + } + } + }); +} diff --git a/lib/commands/option-model.json b/lib/commands/option-model.json index 5538ad9a..a03a9ebf 100644 --- a/lib/commands/option-model.json +++ b/lib/commands/option-model.json @@ -23,6 +23,12 @@ "alias": null, "stringInput": "NONE" }, + "skip-validation": { + "name": "skip-validation", + "description": "Force the ASK CLI to generate ASKIR without validation", + "alias": null, + "stringInput": "NONE" + }, "target": { "name": "target", "description": "Specify which skill project resource to deploy.\n[ENUM]: skill-metadata,skill-infrastructure", @@ -49,7 +55,13 @@ "name": "skill-id", "description": "Skill id", "alias": "s", - "stringInput": "REQUIRED" + "stringInput": "REQUIRED", + "rule": [ + { + "type": "REGEX", + "regex": "^amzn\\d\\.ask\\.skill\\.\\w{8}-\\w{4}-\\w{4}-\\w{4}-\\w{12}$" + } + ] }, "replay": { "name": "replay", @@ -59,9 +71,14 @@ }, "save-skill-io": { "name": "save-skill-io", - "description": "Specify an output file to write simulation invocation requests and responses.", + "description": "Specify an output file to write simulation invocation requests and responses", "stringInput": "REQUIRED" }, + "verbose": { + "name": "verbose", + "description": "(beta) Display explanation for the request and response while simulating skills", + "stringInput": "NONE" + }, "hosted-skill-id": { "name": "hosted-skill-id", "description": "skill-id for the Alexa hosted skill", @@ -73,26 +90,35 @@ "description": "Skill stage", "alias": "g", "stringInput": "REQUIRED", - "rule": [{ - "type": "ENUM", - "values": ["development", "live", "certification"] - }] + "rule": [ + { + "type": "ENUM", + "values": ["development", "live", "certification"] + } + ] }, "locale": { "name": "locale", "description": "Locale value for the resource", "alias": "l", "stringInput": "REQUIRED", - "rule": [{ - "type": "REGEX", - "regex": "^[a-z]{2}-[A-Z]{2}$" - }] + "rule": [ + { + "type": "REGEX", + "regex": "^[a-z]{2}-[A-Z]{2}$" + } + ] }, "templateUrl": { "name": "template-url", "description": "Url for the template to be used with", "alias": null, - "stringInput": "REQUIRED" + "stringInput": "REQUIRED", + "rule": [ + { + "type": "URL" + } + ] }, "templateBranch": { "name": "template-branch", @@ -105,18 +131,22 @@ "description": "Path to the target file input", "alias": "f", "stringInput": "REQUIRED", - "rule": [{ - "type": "FILE_PATH" - }] + "rule": [ + { + "type": "FILE_PATH" + } + ] }, "max-results": { "name": "max-results", "description": "Max results returned by the request", "alias": null, "stringInput": "REQUIRED", - "rule": [{ - "type": "INTEGER" - }] + "rule": [ + { + "type": "INTEGER" + } + ] }, "next-token": { "name": "next-token", @@ -178,9 +208,11 @@ "name": "debug-port", "description": "Port at which the debug process will run.", "stringInput": "REQUIRED", - "rule": [{ - "type": "INTEGER" - }] + "rule": [ + { + "type": "INTEGER" + } + ] }, "wait-for-attach": { "name": "wait-for-attach", @@ -191,10 +223,12 @@ "name": "region", "description": "Sets the run region for the session. Accepted values are - [EU, FE, NA]. Defaults to NA. To know more about which region is right for you refer - https://developer.amazon.com/en-US/docs/alexa/ask-toolkit/vs-code-testing-simulator.html#prepare", "stringInput": "REQUIRED", - "rule": [{ - "type": "ENUM", - "values": ["NA", "FE", "EU"] - }] + "rule": [ + { + "type": "ENUM", + "values": ["NA", "FE", "EU"] + } + ] }, "watch": { "name": "watch", diff --git a/lib/commands/option-validator.js b/lib/commands/option-validator.js deleted file mode 100644 index b2b08460..00000000 --- a/lib/commands/option-validator.js +++ /dev/null @@ -1,114 +0,0 @@ -const R = require('ramda'); -const fs = require('fs'); -const Messenger = require('@src/view/messenger'); -const path = require('path'); - -module.exports = { - validateRequiredOption, - validateOptionString, - validateOptionRules, -}; - -const optionRuleValidatorMap = { - ENUM(options, key, ruleModel) { - assertNotNullForRuleModel(ruleModel, 'values'); - const possibleValues = ruleModel.values; - if (!possibleValues.includes(options[key])) { - throw (`Value must be in (${possibleValues.join(', ')}).`); - } - }, - REGEX(options, key, ruleModel) { - assertNotNullForRuleModel(ruleModel, 'regex'); - const regex = new RegExp(ruleModel.regex); - if (!regex.test(options[key])) { - throw (`Input value (${options[key]}) doesn't match REGEX rule ${ruleModel.regex}.`); - } - }, - FILE_PATH(options, key, ruleModel) { - try { - fs.accessSync(options[key], fs.constants.R_OK); - } catch (e) { - if (e.code === 'ENOENT') { - throw 'File does not exist with the given path.'; - } else { - throw 'The provided file must have read permission.'; - } - } - - if (ruleModel.extension) { - if (!ruleModel.extension.includes(path.extname(options[key]))) { - throw `File extension is not of type ${ruleModel.extension}.`; - } - } - }, - NUMBER(options, key) { - const num = Number(options[key]); - - if (Number.isNaN(num)) { - throw 'Input should be a number.'; - } - }, - INTEGER(options, key) { - optionRuleValidatorMap.NUMBER(options, key); - - const num = Number(options[key]); - - if (!Number.isInteger(num)) { - throw 'Input number should be an integer.'; - } - } -}; - -function assertNotNullForRuleModel(obj, key) { - // TODO add unit test after logger integration - if (obj[key] == null) { - Messenger.getInstance().fatal(new Error(`Option rule model of type "${obj.type}" requires field "${key}" to be set!`)); - Messenger.getInstance().dispose(); - process.exit(1); - } -} - -/** - * Validate that option value has been set - * @param options - * @param key - */ -function validateRequiredOption(options, key) { - if (R.isNil(options[key])) { - throw ('Field is required and must be set.'); - } -} - -/** - * Validate that option value is valid non-empty string - * @param options - * @param key - */ -function validateOptionString(options, key) { - if (!R.is(String, options[key])) { - throw ('Must be a string.'); - } - if (R.isEmpty(options[key].trim())) { - throw ('Value must not be empty.'); - } -} - -/** - * Validate option value against specific rules - * @param options - * @param key - * @param rules - */ -function validateOptionRules(options, key, rules) { - // if no rule is associated with current option key, fallback to no-op - if (rules && rules.length) { - for (const rule of rules) { - const ruleValidator = optionRuleValidatorMap[rule.type]; - - // check if there is a validator for given rule type. If not, fallback to no-op - if (ruleValidator) { - ruleValidator(options, key, rule); - } - } - } -} diff --git a/lib/commands/option-validator.ts b/lib/commands/option-validator.ts new file mode 100644 index 00000000..90ec6f63 --- /dev/null +++ b/lib/commands/option-validator.ts @@ -0,0 +1,153 @@ +const R = require("ramda"); +const fs = require("fs"); +const urlUtils = require("../utils/url-utils"); +import Messenger from "../view/messenger"; +import path from "path"; + +export {validateRequiredOption, validateOptionString, validateOptionRules}; + +export interface OptionModelEntry { + name: string; + description: string; + alias?: string | null; + stringInput: string; + rule?: OptionModelRule[]; +} + +export interface Enum { + type: "ENUM"; + values: string[]; +} + +export interface Regex { + type: "REGEX"; + regex: string | RegExp; +} + +export interface FilePath { + type: "FILE_PATH"; + extension?: string; +} + +export type OptionModelRule = + | Enum + | Regex + | FilePath + | { + type: "NUMBER" | "INTEGER" | "URL"; + }; + +export type OptionModel = Record; + +export type OptionRuleValidatorMap = { + [key in OptionModelRule["type"]]: (options: any, key: any, rule?: T) => void; +}; + +export const optionRuleValidatorMap: OptionRuleValidatorMap = { + ENUM: (options, key, ruleModel) => { + assertNotNullForRuleModel(ruleModel, "values"); + const possibleValues = ruleModel.values; + if (!possibleValues.includes(options[key])) { + throw `Value must be in (${possibleValues.join(", ")}).`; + } + }, + REGEX(options, key, ruleModel) { + assertNotNullForRuleModel(ruleModel, "regex"); + const regex = new RegExp(ruleModel.regex); + if (!regex.test(options[key])) { + throw `Input value (${options[key]}) doesn't match REGEX rule ${ruleModel.regex}.`; + } + }, + FILE_PATH(options, key, ruleModel?: FilePath) { + try { + fs.accessSync(options[key], fs.constants.R_OK); + } catch (e) { + if ((e as any).code === "ENOENT") { + throw "File does not exist with the given path."; + } else { + throw "The provided file must have read permission."; + } + } + + if (ruleModel && (ruleModel).extension) { + if (!(ruleModel).extension?.includes(path.extname(options[key]))) { + throw `File extension is not of type ${(ruleModel).extension}.`; + } + } + }, + NUMBER(options, key) { + const num = Number(options[key]); + + if (Number.isNaN(num)) { + throw "Input should be a number."; + } + }, + INTEGER(options, key) { + optionRuleValidatorMap.NUMBER(options, key); + + const num = Number(options[key]); + + if (!Number.isInteger(num)) { + throw "Input number should be an integer."; + } + }, + URL(options, key) { + if (!urlUtils.isValidUrl(options[key])) { + throw "Input should be a URL."; + } + }, +}; + +function assertNotNullForRuleModel(obj: Partial | undefined, key: keyof T): asserts obj is T { + // TODO add unit test after logger integration + if (!obj || !(obj as any)[key]) { + obj && Messenger.getInstance().fatal(new Error(`Option rule model of type "${obj.type}" requires field "${String(key)}" to be set!`)); + Messenger.getInstance().dispose(); + process.exit(1); + } +} + +/** + * Validate that option value has been set + * @param options + * @param key + */ +function validateRequiredOption(options: Record, key: string) { + if (!options[key]) { + throw "Field is required and must be set."; + } +} + +/** + * Validate that option value is valid non-empty string + * @param options + * @param key + */ +function validateOptionString(options: Record, key: string) { + if (!R.is(String, options[key])) { + throw "Must be a string."; + } + if (R.isEmpty(options[key].trim())) { + throw "Value must not be empty."; + } +} + +/** + * Validate option value against specific rules + * @param options + * @param key + * @param rules + */ +function validateOptionRules(options: Record, key: string, rules: OptionModelRule[] | undefined) { + // if no rule is associated with current option key, fallback to no-op + if (rules && rules.length) { + for (const rule of rules) { + const ruleValidator = optionRuleValidatorMap[rule.type] as any; + + // check if there is a validator for given rule type. If not, fallback to no-op + if (ruleValidator) { + ruleValidator(options, key, rule); + } + } + } +} diff --git a/lib/commands/run/helper.js b/lib/commands/run/helper.js index ddfd33b5..7e6412f5 100644 --- a/lib/commands/run/helper.js +++ b/lib/commands/run/helper.js @@ -1,91 +1,86 @@ -const fs = require('fs'); -const ResourcesConfig = require('@src/model/resources-config'); -const CONSTANTS = require('@src/utils/constants'); -const stringUtils = require('@src/utils/string-utils'); -const CliError = require('@src/exceptions/cli-error'); -const NodejsRunFlow = require('./run-flow/nodejs-run'); -const PythonRunFlow = require('./run-flow/python-run'); -const JavaRunFlow = require('./run-flow/java-run'); +const fs = require("fs"); +const ResourcesConfig = require("../../model/resources-config"); +const CONSTANTS = require("../../utils/constants"); +const stringUtils = require("../../utils/string-utils"); +const CliError = require("../../exceptions/cli-error"); +const NodejsRunFlow = require("./run-flow/nodejs-run"); +const PythonRunFlow = require("./run-flow/python-run"); +const JavaRunFlow = require("./run-flow/java-run"); -const RUN_FLOWS = [ - JavaRunFlow, - NodejsRunFlow, - PythonRunFlow -]; +const RUN_FLOWS = [JavaRunFlow, NodejsRunFlow, PythonRunFlow]; module.exports = { - getHostedSkillInvocationInfo, - getNonHostedSkillInvocationInfo, - getSkillCodeFolderName, - getNormalisedRuntime, - selectRunFlowClass, - getSkillFlowInstance + getHostedSkillInvocationInfo, + getNonHostedSkillInvocationInfo, + getSkillCodeFolderName, + getNormalisedRuntime, + selectRunFlowClass, + getSkillFlowInstance, }; function getHostedSkillInvocationInfo(runtime) { - return CONSTANTS.HOSTED_SKILL.RUN.INVOCATION_INFO[runtime]; + return CONSTANTS.HOSTED_SKILL.RUN.INVOCATION_INFO[runtime]; } function getNonHostedSkillInvocationInfo(runtime, handler, skillCodeFolderName) { - if (!stringUtils.isNonBlankString(runtime)) { - throw new CliError('Missing runtime info in ' - + `resource file ${CONSTANTS.FILE_PATH.ASK_RESOURCES_JSON_CONFIG}.`); - } - if (!stringUtils.isNonBlankString(handler)) { - throw new CliError('Missing handler info ' - + `in resource file ${CONSTANTS.FILE_PATH.ASK_RESOURCES_JSON_CONFIG}.`); - } - if (runtime === CONSTANTS.RUNTIME.JAVA) { - return { handlerName: handler, skillCodeFolderName }; - } - const handlerInfo = handler.split('.'); - const handlerName = handlerInfo.pop(); - const skillFileName = handlerInfo.pop(); - return { handlerName, skillFileName, skillCodeFolderName }; + if (!stringUtils.isNonBlankString(runtime)) { + throw new CliError("Missing runtime info in " + `resource file ${CONSTANTS.FILE_PATH.ASK_RESOURCES_JSON_CONFIG}.`); + } + if (!stringUtils.isNonBlankString(handler)) { + throw new CliError("Missing handler info " + `in resource file ${CONSTANTS.FILE_PATH.ASK_RESOURCES_JSON_CONFIG}.`); + } + if (runtime === CONSTANTS.RUNTIME.JAVA) { + return {handlerName: handler, skillCodeFolderName}; + } + const handlerInfo = handler.split("."); + const handlerName = handlerInfo.pop(); + const skillFileName = handlerInfo.pop(); + return {handlerName, skillFileName, skillCodeFolderName}; } function getSkillCodeFolderName(profile, skillCodeRegion) { - const userRegionSkillCodeFolderName = ResourcesConfig.getInstance().getCodeSrcByRegion(profile, skillCodeRegion); - const skillCodeFolderName = ((!stringUtils.isNonBlankString(userRegionSkillCodeFolderName)) - && (userRegionSkillCodeFolderName !== CONSTANTS.ALEXA.REGION.DEFAULT)) - ? ResourcesConfig.getInstance().getCodeSrcByRegion(profile, CONSTANTS.ALEXA.REGION.DEFAULT) : userRegionSkillCodeFolderName; - if (!stringUtils.isNonBlankString(skillCodeFolderName)) { - throw new CliError(`Invalid code setting in region ${skillCodeRegion}. "src" must be set if you want to run ` - + 'the skill code with skill package.'); - } - if (!fs.existsSync(skillCodeFolderName)) { - throw new CliError(`Invalid code setting in region ${skillCodeRegion}.` - + ` File doesn't exist for code src: ${skillCodeFolderName}.`); - } - return skillCodeFolderName; + const userRegionSkillCodeFolderName = ResourcesConfig.getInstance().getCodeSrcByRegion(profile, skillCodeRegion); + const skillCodeFolderName = + !stringUtils.isNonBlankString(userRegionSkillCodeFolderName) && userRegionSkillCodeFolderName !== CONSTANTS.ALEXA.REGION.DEFAULT + ? ResourcesConfig.getInstance().getCodeSrcByRegion(profile, CONSTANTS.ALEXA.REGION.DEFAULT) + : userRegionSkillCodeFolderName; + if (!stringUtils.isNonBlankString(skillCodeFolderName)) { + throw new CliError( + `Invalid code setting in region ${skillCodeRegion}. "src" must be set if you want to run ` + "the skill code with skill package.", + ); + } + if (!fs.existsSync(skillCodeFolderName)) { + throw new CliError(`Invalid code setting in region ${skillCodeRegion}.` + ` File doesn't exist for code src: ${skillCodeFolderName}.`); + } + return skillCodeFolderName; } function getNormalisedRuntime(runtime) { - if (runtime.includes(CONSTANTS.RUNTIME.NODE)) { - return CONSTANTS.RUNTIME.NODE; - } - if (runtime.includes(CONSTANTS.RUNTIME.PYTHON)) { - return CONSTANTS.RUNTIME.PYTHON; - } - if (runtime.includes(CONSTANTS.RUNTIME.JAVA)) { - return CONSTANTS.RUNTIME.JAVA; - } - throw new CliError(`Runtime - ${runtime} is not supported.`); + if (runtime.includes(CONSTANTS.RUNTIME.NODE)) { + return CONSTANTS.RUNTIME.NODE; + } + if (runtime.includes(CONSTANTS.RUNTIME.PYTHON)) { + return CONSTANTS.RUNTIME.PYTHON; + } + if (runtime.includes(CONSTANTS.RUNTIME.JAVA)) { + return CONSTANTS.RUNTIME.JAVA; + } + throw new CliError(`Runtime - ${runtime} is not supported.`); } function selectRunFlowClass(runtime) { - return RUN_FLOWS.find(flow => flow.canHandle(runtime)); + return RUN_FLOWS.find((flow) => flow.canHandle(runtime)); } function getSkillFlowInstance(runtime, skillInvocationInfo, waitForAttach, debugPort, token, skillId, runRegion, watch) { - const RunFlow = this.selectRunFlowClass(runtime); - return new RunFlow({ - skillInvocationInfo, - waitForAttach, - debugPort, - token, - skillId, - runRegion, - watch - }); + const RunFlow = this.selectRunFlowClass(runtime); + return new RunFlow({ + skillInvocationInfo, + waitForAttach, + debugPort, + token, + skillId, + runRegion, + watch, + }); } diff --git a/lib/commands/run/index.js b/lib/commands/run/index.js deleted file mode 100644 index 0518107a..00000000 --- a/lib/commands/run/index.js +++ /dev/null @@ -1,164 +0,0 @@ -const path = require('path'); -const SmapiClient = require('@src/clients/smapi-client'); -const { AbstractCommand } = require('@src/commands/abstract-command'); -const optionModel = require('@src/commands/option-model'); -const AuthorizationController = require('@src/controllers/authorization-controller'); -const ResourcesConfig = require('@src/model/resources-config'); -const CONSTANTS = require('@src/utils/constants'); -const profileHelper = require('@src/utils/profile-helper'); -const jsonView = require('@src/view/json-view'); -const stringUtils = require('@src/utils/string-utils'); -const Messenger = require('@src/view/messenger'); -const CliError = require('@src/exceptions/cli-error'); -const helper = require('./helper'); - -class RunCommand extends AbstractCommand { - name() { - return 'run'; - } - - description() { - return 'Starts a local instance of your project as the skill endpoint.' - + ' Automatically re-routes development requests and responses between the Alexa service and your local instance.'; - } - - requiredOptions() { - return []; - } - - optionalOptions() { - return ['debug-port', 'wait-for-attach', 'watch', 'region', 'profile', 'debug']; - } - - handle(cmd, cb) { - const debugPort = cmd.debugPort || CONSTANTS.RUN.DEFAULT_DEBUG_PORT; - const skillCodeRegion = cmd.region || CONSTANTS.ALEXA.REGION.NA; - const runRegion = cmd.region || CONSTANTS.ALEXA.REGION.NA; - const watch = cmd.watch || false; - let skillId, profile; - - try { - profile = profileHelper.runtimeProfile(cmd.profile); - new ResourcesConfig(path.join(process.cwd(), CONSTANTS.FILE_PATH.ASK_RESOURCES_JSON_CONFIG)); - skillId = ResourcesConfig.getInstance().getSkillId(profile); - if (!stringUtils.isNonBlankString(skillId)) { - throw new CliError(`Failed to obtain skill-id for the given profile - ${profile}` - + '. Please deploy you skill project first.'); - } - } catch (error) { - Messenger.getInstance().error(error); - cb(error); - } - - this._getAccessTokenForProfile(profile, cmd.debug, (tokenErr, token) => { - if (tokenErr) { - Messenger.getInstance().error(tokenErr); - return cb(tokenErr); - } - this._getSkillRunFlow(skillId, profile, skillCodeRegion, cmd.waitForAttach, watch, cmd.debug, debugPort, token, - runRegion, (err, runFlowInstance) => { - if (err) { - Messenger.getInstance().error(err); - return cb(err); - } - Messenger.getInstance() - .info('\n*****Once the session is successfully started, ' - + 'you can use `ask dialog` to make simulation requests to your local skill code*****\n'); - if (cmd.waitForAttach) { - Messenger.getInstance() - .info(`\n*****Debugging session will wait until inspector is attached at port - ${debugPort}*****\n`); - } - runFlowInstance.execCommand(); - }); - }); - } - - _getAccessTokenForProfile(profile, debug, callback) { - const authorizationController = new AuthorizationController({ - auth_client_type: 'LWA', - doDebug: debug - }); - authorizationController.tokenRefreshAndRead(profile, (tokenErr, token) => { - if (tokenErr) { - return callback(tokenErr); - } - callback(null, token); - }); - } - - _getHostedSkillRuntime(smapiClient, skillId, callback) { - smapiClient.skill.alexaHosted.getAlexaHostedSkillMetadata(skillId, (err, response) => { - if (err) { - return callback(err); - } - if (response.statusCode >= 300) { - const error = jsonView.toString(response.body); - return callback(error); - } - try { - if (!response.body) { - throw new CliError('Received an empty response body from getAlexaHostedSkillMetadata'); - } - const { runtime } = response.body.alexaHosted; - if (!stringUtils.isNonBlankString(runtime)) { - throw new CliError(`Unable to determine runtime of the hosted skill - ${skillId}`); - } - callback(null, helper.getNormalisedRuntime(runtime)); - } catch (error) { - return callback(error); - } - }); - } - - _getSkillRunFlow(skillId, profile, skillCodeRegion, waitForAttach, watch, debug, debugPort, token, runRegion, callback) { - let skillFlowInstance; - if (this._filterAlexaHostedSkill(profile)) { - const smapiClient = new SmapiClient({ - profile, - doDebug: debug - }); - this._getHostedSkillRuntime(smapiClient, skillId, (err, runtime) => { - if (err) { - return callback(err); - } - try { - skillFlowInstance = helper.getSkillFlowInstance(runtime, helper.getHostedSkillInvocationInfo(runtime), - waitForAttach, debugPort, token, skillId, runRegion, watch); - } catch (error) { - return callback(error); - } - callback(null, skillFlowInstance); - }); - } else { - try { - const skillCodeFolderName = helper.getSkillCodeFolderName(profile, skillCodeRegion); - Messenger.getInstance().info(`Skill code folder name select for the run session: ${skillCodeFolderName}`); - const userConfig = ResourcesConfig.getInstance().getSkillInfraUserConfig(profile); - if (!userConfig) { - return callback(new CliError('Failed to obtain userConfig from project ' - + `resource file ${CONSTANTS.FILE_PATH.ASK_RESOURCES_JSON_CONFIG}`)); - } - const { runtime, handler } = userConfig; - if (!runtime) { - throw new CliError( - `Failed to obtain runtime from userConfig in project resource file ${CONSTANTS.FILE_PATH.ASK_RESOURCES_JSON_CONFIG}`, - ); - } - const normalisedRuntime = helper.getNormalisedRuntime(runtime); - skillFlowInstance = helper.getSkillFlowInstance(normalisedRuntime, - helper.getNonHostedSkillInvocationInfo(normalisedRuntime, handler, skillCodeFolderName), - waitForAttach, debugPort, token, skillId, runRegion, watch); - } catch (err) { - return callback(err); - } - callback(null, skillFlowInstance); - } - } - - _filterAlexaHostedSkill(profile) { - return (ResourcesConfig.getInstance().getSkillInfraType(profile) === CONSTANTS.DEPLOYER_TYPE.HOSTED.NAME); - } -} - -module.exports = RunCommand; -module.exports.createCommand = new RunCommand(optionModel).createCommand(); diff --git a/lib/commands/run/index.ts b/lib/commands/run/index.ts new file mode 100644 index 00000000..dbaccfe0 --- /dev/null +++ b/lib/commands/run/index.ts @@ -0,0 +1,182 @@ +import path from "path"; +import SmapiClient, {ISmapiClient} from "../../clients/smapi-client"; +import {AbstractCommand} from "../abstract-command"; +import optionModel from "../../commands/option-model.json"; +import AuthorizationController from "../../controllers/authorization-controller"; +import ResourcesConfig from "../../model/resources-config"; +import CONSTANTS from "../../utils/constants"; +import profileHelper from "../../utils/profile-helper"; +import jsonView from "../../view/json-view"; +import stringUtils from "../../utils/string-utils"; +import Messenger from "../../view/messenger"; +import CliError from "../../exceptions/cli-error"; +import helper from "./helper"; +import {OptionModel} from "../option-validator"; + +export default class RunCommand extends AbstractCommand { + name() { + return "run"; + } + + description() { + return ( + "Starts a local instance of your project as the skill endpoint." + + " Automatically re-routes development requests and responses between the Alexa service and your local instance." + ); + } + + requiredOptions() { + return []; + } + + optionalOptions() { + return ["debug-port", "wait-for-attach", "watch", "region", "profile", "debug"]; + } + + async handle(cmd: Record): Promise { + const debugPort = cmd.debugPort || CONSTANTS.RUN.DEFAULT_DEBUG_PORT; + const skillCodeRegion = cmd.region || CONSTANTS.ALEXA.REGION.NA; + const runRegion = cmd.region || CONSTANTS.ALEXA.REGION.NA; + const watch = cmd.watch || false; + let skillId, profile; + + try { + profile = profileHelper.runtimeProfile(cmd.profile); + new ResourcesConfig(path.join(process.cwd(), CONSTANTS.FILE_PATH.ASK_RESOURCES_JSON_CONFIG)); + skillId = ResourcesConfig.getInstance().getSkillId(profile); + if (!stringUtils.isNonBlankString(skillId)) { + throw new CliError(`Failed to obtain skill-id for the given profile - ${profile}` + ". Please deploy you skill project first."); + } + } catch (error) { + Messenger.getInstance().error(error); + throw error; + } + + try { + const token = await this._getAccessTokenForProfile(profile, cmd.debug); + const runFlowInstance = await this._getSkillRunFlow( + skillId, + profile, + skillCodeRegion, + cmd.waitForAttach, + watch, + cmd.debug, + debugPort, + token, + runRegion, + ); + Messenger.getInstance().info( + "\n*****Once the session is successfully started, " + + "you can use `ask dialog` to make simulation requests to your local skill code*****\n", + ); + if (cmd.waitForAttach) { + Messenger.getInstance().info(`\n*****Debugging session will wait until inspector is attached at port - ${debugPort}*****\n`); + } + runFlowInstance.execCommand(); + } catch (tokenErr) { + Messenger.getInstance().error(tokenErr); + throw tokenErr; + } + } + + _getAccessTokenForProfile(profile: string, debug: string): Promise { + const authorizationController = new AuthorizationController({ + auth_client_type: "LWA", + doDebug: debug, + }); + return new Promise((resolve, reject) => { + authorizationController.tokenRefreshAndRead(profile, (tokenErr: any, token: string) => { + if (tokenErr) { + return reject(tokenErr); + } + resolve(token); + }); + }); + } + + _getHostedSkillRuntime(smapiClient: ISmapiClient, skillId: string): Promise { + return new Promise((resolve, reject) => { + smapiClient.skill.alexaHosted.getAlexaHostedSkillMetadata(skillId, (err: any, response: any) => { + if (err) { + return reject(err); + } + if (response.statusCode >= 300) { + const error = jsonView.toString(response.body); + return reject(error); + } + try { + if (!response.body) { + throw new CliError("Received an empty response body from getAlexaHostedSkillMetadata"); + } + const {runtime} = response.body.alexaHosted; + if (!stringUtils.isNonBlankString(runtime)) { + throw new CliError(`Unable to determine runtime of the hosted skill - ${skillId}`); + } + resolve(helper.getNormalisedRuntime(runtime)); + } catch (error) { + return reject(error); + } + }); + }); + } + + async _getSkillRunFlow( + skillId: string, + profile: string, + skillCodeRegion: string, + waitForAttach: boolean, + watch: boolean, + debug: boolean, + debugPort: string, + token: string, + runRegion: string, + ) { + if (this._filterAlexaHostedSkill(profile)) { + const smapiClient = new SmapiClient({ + profile, + doDebug: debug, + }); + const runtime = await this._getHostedSkillRuntime(smapiClient, skillId); + return helper.getSkillFlowInstance( + runtime, + helper.getHostedSkillInvocationInfo(runtime), + waitForAttach, + debugPort, + token, + skillId, + runRegion, + watch, + ); + } else { + const skillCodeFolderName = helper.getSkillCodeFolderName(profile, skillCodeRegion); + Messenger.getInstance().info(`Skill code folder name select for the run session: ${skillCodeFolderName}`); + const userConfig = ResourcesConfig.getInstance().getSkillInfraUserConfig(profile); + if (!userConfig) { + throw new CliError("Failed to obtain userConfig from project " + `resource file ${CONSTANTS.FILE_PATH.ASK_RESOURCES_JSON_CONFIG}`); + } + const {runtime, handler} = userConfig; + if (!runtime) { + throw new CliError( + `Failed to obtain runtime from userConfig in project resource file ${CONSTANTS.FILE_PATH.ASK_RESOURCES_JSON_CONFIG}`, + ); + } + const normalisedRuntime = helper.getNormalisedRuntime(runtime); + return helper.getSkillFlowInstance( + normalisedRuntime, + helper.getNonHostedSkillInvocationInfo(normalisedRuntime, handler, skillCodeFolderName), + waitForAttach, + debugPort, + token, + skillId, + runRegion, + watch, + ); + } + } + + _filterAlexaHostedSkill(profile: string) { + return ResourcesConfig.getInstance().getSkillInfraType(profile) === CONSTANTS.DEPLOYER_TYPE.HOSTED.NAME; + } +} + +export const createCommand = new RunCommand(optionModel as OptionModel).createCommand(); diff --git a/lib/commands/run/run-flow/abstract-run-flow.js b/lib/commands/run/run-flow/abstract-run-flow.js index 721e8d2a..e351611b 100644 --- a/lib/commands/run/run-flow/abstract-run-flow.js +++ b/lib/commands/run/run-flow/abstract-run-flow.js @@ -1,17 +1,17 @@ -const nodemon = require('nodemon'); +const nodemon = require("nodemon"); class AbstractRunFlow { - constructor(execConfig) { - this.execConfig = execConfig; - } + constructor(execConfig) { + this.execConfig = execConfig; + } - execCommand() { - nodemon(this.execConfig); - } + execCommand() { + nodemon(this.execConfig); + } - getExecConfig() { - return this.execConfig; - } + getExecConfig() { + return this.execConfig; + } } module.exports = AbstractRunFlow; diff --git a/lib/commands/run/run-flow/java-run.js b/lib/commands/run/run-flow/java-run.js index c21009ad..0da83d4f 100644 --- a/lib/commands/run/run-flow/java-run.js +++ b/lib/commands/run/run-flow/java-run.js @@ -1,27 +1,29 @@ -const CONSTANTS = require('@src/utils/constants'); -const AbstractRunFlow = require('./abstract-run-flow'); +const CONSTANTS = require("../../../utils/constants"); +const AbstractRunFlow = require("./abstract-run-flow"); class JavaRunFlow extends AbstractRunFlow { - static canHandle(runtime) { - return runtime === CONSTANTS.RUNTIME.JAVA; - } + static canHandle(runtime) { + return runtime === CONSTANTS.RUNTIME.JAVA; + } - constructor({ skillInvocationInfo, waitForAttach, debugPort, token, skillId, runRegion, watch }) { - let execCmd = `cd ${skillInvocationInfo.skillCodeFolderName}; mvn exec:exec -Dexec.executable=java -Dexec.args=` - + '"-classpath %classpath com.amazon.ask.localdebug.LocalDebuggerInvoker ' - + `--accessToken ${token} --skillId ${skillId} --skillStreamHandlerClass ${skillInvocationInfo.handlerName} --region ${runRegion}"`; - if (waitForAttach) { - execCmd = `cd ${skillInvocationInfo.skillCodeFolderName}; mvn exec:exec -Dexec.executable=java -Dexec.args=` - + `"-classpath %classpath -Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=${debugPort} ` - + 'com.amazon.ask.localdebug.LocalDebuggerInvoker ' - + `--accessToken ${token} --skillId ${skillId} --region ${runRegion} --skillStreamHandlerClass ${skillInvocationInfo.handlerName}"`; - } - super({ - exec: execCmd, - ext: 'java, xml', - watch: watch ? `${skillInvocationInfo.skillCodeFolderName}` : watch - }); + constructor({skillInvocationInfo, waitForAttach, debugPort, token, skillId, runRegion, watch}) { + let execCmd = + `cd ${skillInvocationInfo.skillCodeFolderName}; mvn exec:exec -Dexec.executable=java -Dexec.args=` + + '"-classpath %classpath com.amazon.ask.localdebug.LocalDebuggerInvoker ' + + `--accessToken ${token} --skillId ${skillId} --skillStreamHandlerClass ${skillInvocationInfo.handlerName} --region ${runRegion}"`; + if (waitForAttach) { + execCmd = + `cd ${skillInvocationInfo.skillCodeFolderName}; mvn exec:exec -Dexec.executable=java -Dexec.args=` + + `"-classpath %classpath -Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=${debugPort} ` + + "com.amazon.ask.localdebug.LocalDebuggerInvoker " + + `--accessToken ${token} --skillId ${skillId} --region ${runRegion} --skillStreamHandlerClass ${skillInvocationInfo.handlerName}"`; } + super({ + exec: execCmd, + ext: "java, xml", + watch: watch ? `${skillInvocationInfo.skillCodeFolderName}` : watch, + }); + } } module.exports = JavaRunFlow; diff --git a/lib/commands/run/run-flow/nodejs-run.js b/lib/commands/run/run-flow/nodejs-run.js index 22df2361..3f310c2c 100644 --- a/lib/commands/run/run-flow/nodejs-run.js +++ b/lib/commands/run/run-flow/nodejs-run.js @@ -1,34 +1,46 @@ -const path = require('path'); -const fs = require('fs'); -const CONSTANTS = require('@src/utils/constants'); -const CliError = require('@src/exceptions/cli-error'); -const AbstractRunFlow = require('./abstract-run-flow'); +const path = require("path"); +const fs = require("fs"); +const CONSTANTS = require("../../../utils/constants"); +const CliError = require("../../../exceptions/cli-error"); +const AbstractRunFlow = require("./abstract-run-flow"); class NodejsRunFlow extends AbstractRunFlow { - static canHandle(runtime) { - return runtime === CONSTANTS.RUNTIME.NODE; - } + static canHandle(runtime) { + return runtime === CONSTANTS.RUNTIME.NODE; + } - constructor({ skillInvocationInfo, waitForAttach, debugPort, token, skillId, runRegion, watch }) { - const skillFolderPath = path.join(process.cwd(), skillInvocationInfo.skillCodeFolderName); - const script = path.join(skillFolderPath, CONSTANTS.RUN.NODE.SCRIPT_LOCATION); - if (!fs.existsSync(script)) { - throw new CliError('ask-sdk-local-debug cannot be found. Please install ask-sdk-local-debug to your skill code project. ' - + 'Refer https://www.npmjs.com/package/ask-sdk-local-debug for more info.'); - } - const execMap = waitForAttach ? { - js: `node --inspect-brk=${debugPort}`, - } : undefined; - super({ - execMap, - script, - args: ['--accessToken', `"${token}"`, '--skillId', skillId, - '--handlerName', skillInvocationInfo.handlerName, - '--skillEntryFile', path.join(skillFolderPath, `${skillInvocationInfo.skillFileName}.js`), - '--region', runRegion], - watch: watch ? `${skillInvocationInfo.skillCodeFolderName}` : watch - }); + constructor({skillInvocationInfo, waitForAttach, debugPort, token, skillId, runRegion, watch}) { + const skillFolderPath = path.join(process.cwd(), skillInvocationInfo.skillCodeFolderName); + const script = path.join(skillFolderPath, CONSTANTS.RUN.NODE.SCRIPT_LOCATION); + if (!fs.existsSync(script)) { + throw new CliError( + "ask-sdk-local-debug cannot be found. Please install ask-sdk-local-debug to your skill code project. " + + "Refer https://www.npmjs.com/package/ask-sdk-local-debug for more info.", + ); } + const execMap = waitForAttach + ? { + js: `node --inspect-brk=${debugPort}`, + } + : undefined; + super({ + execMap, + script, + args: [ + "--accessToken", + `"${token}"`, + "--skillId", + skillId, + "--handlerName", + skillInvocationInfo.handlerName, + "--skillEntryFile", + path.join(skillFolderPath, `${skillInvocationInfo.skillFileName}.js`), + "--region", + runRegion, + ], + watch: watch ? `${skillInvocationInfo.skillCodeFolderName}` : watch, + }); + } } module.exports = NodejsRunFlow; diff --git a/lib/commands/run/run-flow/python-run.js b/lib/commands/run/run-flow/python-run.js index 75afa5a2..7483ec17 100644 --- a/lib/commands/run/run-flow/python-run.js +++ b/lib/commands/run/run-flow/python-run.js @@ -1,45 +1,58 @@ -const childprocess = require('child_process'); -const path = require('path'); -const fs = require('fs'); -const CONSTANTS = require('@src/utils/constants'); -const CliError = require('@src/exceptions/cli-error'); -const AbstractRunFlow = require('./abstract-run-flow'); +const childprocess = require("child_process"); +const path = require("path"); +const fs = require("fs"); +const CONSTANTS = require("../../../utils/constants"); +const CliError = require("../../../exceptions/cli-error"); +const AbstractRunFlow = require("./abstract-run-flow"); class PythonRunFlow extends AbstractRunFlow { - static canHandle(runtime) { - return runtime === CONSTANTS.RUNTIME.PYTHON; - } + static canHandle(runtime) { + return runtime === CONSTANTS.RUNTIME.PYTHON; + } - constructor({ skillInvocationInfo, waitForAttach, debugPort, token, skillId, runRegion, watch }) { - const sitePkgLocationsStr = childprocess.execSync('python3 -c "import site; import json; print(json.dumps(site.getsitepackages()))"') - .toString(); - const sitePkgLocations = JSON.parse(sitePkgLocationsStr); - const localDebuggerPath = sitePkgLocations - .map(location => path.join(location, CONSTANTS.RUN.PYTHON.SCRIPT_LOCATION)) - .find(location => fs.existsSync(location)); - if (!fs.existsSync(localDebuggerPath)) { - throw new CliError('ask-sdk-local-debug cannot be found. Please install ask-sdk-local-debug to your skill code project. ' - + 'Refer https://pypi.org/project/ask-sdk-local-debug, for more info.'); - } - if (waitForAttach) { - childprocess.execSync('python3 -m pip install debugpy', { stdio: 'inherit' }); + constructor({skillInvocationInfo, waitForAttach, debugPort, token, skillId, runRegion, watch}) { + const sitePkgLocationsStr = childprocess + .execSync('python3 -c "import site; import json; print(json.dumps(site.getsitepackages()))"') + .toString(); + const sitePkgLocations = JSON.parse(sitePkgLocationsStr); + const localDebuggerPath = sitePkgLocations + .map((location) => path.join(location, CONSTANTS.RUN.PYTHON.SCRIPT_LOCATION)) + .find((location) => fs.existsSync(location)); + if (!fs.existsSync(localDebuggerPath)) { + throw new CliError( + "ask-sdk-local-debug cannot be found. Please install ask-sdk-local-debug to your skill code project. " + + "Refer https://pypi.org/project/ask-sdk-local-debug, for more info.", + ); + } + if (waitForAttach) { + childprocess.execSync("python3 -m pip install debugpy", {stdio: "inherit"}); + } + const execMap = waitForAttach + ? { + py: `python3 -m debugpy --listen ${debugPort} --wait-for-client`, } - const execMap = waitForAttach ? { - py: `python3 -m debugpy --listen ${debugPort} --wait-for-client`, - } : { - py: 'python3' + : { + py: "python3", }; - super({ - execMap, - script: localDebuggerPath, - args: ['--accessToken', `"${token}"`, '--skillId', skillId, - '--skillHandler', skillInvocationInfo.handlerName, - '--skillFilePath', path.join(`${skillInvocationInfo.skillCodeFolderName}`, `${skillInvocationInfo.skillFileName}.py`), - '--region', runRegion], - ext: 'py,json,txt', - watch: watch ? `${skillInvocationInfo.skillCodeFolderName}` : watch - }); - } + super({ + execMap, + script: localDebuggerPath, + args: [ + "--accessToken", + `"${token}"`, + "--skillId", + skillId, + "--skillHandler", + skillInvocationInfo.handlerName, + "--skillFilePath", + path.join(`${skillInvocationInfo.skillCodeFolderName}`, `${skillInvocationInfo.skillFileName}.py`), + "--region", + runRegion, + ], + ext: "py,json,txt", + watch: watch ? `${skillInvocationInfo.skillCodeFolderName}` : watch, + }); + } } module.exports = PythonRunFlow; diff --git a/lib/commands/skill/add-locales/helper.js b/lib/commands/skill/add-locales/helper.js index 2ca3163b..a1c598d8 100644 --- a/lib/commands/skill/add-locales/helper.js +++ b/lib/commands/skill/add-locales/helper.js @@ -1,19 +1,19 @@ -const fs = require('fs-extra'); -const path = require('path'); -const R = require('ramda'); -const async = require('async'); +const fs = require("fs-extra"); +const path = require("path"); +const R = require("ramda"); +const async = require("async"); -const httpClient = require('@src/clients/http-client'); -const SkillMetadataController = require('@src/controllers/skill-metadata-controller'); -const CliError = require('@src/exceptions/cli-error'); -const ResourcesConfig = require('@src/model/resources-config'); -const Manifest = require('@src/model/manifest'); -const stringUtils = require('@src/utils/string-utils'); -const CONSTANTS = require('@src/utils/constants'); +const httpClient = require("../../../clients/http-client"); +const SkillMetadataController = require("../../../controllers/skill-metadata-controller"); +const CliError = require("../../../exceptions/cli-error"); +const ResourcesConfig = require("../../../model/resources-config"); +const Manifest = require("../../../model/manifest"); +const stringUtils = require("../../../utils/string-utils"); +const CONSTANTS = require("../../../utils/constants"); module.exports = { - initiateModels, - addLocales + initiateModels, + addLocales, }; /** @@ -21,16 +21,16 @@ module.exports = { * @param {String} profile */ function initiateModels(profile) { - new ResourcesConfig(path.join(process.cwd(), CONSTANTS.FILE_PATH.ASK_RESOURCES_JSON_CONFIG)); - const skillPackageSrc = ResourcesConfig.getInstance().getSkillMetaSrc(profile); - if (!stringUtils.isNonBlankString(skillPackageSrc)) { - throw new CliError('Skill package src is not found in ask-resources.json.'); - } - if (!fs.existsSync(skillPackageSrc)) { - throw new CliError(`The skillMetadata src file ${skillPackageSrc} does not exist.`); - } - const manifestPath = path.join(skillPackageSrc, CONSTANTS.FILE_PATH.SKILL_PACKAGE.MANIFEST); - new Manifest(manifestPath); + new ResourcesConfig(path.join(process.cwd(), CONSTANTS.FILE_PATH.ASK_RESOURCES_JSON_CONFIG)); + const skillPackageSrc = ResourcesConfig.getInstance().getSkillMetaSrc(profile); + if (!stringUtils.isNonBlankString(skillPackageSrc)) { + throw new CliError("Skill package src is not found in ask-resources.json."); + } + if (!fs.existsSync(skillPackageSrc)) { + throw new CliError(`The skillMetadata src file ${skillPackageSrc} does not exist.`); + } + const manifestPath = path.join(skillPackageSrc, CONSTANTS.FILE_PATH.SKILL_PACKAGE.MANIFEST); + new Manifest(manifestPath); } /** @@ -43,42 +43,48 @@ function initiateModels(profile) { * @param {Function} callback */ function addLocales(selectedLocales, profile, doDebug, callback) { - // analyze all the selected locales, whether copy from local existing files or get from remote templates - _getNewLocaleModelUri(selectedLocales, profile, doDebug, (resolveErr, iModelSourceByLocales) => { - if (resolveErr) { - return callback(resolveErr); + // analyze all the selected locales, whether copy from local existing files or get from remote templates + _getNewLocaleModelUri(selectedLocales, profile, doDebug, (resolveErr, iModelSourceByLocales) => { + if (resolveErr) { + return callback(resolveErr); + } + const iModelFolderPath = path.join( + process.cwd(), + ResourcesConfig.getInstance().getSkillMetaSrc(profile), + CONSTANTS.FILE_PATH.SKILL_PACKAGE.INTERACTION_MODEL, + "custom", + ); + const remoteTemplateSet = new Set( + [...iModelSourceByLocales.values()].reduce((acc, cur) => { + if (!cur.canCopy) { + acc.push(cur.uri); } - const iModelFolderPath = path.join(process.cwd(), ResourcesConfig.getInstance().getSkillMetaSrc(profile), - CONSTANTS.FILE_PATH.SKILL_PACKAGE.INTERACTION_MODEL, 'custom'); - const remoteTemplateSet = new Set( - [...iModelSourceByLocales.values()].reduce((acc, cur) => { - if (!cur.canCopy) { acc.push(cur.uri); } - return acc; - }, []) - ); - // retrieve remote templates when no existing JSON shares the same language - _retrieveTemplatesByLanguage(remoteTemplateSet, doDebug, (templateErr, templateByLanguage) => { - if (templateErr) { - return callback(templateErr); - } - // copy iModel JSONs that contains same language - iModelSourceByLocales.forEach((v, k) => { - if (v.canCopy) { - const sourceLocale = path.basename(v.uri, path.extname(v.uri)); - const targetFilePath = path.join(iModelFolderPath, `${k}.json`); - fs.copySync(v.uri, targetFilePath); // do not fail if the target locale exists already - const sourceManifestLocale = Manifest.getInstance().getPublishingLocale(sourceLocale); - Manifest.getInstance().setPublishingLocale(k, sourceManifestLocale); - } else { - const targetFilePath = path.join(iModelFolderPath, `${k}.json`); - fs.writeFileSync(targetFilePath, templateByLanguage.get(v.uri), { encoding: 'utf-8' }); - Manifest.getInstance().setPublishingLocale(k, { name: 'please change' }); - } - }); - Manifest.getInstance().write(); - callback(undefined, iModelSourceByLocales); - }); + return acc; + }, []), + ); + // retrieve remote templates when no existing JSON shares the same language + _retrieveTemplatesByLanguage(remoteTemplateSet, doDebug, (templateErr, templateByLanguage) => { + if (templateErr) { + return callback(templateErr); + } + // copy iModel JSONs that contains same language + iModelSourceByLocales.forEach((v, k) => { + if (v.canCopy) { + const sourceLocale = path.basename(v.uri, path.extname(v.uri)); + const targetFilePath = path.join(iModelFolderPath, `${k}.json`); + fs.copySync(v.uri, targetFilePath); // do not fail if the target locale exists already + const sourceManifestLocale = Manifest.getInstance().getPublishingLocale(sourceLocale); + Manifest.getInstance().setPublishingLocale(k, sourceManifestLocale); + } else { + const targetFilePath = path.join(iModelFolderPath, `${k}.json`); + fs.writeFileSync(targetFilePath, templateByLanguage.get(v.uri), {encoding: "utf-8"}); + Manifest.getInstance().setPublishingLocale(k, {name: "please change"}); + } + }); + Manifest.getInstance().write(); + callback(undefined, iModelSourceByLocales); }); + }); } /** @@ -91,38 +97,43 @@ function addLocales(selectedLocales, profile, doDebug, callback) { * @returns {Function} callback Map { locale: { uri, canCopy} } where the uri is filePath or remoteURI */ function _getNewLocaleModelUri(selectedLocales, profile, doDebug, callback) { - const skillMetaController = new SkillMetadataController({ profile, doDebug }); - const localIModelByLocale = skillMetaController.getInteractionModelLocales(); - const result = new Map(); - // get from map of templates - httpClient.request({ - url: CONSTANTS.TEMPLATES.INTERACTION_MODEL_MAP, - method: CONSTANTS.HTTP_REQUEST.VERB.GET - }, 'GET_INTERACTION_MODEL_MAP', doDebug, (error, templateMapResponse) => { - if (error) { - return callback(`Failed to retrieve the template list.\nError: ${error}`); - } - if (templateMapResponse.statusCode !== 200) { - return callback(`Failed to retrieve the template list, please see the details from the error response. + const skillMetaController = new SkillMetadataController({profile, doDebug}); + const localIModelByLocale = skillMetaController.getInteractionModelLocales(); + const result = new Map(); + // get from map of templates + httpClient.request( + { + url: CONSTANTS.TEMPLATES.INTERACTION_MODEL_MAP, + method: CONSTANTS.HTTP_REQUEST.VERB.GET, + }, + "GET_INTERACTION_MODEL_MAP", + doDebug, + (error, templateMapResponse) => { + if (error) { + return callback(`Failed to retrieve the template list.\nError: ${error}`); + } + if (templateMapResponse.statusCode !== 200) { + return callback(`Failed to retrieve the template list, please see the details from the error response. ${JSON.stringify(templateMapResponse, null, 2)}`); + } + const templateIndexMap = JSON.parse(templateMapResponse.body); + // assign for each locale + for (const locale of selectedLocales) { + if (R.keys(localIModelByLocale).includes(locale)) { + continue; } - const templateIndexMap = JSON.parse(templateMapResponse.body); - // assign for each locale - for (const locale of selectedLocales) { - if (R.keys(localIModelByLocale).includes(locale)) { - continue; - } - const languageExtractor = (s) => R.slice(0, R.lastIndexOf('-', s), s); - const language = languageExtractor(locale); - const reusableLocale = R.find((k) => languageExtractor(k) === language)(R.keys(localIModelByLocale)); - if (reusableLocale) { - result.set(locale, { uri: localIModelByLocale[reusableLocale], canCopy: true }); - } else { - result.set(locale, { uri: templateIndexMap.INTERACTION_MODEL_BY_LANGUAGE[language], canCopy: false }); - } + const languageExtractor = (s) => R.slice(0, R.lastIndexOf("-", s), s); + const language = languageExtractor(locale); + const reusableLocale = R.find((k) => languageExtractor(k) === language)(R.keys(localIModelByLocale)); + if (reusableLocale) { + result.set(locale, {uri: localIModelByLocale[reusableLocale], canCopy: true}); + } else { + result.set(locale, {uri: templateIndexMap.INTERACTION_MODEL_BY_LANGUAGE[language], canCopy: false}); } - callback(undefined, result); - }); + } + callback(undefined, result); + }, + ); } /** @@ -132,28 +143,37 @@ ${JSON.stringify(templateMapResponse, null, 2)}`); * @param {Function} callback Map { templateUrl: bodyContent } */ function _retrieveTemplatesByLanguage(templateSet, doDebug, callback) { - const result = new Map(); - if (templateSet.size === 0) { - return process.nextTick(() => { - callback(undefined, result); - }); - } - async.forEach(templateSet.values(), (templateUrl, loopCallback) => { - httpClient.request({ - url: templateUrl, - method: CONSTANTS.HTTP_REQUEST.VERB.GET - }, 'GET_INTERACTION_MODEL_TEMPLATE', doDebug, (error, response) => { - if (error) { - return loopCallback(`Failed to retrieve the template list.\n${error}`); - } - if (response.statusCode > 300) { - return loopCallback(`Failed to retrieve the template list, please see the details from the error response. -${JSON.stringify(response, null, 2)}`); - } - result.set(templateUrl, response.body); - loopCallback(); - }); - }, (error) => { - callback(error, error ? undefined : result); + const result = new Map(); + if (templateSet.size === 0) { + return process.nextTick(() => { + callback(undefined, result); }); + } + async.forEach( + templateSet.values(), + (templateUrl, loopCallback) => { + httpClient.request( + { + url: templateUrl, + method: CONSTANTS.HTTP_REQUEST.VERB.GET, + }, + "GET_INTERACTION_MODEL_TEMPLATE", + doDebug, + (error, response) => { + if (error) { + return loopCallback(`Failed to retrieve the template list.\n${error}`); + } + if (response.statusCode > 300) { + return loopCallback(`Failed to retrieve the template list, please see the details from the error response. +${JSON.stringify(response, null, 2)}`); + } + result.set(templateUrl, response.body); + loopCallback(); + }, + ); + }, + (error) => { + callback(error, error ? undefined : result); + }, + ); } diff --git a/lib/commands/skill/add-locales/index.js b/lib/commands/skill/add-locales/index.js deleted file mode 100644 index 2d6334b3..00000000 --- a/lib/commands/skill/add-locales/index.js +++ /dev/null @@ -1,56 +0,0 @@ -const R = require('ramda'); - -const { AbstractCommand } = require('@src/commands/abstract-command'); -const optionModel = require('@src/commands/option-model'); -const CONSTANTS = require('@src/utils/constants'); -const profileHelper = require('@src/utils/profile-helper'); -const Messenger = require('@src/view/messenger'); - -const helper = require('./helper'); -const ui = require('./ui'); - -class AddLocalesCommand extends AbstractCommand { - name() { - return 'add-locales'; - } - - description() { - return 'add new locale(s) from existing locale or from the template'; - } - - requiredOptions() { - return []; - } - - optionalOptions() { - return ['profile', 'debug']; - } - - handle(cmd, cb) { - let profile; - try { - profile = profileHelper.runtimeProfile(cmd.profile); - helper.initiateModels(profile); - } catch (err) { - Messenger.getInstance().error(err); - return cb(err); - } - ui.selectLocales(R.keys(CONSTANTS.ALEXA.LANGUAGES), (selectErr, selectedLocales) => { - if (selectErr) { - Messenger.getInstance().error(selectErr); - return cb(selectErr); - } - helper.addLocales(selectedLocales, profile, cmd.debug, (addErr, iModelSourceByLocales) => { - if (addErr) { - Messenger.getInstance().error(addErr); - return cb(addErr); - } - ui.displayAddLocalesResult(selectedLocales, iModelSourceByLocales); - cb(); - }); - }); - } -} - -module.exports = AddLocalesCommand; -module.exports.createCommand = new AddLocalesCommand(optionModel).createCommand(); diff --git a/lib/commands/skill/add-locales/index.ts b/lib/commands/skill/add-locales/index.ts new file mode 100644 index 00000000..ea0b351c --- /dev/null +++ b/lib/commands/skill/add-locales/index.ts @@ -0,0 +1,56 @@ +import R from "ramda"; +import {AbstractCommand} from "../../abstract-command"; +import optionModel from "../../option-model.json"; +import CONSTANTS from "../../../utils/constants"; +import profileHelper from "../../../utils/profile-helper"; +import Messenger from "../../../view/messenger"; +import helper from "./helper"; +import ui from "./ui"; +import {OptionModel} from "../../option-validator"; + +export default class AddLocalesCommand extends AbstractCommand { + name() { + return "add-locales"; + } + + description() { + return "add new locale(s) from existing locale or from the template"; + } + + requiredOptions() { + return []; + } + + optionalOptions() { + return ["profile", "debug"]; + } + + async handle(cmd: Record): Promise { + let profile: string; + try { + profile = profileHelper.runtimeProfile(cmd.profile); + helper.initiateModels(profile); + } catch (err) { + Messenger.getInstance().error(err); + throw err; + } + return new Promise((resolve, reject) => { + ui.selectLocales(R.keys(CONSTANTS.ALEXA.LANGUAGES), (selectErr: any, selectedLocales: string[]) => { + if (selectErr) { + Messenger.getInstance().error(selectErr); + return reject(selectErr); + } + helper.addLocales(selectedLocales, profile, cmd.debug, (addErr: any, iModelSourceByLocales: any) => { + if (addErr) { + Messenger.getInstance().error(addErr); + return reject(addErr); + } + ui.displayAddLocalesResult(selectedLocales, iModelSourceByLocales, profile); + resolve(); + }); + }); + }); + } +} + +export const createCommand = new AddLocalesCommand(optionModel as OptionModel).createCommand(); diff --git a/lib/commands/skill/add-locales/ui.js b/lib/commands/skill/add-locales/ui.js index 5487732e..30af5a3b 100644 --- a/lib/commands/skill/add-locales/ui.js +++ b/lib/commands/skill/add-locales/ui.js @@ -1,11 +1,12 @@ -const inquirer = require('inquirer'); -const path = require('path'); +const inquirer = require("inquirer"); +const path = require("path"); +const acUtil = require("../../../utils/ac-util"); -const Messenger = require('@src/view/messenger'); +const Messenger = require("../../../view/messenger"); module.exports = { - selectLocales, - displayAddLocalesResult + selectLocales, + displayAddLocalesResult, }; /** @@ -14,15 +15,20 @@ module.exports = { * @param {Function} callback */ function selectLocales(localeChoices, callback) { - inquirer.prompt([{ - message: 'Please select at least one locale to add:', - type: 'checkbox', - name: 'localeList', - choices: localeChoices - }]).then((answer) => { - callback(null, answer.localeList); - }).catch((error) => { - callback(error); + inquirer + .prompt([ + { + message: "Please select at least one locale to add:", + type: "checkbox", + name: "localeList", + choices: localeChoices, + }, + ]) + .then((answer) => { + callback(null, answer.localeList); + }) + .catch((error) => { + callback(error); }); } @@ -31,25 +37,29 @@ function selectLocales(localeChoices, callback) { * @param {Array} selectedLocales selected locales * @param {Map} iModelSourceByLocales Map { locale: { uri, canCopy} } */ -function displayAddLocalesResult(selectedLocales, iModelSourceByLocales) { - for (const locale of selectedLocales) { - if (!iModelSourceByLocales.has(locale)) { - Messenger.getInstance().info(`Locale ${locale}.json already exists`); - } - } - Messenger.getInstance().info(''); - if (iModelSourceByLocales.size === 0) { - return; +function displayAddLocalesResult(selectedLocales, iModelSourceByLocales, profile) { + for (const locale of selectedLocales) { + if (!iModelSourceByLocales.has(locale)) { + Messenger.getInstance().info(`Locale ${locale}.json already exists`); } + } + Messenger.getInstance().info(""); + if (iModelSourceByLocales.size === 0) { + return; + } - Messenger.getInstance().info('The following skill locale(s) have been added according to your local project:'); - iModelSourceByLocales.forEach((v, k) => { - if (v.canCopy) { - const sourceLocale = path.basename(v.uri, path.extname(v.uri)); - Messenger.getInstance().info(` Added locale ${k}.json from ${sourceLocale}'s interactionModel`); - } else { - Messenger.getInstance().info(` Added locale ${k}.json from the template of interactionModel`); - } - }); - Messenger.getInstance().info('Please check the added files above, and run "ask deploy" to deploy the changes.'); + Messenger.getInstance().info("The following skill locale(s) have been added according to your local project:"); + iModelSourceByLocales.forEach((v, k) => { + if (v.canCopy) { + const sourceLocale = path.basename(v.uri, path.extname(v.uri)); + Messenger.getInstance().info(` Added locale ${k}.json from ${sourceLocale}'s interactionModel`); + } else { + Messenger.getInstance().info(` Added locale ${k}.json from the template of interactionModel`); + } + }); + acUtil.isAcSkill(profile) + ? Messenger.getInstance().info( + 'Please check the added files above, compile your Alexa Conversation skill and run "ask deploy" to deploy the changes.', + ) + : Messenger.getInstance().info('Please check the added files above, and run "ask deploy" to deploy the changes.'); } diff --git a/lib/commands/skill/skill-commander.js b/lib/commands/skill/skill-commander.js deleted file mode 100644 index c306fb31..00000000 --- a/lib/commands/skill/skill-commander.js +++ /dev/null @@ -1,16 +0,0 @@ -const commander = require('commander'); - -const SKILL_COMMAND_MAP = { - 'add-locales': '@src/commands/skill/add-locales' -}; - -Object.keys(SKILL_COMMAND_MAP).forEach((cmd) => { - // eslint-disable-next-line global-require - require(SKILL_COMMAND_MAP[cmd]).createCommand(commander); -}); - -commander._name = 'ask skill'; -commander - .description('increase the productivity when managing skill metadata'); - -module.exports = { commander, SKILL_COMMAND_MAP }; diff --git a/lib/commands/skill/skill-commander.ts b/lib/commands/skill/skill-commander.ts new file mode 100644 index 00000000..06f7a128 --- /dev/null +++ b/lib/commands/skill/skill-commander.ts @@ -0,0 +1,15 @@ +import {Command} from "commander"; + +import {createCommand as localesCreateCommand} from "./add-locales"; + +const commander = new Command(); +const SKILL_COMMAND_MAP: Record void> = { + "add-locales": localesCreateCommand, +}; + +Object.values(SKILL_COMMAND_MAP).forEach((create) => create(commander)); + +commander.name("ask skill"); +commander.description("increase the productivity when managing skill metadata"); + +export {commander, SKILL_COMMAND_MAP}; diff --git a/lib/commands/smapi/appended-commands/export-package/helper.js b/lib/commands/smapi/appended-commands/export-package/helper.js index c4b69666..6e80e71f 100644 --- a/lib/commands/smapi/appended-commands/export-package/helper.js +++ b/lib/commands/smapi/appended-commands/export-package/helper.js @@ -1,9 +1,9 @@ -const CONSTANTS = require('@src/utils/constants'); -const jsonView = require('@src/view/json-view'); -const Retry = require('@src/utils/retry-utility'); +const CONSTANTS = require("../../../../utils/constants"); +const jsonView = require("../../../../view/json-view"); +const Retry = require("../../../../utils/retry-utility"); module.exports = { - pollExportStatus + pollExportStatus, }; /** @@ -12,22 +12,22 @@ module.exports = { * @param {Function} callback (err, lastExportStatus) */ function pollExportStatus(smapiClient, exportId, callback) { - const retryConfig = { - base: CONSTANTS.CONFIGURATION.RETRY.GET_PACKAGE_EXPORT_STATUS.MIN_TIME_OUT, - factor: CONSTANTS.CONFIGURATION.RETRY.GET_PACKAGE_EXPORT_STATUS.FACTOR, - maxRetry: CONSTANTS.CONFIGURATION.RETRY.GET_PACKAGE_EXPORT_STATUS.MAX_RETRY - }; - const retryCall = (loopCallback) => { - smapiClient.skillPackage.getExportStatus(exportId, (pollErr, pollResponse) => { - if (pollErr) { - return loopCallback(pollErr); - } - if (pollResponse.statusCode >= 300) { - return loopCallback(jsonView.toString(pollResponse.body)); - } - loopCallback(null, pollResponse); - }); - }; - const shouldRetryCondition = retryResponse => retryResponse.body.status === CONSTANTS.SKILL.PACKAGE_STATUS.IN_PROGRESS; - Retry.retry(retryConfig, retryCall, shouldRetryCondition, (err, res) => callback(err, err ? null : res)); + const retryConfig = { + base: CONSTANTS.CONFIGURATION.RETRY.GET_PACKAGE_EXPORT_STATUS.MIN_TIME_OUT, + factor: CONSTANTS.CONFIGURATION.RETRY.GET_PACKAGE_EXPORT_STATUS.FACTOR, + maxRetry: CONSTANTS.CONFIGURATION.RETRY.GET_PACKAGE_EXPORT_STATUS.MAX_RETRY, + }; + const retryCall = (loopCallback) => { + smapiClient.skillPackage.getExportStatus(exportId, (pollErr, pollResponse) => { + if (pollErr) { + return loopCallback(pollErr); + } + if (pollResponse.statusCode >= 300) { + return loopCallback(jsonView.toString(pollResponse.body)); + } + loopCallback(null, pollResponse); + }); + }; + const shouldRetryCondition = (retryResponse) => retryResponse.body.status === CONSTANTS.SKILL.PACKAGE_STATUS.IN_PROGRESS; + Retry.retry(retryConfig, retryCall, shouldRetryCondition, (err, res) => callback(err, err ? null : res)); } diff --git a/lib/commands/smapi/appended-commands/export-package/index.js b/lib/commands/smapi/appended-commands/export-package/index.js deleted file mode 100644 index ff2584f4..00000000 --- a/lib/commands/smapi/appended-commands/export-package/index.js +++ /dev/null @@ -1,87 +0,0 @@ -const fs = require('fs'); -const path = require('path'); -const R = require('ramda'); - -const { AbstractCommand } = require('@src/commands/abstract-command'); -const CONSTANTS = require('@src/utils/constants'); -const jsonView = require('@src/view/json-view'); -const Messenger = require('@src/view/messenger'); -const optionModel = require('@src/commands/option-model'); -const profileHelper = require('@src/utils/profile-helper'); -const SmapiClient = require('@src/clients/smapi-client'); -const zipUtils = require('@src/utils/zip-utils'); - -const helper = require('./helper'); - -class ExportPackageCommand extends AbstractCommand { - name() { - return 'export-package'; - } - - description() { - return 'download the skill package to "skill-package" folder in current directory'; - } - - requiredOptions() { - return ['skill-id', 'stage']; - } - - optionalOptions() { - return ['profile', 'debug']; - } - - handle(cmd, cb) { - let profile; - try { - profile = profileHelper.runtimeProfile(cmd.profile); - // 0.check if a skill-package file exists - if (fs.existsSync(CONSTANTS.FILE_PATH.SKILL_PACKAGE.PACKAGE)) { - throw new Error(`A ${CONSTANTS.FILE_PATH.SKILL_PACKAGE.PACKAGE} fold already exists in the current working directory.`); - } - } catch (err) { - Messenger.getInstance().error(err); - return cb(err); - } - const smapiClient = new SmapiClient({ - profile, - doDebug: cmd.debug - }); - - // 1.request to export skill package - smapiClient.skillPackage.exportPackage(cmd.skillId, cmd.stage, (exportErr, exportResponse) => { - if (exportErr) { - Messenger.getInstance().error(exportErr); - return cb(exportErr); - } - if (exportResponse.statusCode >= 300) { - const error = jsonView.toString(exportResponse.body); - Messenger.getInstance().error(error); - return cb(error); - } - const exportId = path.basename(R.view(R.lensPath(['headers', 'location']), exportResponse)); - - // 2.poll for the skill package export status - helper.pollExportStatus(smapiClient, exportId, (pollErr, pollResponse) => { - if (pollErr) { - Messenger.getInstance().error(pollErr); - return cb(pollErr); - } - // 3.download skill package into local file system - const skillPackageLocation = R.view(R.lensPath(['body', 'skill', 'location']), pollResponse); - const rootPath = process.cwd(); - const targetPath = path.join(rootPath, CONSTANTS.FILE_PATH.SKILL_PACKAGE.PACKAGE); - zipUtils.unzipRemoteZipFile(skillPackageLocation, targetPath, false, (unzipErr) => { - if (unzipErr) { - Messenger.getInstance().error(unzipErr); - return cb(unzipErr); - } - Messenger.getInstance().info(`The skill package had been downloaded into ${targetPath}.`); - cb(); - }); - }); - }); - } -} - -module.exports = ExportPackageCommand; -module.exports.createCommand = new ExportPackageCommand(optionModel).createCommand(); diff --git a/lib/commands/smapi/appended-commands/export-package/index.ts b/lib/commands/smapi/appended-commands/export-package/index.ts new file mode 100644 index 00000000..5725cae2 --- /dev/null +++ b/lib/commands/smapi/appended-commands/export-package/index.ts @@ -0,0 +1,86 @@ +import fs from "fs"; +import path from "path"; +import {AbstractCommand} from "../../../abstract-command"; +import CONSTANTS from "../../../../utils/constants"; +import jsonView from "../../../../view/json-view"; +import Messenger from "../../../../view/messenger"; +import optionModel from "../../../option-model.json"; +import profileHelper from "../../../../utils/profile-helper"; +import SmapiClient, {isSmapiError} from "../../../../clients/smapi-client"; +import zipUtils from "../../../../utils/zip-utils"; +import helper from "./helper.js"; +import {OptionModel} from "../../../option-validator"; + +export default class ExportPackageCommand extends AbstractCommand { + name() { + return "export-package"; + } + + description() { + return 'download the skill package to "skill-package" folder in current directory'; + } + + requiredOptions() { + return ["skill-id", "stage"]; + } + + optionalOptions() { + return ["profile", "debug"]; + } + + async handle(cmd: Record): Promise { + let profile; + try { + profile = profileHelper.runtimeProfile(cmd.profile); + // 0.check if a skill-package file exists + if (fs.existsSync(CONSTANTS.FILE_PATH.SKILL_PACKAGE.PACKAGE)) { + throw new Error(`A ${CONSTANTS.FILE_PATH.SKILL_PACKAGE.PACKAGE} fold already exists in the current working directory.`); + } + } catch (err) { + Messenger.getInstance().error(err); + throw err; + } + const smapiClient = new SmapiClient({ + profile, + doDebug: cmd.debug, + }); + + // 1.request to export skill package + return new Promise((resolve, reject) => { + smapiClient.skillPackage.exportPackage(cmd.skillId, cmd.stage, (exportErr: any, exportResponse: any) => { + if (exportErr) { + Messenger.getInstance().error(exportErr); + return reject(exportErr); + } + if (isSmapiError(exportResponse)) { + const error = jsonView.toString(exportResponse.body); + Messenger.getInstance().error(error); + return reject(error); + } + const exportId = path.basename(exportResponse?.headers?.location); + + // 2.poll for the skill package export status + helper.pollExportStatus(smapiClient, exportId, (pollErr: any, pollResponse: any) => { + if (pollErr) { + Messenger.getInstance().error(pollErr); + return reject(pollErr); + } + // 3.download skill package into local file system + const skillPackageLocation = pollResponse?.body?.skill?.location; + const rootPath = process.cwd(); + const targetPath = path.join(rootPath, CONSTANTS.FILE_PATH.SKILL_PACKAGE.PACKAGE); + zipUtils.unzipRemoteZipFile(skillPackageLocation, targetPath, false, (unzipErr: any) => { + if (unzipErr) { + Messenger.getInstance().error(unzipErr); + return reject(unzipErr); + } + Messenger.getInstance().info(`The skill package had been downloaded into ${targetPath}.`); + resolve(); + }); + }); + }); + }); + } +} + +export const createCommand = new ExportPackageCommand(optionModel as OptionModel).createCommand(); diff --git a/lib/commands/smapi/appended-commands/get-task/index.js b/lib/commands/smapi/appended-commands/get-task/index.js deleted file mode 100644 index dc083c0c..00000000 --- a/lib/commands/smapi/appended-commands/get-task/index.js +++ /dev/null @@ -1,46 +0,0 @@ -const { AbstractCommand } = require('@src/commands/abstract-command'); -const jsonView = require('@src/view/json-view'); -const Messenger = require('@src/view/messenger'); -const optionModel = require('@src/commands/option-model'); -const profileHelper = require('@src/utils/profile-helper'); -const SmapiClient = require('@src/clients/smapi-client'); - -class GetTaskCommand extends AbstractCommand { - name() { - return 'get-task'; - } - - description() { - return 'Get the task definition details specified by the taskName and version.'; - } - - requiredOptions() { - return ['skill-id', 'task-name', 'task-version']; - } - - optionalOptions() { - return ['profile', 'debug']; - } - - handle(cmd, cb) { - const { skillId, taskName, taskVersion, profile, debug } = cmd; - const smapiClient = new SmapiClient({ - profile: profileHelper.runtimeProfile(profile), - doDebug: debug - }); - smapiClient.task.getTask(skillId, taskName, taskVersion, (err, result) => { - if (err || result.statusCode >= 400) { - const error = err || jsonView.toString(result.body); - Messenger.getInstance().error(error); - cb(error); - } else { - const res = jsonView.toString(JSON.parse(result.body.definition)); - Messenger.getInstance().info(res); - cb(null, res); - } - }); - } -} - -module.exports = GetTaskCommand; -module.exports.createCommand = new GetTaskCommand(optionModel).createCommand(); diff --git a/lib/commands/smapi/appended-commands/get-task/index.ts b/lib/commands/smapi/appended-commands/get-task/index.ts new file mode 100644 index 00000000..6aa3f3bf --- /dev/null +++ b/lib/commands/smapi/appended-commands/get-task/index.ts @@ -0,0 +1,48 @@ +import {AbstractCommand} from "../../../abstract-command"; +import jsonView from "../../../../view/json-view"; +import Messenger from "../../../../view/messenger"; +import optionModel from "../../../option-model.json"; +import profileHelper from "../../../../utils/profile-helper"; +import SmapiClient from "../../../../clients/smapi-client"; +import {OptionModel} from "../../../option-validator"; + +export default class GetTaskCommand extends AbstractCommand { + name() { + return "get-task"; + } + + description() { + return "Get the task definition details specified by the taskName and version."; + } + + requiredOptions() { + return ["skill-id", "task-name", "task-version"]; + } + + optionalOptions() { + return ["profile", "debug"]; + } + + async handle(cmd: Record): Promise { + const {skillId, taskName, taskVersion, profile, debug} = cmd; + const smapiClient = new SmapiClient({ + profile: profileHelper.runtimeProfile(profile), + doDebug: debug, + }); + return new Promise((resolve, reject) => { + smapiClient.task.getTask(skillId, taskName, taskVersion, (err: any, result: any) => { + if (err || result.statusCode >= 400) { + const error = err || jsonView.toString(result.body); + Messenger.getInstance().error(error); + reject(error); + } else { + const res = jsonView.toString(JSON.parse(result.body.definition)); + Messenger.getInstance().info(res); + resolve(res); + } + }); + }); + } +} + +export const createCommand = new GetTaskCommand(optionModel as OptionModel).createCommand(); diff --git a/lib/commands/smapi/appended-commands/search-task/index.js b/lib/commands/smapi/appended-commands/search-task/index.js deleted file mode 100644 index 79fcc524..00000000 --- a/lib/commands/smapi/appended-commands/search-task/index.js +++ /dev/null @@ -1,58 +0,0 @@ -const R = require('ramda'); - -const { AbstractCommand } = require('@src/commands/abstract-command'); -const jsonView = require('@src/view/json-view'); -const Messenger = require('@src/view/messenger'); -const optionModel = require('@src/commands/option-model'); -const profileHelper = require('@src/utils/profile-helper'); -const SmapiClient = require('@src/clients/smapi-client'); - -class SearchTaskCommand extends AbstractCommand { - name() { - return 'search-task'; - } - - description() { - return 'List the tasks summary information based on keywords or provider skillId. ' - + 'If both keywords and provider skillId are not specified, will list all the tasks ' - + 'summary information accessible by the skillId.'; - } - - requiredOptions() { - return ['skill-id']; - } - - optionalOptions() { - return ['next-token', 'max-results', 'provider-skill-id', 'keywords', 'profile', 'debug']; - } - - static encodeSpaces(keywords) { - return keywords ? keywords.replace(/\s/g, '%20') : keywords; - } - - handle(cmd, cb) { - const { skillId, providerSkillId, maxResults, nextToken, profile, debug } = cmd; - const keywords = SearchTaskCommand.encodeSpaces(cmd.keywords); - const queryParams = R.reject(R.isNil, { maxResults, nextToken }); - - const smapiClient = new SmapiClient({ - profile: profileHelper.runtimeProfile(profile), - doDebug: debug - }); - - smapiClient.task.searchTask(skillId, keywords, providerSkillId, queryParams, (err, result) => { - if (err || result.statusCode >= 400) { - const error = err || jsonView.toString(result.body); - Messenger.getInstance().error(error); - cb(error); - } else { - const res = jsonView.toString(result.body); - Messenger.getInstance().info(res); - cb(null, res); - } - }); - } -} - -module.exports = SearchTaskCommand; -module.exports.createCommand = new SearchTaskCommand(optionModel).createCommand(); diff --git a/lib/commands/smapi/appended-commands/search-task/index.ts b/lib/commands/smapi/appended-commands/search-task/index.ts new file mode 100644 index 00000000..de750ccc --- /dev/null +++ b/lib/commands/smapi/appended-commands/search-task/index.ts @@ -0,0 +1,61 @@ +import R from "ramda"; +import {AbstractCommand} from "../../../abstract-command"; +import jsonView from "../../../../view/json-view"; +import Messenger from "../../../../view/messenger"; +import optionModel from "../../../option-model.json"; +import profileHelper from "../../../../utils/profile-helper"; +import SmapiClient from "../../../../clients/smapi-client"; +import {OptionModel} from "../../../option-validator"; + +export default class SearchTaskCommand extends AbstractCommand { + name() { + return "search-task"; + } + + description() { + return ( + "List the tasks summary information based on keywords or provider skillId. " + + "If both keywords and provider skillId are not specified, will list all the tasks " + + "summary information accessible by the skillId." + ); + } + + requiredOptions() { + return ["skill-id"]; + } + + optionalOptions() { + return ["next-token", "max-results", "provider-skill-id", "keywords", "profile", "debug"]; + } + + static encodeSpaces(keywords: string) { + return keywords ? keywords.replace(/\s/g, "%20") : keywords; + } + + async handle(cmd: Record): Promise { + const {skillId, providerSkillId, maxResults, nextToken, profile, debug} = cmd; + const keywords = SearchTaskCommand.encodeSpaces(cmd.keywords); + const queryParams = R.reject(R.isNil, {maxResults, nextToken}); + + const smapiClient = new SmapiClient({ + profile: profileHelper.runtimeProfile(profile), + doDebug: debug, + }); + + return new Promise((resolve, reject) => { + smapiClient.task.searchTask(skillId, keywords, providerSkillId, queryParams, (err: any, result: any) => { + if (err || result.statusCode >= 400) { + const error = err || jsonView.toString(result.body); + Messenger.getInstance().error(error); + reject(error); + } else { + const res = jsonView.toString(result.body); + Messenger.getInstance().info(res); + resolve(res); + } + }); + }); + } +} + +export const createCommand = new SearchTaskCommand(optionModel as OptionModel).createCommand(); diff --git a/lib/commands/smapi/appended-commands/upload-catalog/helper.js b/lib/commands/smapi/appended-commands/upload-catalog/helper.js index ec1d9e89..201d7a5c 100644 --- a/lib/commands/smapi/appended-commands/upload-catalog/helper.js +++ b/lib/commands/smapi/appended-commands/upload-catalog/helper.js @@ -1,72 +1,78 @@ -const fs = require('fs'); -const inquirer = require('inquirer'); -const prettyBytes = require('pretty-bytes'); +const fs = require("fs"); +const inquirer = require("inquirer"); +const prettyBytes = require("pretty-bytes"); -const CONSTANTS = require('@src/utils/constants'); +const CONSTANTS = require("../../../../utils/constants"); module.exports = { - _resolvePartSize, - _confirmOrOverwritePartSize, - _transformUploadArrayToMap + _resolvePartSize, + _confirmOrOverwritePartSize, + _transformUploadArrayToMap, }; function _resolvePartSize(file) { - const fileSize = fs.statSync(file).size; - const minAverageSize = Math.max(Math.ceil(fileSize / CONSTANTS.CONFIGURATION.S3.MULTIPART_UPLOAD.MAX_PART_COUNT), - CONSTANTS.CONFIGURATION.S3.MULTIPART_UPLOAD.DEFAULT_PART_SIZE); - const partsNumber = Math.ceil(fileSize / minAverageSize); + const fileSize = fs.statSync(file).size; + const minAverageSize = Math.max( + Math.ceil(fileSize / CONSTANTS.CONFIGURATION.S3.MULTIPART_UPLOAD.MAX_PART_COUNT), + CONSTANTS.CONFIGURATION.S3.MULTIPART_UPLOAD.DEFAULT_PART_SIZE, + ); + const partsNumber = Math.ceil(fileSize / minAverageSize); - return { - totalSize: fileSize, - calculatedPartSize: minAverageSize, - calculatedPartsNumber: partsNumber - }; + return { + totalSize: fileSize, + calculatedPartSize: minAverageSize, + calculatedPartsNumber: partsNumber, + }; } function _confirmOrOverwritePartSize(totalSize, partSize, partsNumber, callback) { - if (partsNumber === 1) { - return process.nextTick(() => { - callback(partSize, partsNumber); - }); - } + if (partsNumber === 1) { + return process.nextTick(() => { + callback(partSize, partsNumber); + }); + } - inquirer.prompt({ - type: 'confirm', - name: 'isAllowed', - message: `CLI's about to partition this ${prettyBytes(totalSize)} file to ${partsNumber} parts and upload \ -in parallel.\n Do you agree with this partition?` - }).then((answer) => { - if (answer.isAllowed) { - return callback(partSize, partsNumber); - } + inquirer + .prompt({ + type: "confirm", + name: "isAllowed", + message: `CLI's about to partition this ${prettyBytes(totalSize)} file to ${partsNumber} parts and upload \ +in parallel.\n Do you agree with this partition?`, + }) + .then((answer) => { + if (answer.isAllowed) { + return callback(partSize, partsNumber); + } - const maxPartitions = Math.floor(totalSize / CONSTANTS.CONFIGURATION.S3.MULTIPART_UPLOAD.MIN_PART_SIZE); - inquirer.prompt({ - type: 'input', - name: 'preferredPartsNumber', - message: `Please tell us your preferred number of partitions (1 ~ ${maxPartitions}):`, - validate: (input) => { - if (!Number(input) || Number(input) <= 0 || Number(input) > maxPartitions) { - return `Parts number should be a valid integer in the range (1 ~ ${maxPartitions}) to make sure \ + const maxPartitions = Math.floor(totalSize / CONSTANTS.CONFIGURATION.S3.MULTIPART_UPLOAD.MIN_PART_SIZE); + inquirer + .prompt({ + type: "input", + name: "preferredPartsNumber", + message: `Please tell us your preferred number of partitions (1 ~ ${maxPartitions}):`, + validate: (input) => { + if (!Number(input) || Number(input) <= 0 || Number(input) > maxPartitions) { + return `Parts number should be a valid integer in the range (1 ~ ${maxPartitions}) to make sure \ each part is larger then ${CONSTANTS.CONFIGURATION.S3.MULTIPART_UPLOAD.MIN_PART_SIZE_DISPLAY}.`; - } - return true; } - }).then((ans) => { - const preferredParts = Number(ans.preferredPartsNumber); - callback(Math.ceil(totalSize / preferredParts), preferredParts); + return true; + }, + }) + .then((ans) => { + const preferredParts = Number(ans.preferredPartsNumber); + callback(Math.ceil(totalSize / preferredParts), preferredParts); }); }); } function _transformUploadArrayToMap(uploadPartsArray) { - if (!uploadPartsArray || uploadPartsArray.length === 0) { - return null; - } + if (!uploadPartsArray || uploadPartsArray.length === 0) { + return null; + } - const result = new Map(); - uploadPartsArray.forEach((cell) => { - result.set(cell.partNumber, cell.url); - }); - return result; + const result = new Map(); + uploadPartsArray.forEach((cell) => { + result.set(cell.partNumber, cell.url); + }); + return result; } diff --git a/lib/commands/smapi/appended-commands/upload-catalog/index.js b/lib/commands/smapi/appended-commands/upload-catalog/index.js deleted file mode 100644 index 19533fed..00000000 --- a/lib/commands/smapi/appended-commands/upload-catalog/index.js +++ /dev/null @@ -1,90 +0,0 @@ -const { AbstractCommand } = require('@src/commands/abstract-command'); -const Messenger = require('@src/view/messenger'); -const SmapiClient = require('@src/clients/smapi-client'); -const S3Client = require('@src/clients/aws-client/s3-client'); -const optionModel = require('@src/commands/option-model'); -const profileHelper = require('@src/utils/profile-helper'); - -const helper = require('./helper'); - -class UploadCatalogCommand extends AbstractCommand { - name() { - return 'upload-catalog'; - } - - description() { - return 'upload a file for the catalog'; - } - - requiredOptions() { - return ['catalog-id', 'file']; - } - - optionalOptions() { - return ['profile', 'debug']; - } - - handle(cmd, cb) { - let profile; - try { - profile = profileHelper.runtimeProfile(cmd.profile); - } catch (err) { - Messenger.getInstance().error(err); - return cb(err); - } - const smapiClient = new SmapiClient({ - profile, - doDebug: cmd.debug - }); - _multiPartUploadCatalog(cmd.catalogId, cmd.file, smapiClient, (err) => { - if (err) { - console.error(err); - process.exit(1); - } - Messenger.getInstance().info('Catalog uploaded successfully.'); - }); - } -} - -function _multiPartUploadCatalog(catalogId, filePath, smapiClient, callback) { - const { totalSize, calculatedPartSize, calculatedPartsNumber } = helper._resolvePartSize(filePath); - if (totalSize === 0 || calculatedPartSize === 0 || calculatedPartsNumber === 0) { - return callback('[Error]: The file to be uploaded cannot be empty.'); - } - - helper._confirmOrOverwritePartSize(totalSize, calculatedPartSize, calculatedPartsNumber, (partSize, partsNumber) => { - smapiClient.catalog.createCatalogUpload(catalogId, partsNumber, (createCatalogUploadError, createResponse) => { - if (createCatalogUploadError) { - callback(createCatalogUploadError); - return; - } - if (!createResponse.body) { - return process.nextTick(() => { - callback('[Error]: The response from create-catalog-upload should not be empty.'); - }); - } - const uploadId = createResponse.body.id; - if (!uploadId || !createResponse.body.presignedUploadParts) { - return callback('[Error]: The response of create-catalog-upload is not valid.'); - } - const uploadPartsMap = helper._transformUploadArrayToMap(createResponse.body.presignedUploadParts); - if (!uploadPartsMap) { - return callback('[Error]: The response from create-catalog-upload is empty.'); - } - - Messenger.getInstance().info(`Upload (upload-id: ${uploadId}) created successfully. Upload starts...`); - S3Client.multipartsUploadToPresignedUrls(uploadPartsMap, filePath, totalSize, partSize, partsNumber, (err, partETagsList) => { - if (err) { - return callback(err); - } - smapiClient.catalog.completeCatalogUpload(catalogId, uploadId, partETagsList, (completeCatalogUploadError) => { - callback(completeCatalogUploadError); - }); - }); - }); - }); -} - -module.exports = { - createCommand: new UploadCatalogCommand(optionModel).createCommand() -}; diff --git a/lib/commands/smapi/appended-commands/upload-catalog/index.ts b/lib/commands/smapi/appended-commands/upload-catalog/index.ts new file mode 100644 index 00000000..30293ebf --- /dev/null +++ b/lib/commands/smapi/appended-commands/upload-catalog/index.ts @@ -0,0 +1,99 @@ +import {AbstractCommand} from "../../../abstract-command"; +import Messenger from "../../../../view/messenger"; +import SmapiClient, {ISmapiClient} from "../../../../clients/smapi-client"; +import S3Client from "../../../../clients/aws-client/s3-client"; +import optionModel from "../../../option-model.json"; +import profileHelper from "../../../../utils/profile-helper"; +import helper from "./helper"; +import {OptionModel} from "../../../option-validator"; + +export default class UploadCatalogCommand extends AbstractCommand { + name() { + return "upload-catalog"; + } + + description() { + return "upload a file for the catalog"; + } + + requiredOptions() { + return ["catalog-id", "file"]; + } + + optionalOptions() { + return ["profile", "debug"]; + } + + async handle(cmd: Record): Promise { + let profile; + try { + profile = profileHelper.runtimeProfile(cmd.profile); + } catch (err) { + Messenger.getInstance().error(err); + throw err; + } + const smapiClient = new SmapiClient({ + profile, + doDebug: cmd.debug, + }); + try { + await _multiPartUploadCatalog(cmd.catalogId, cmd.file, smapiClient); + Messenger.getInstance().info("Catalog uploaded successfully."); + } catch (err) { + console.error(err); + process.exit(1); + } + } +} + +async function _multiPartUploadCatalog(catalogId: string, filePath: string, smapiClient: ISmapiClient): Promise { + const {totalSize, calculatedPartSize, calculatedPartsNumber} = helper._resolvePartSize(filePath); + if (totalSize === 0 || calculatedPartSize === 0 || calculatedPartsNumber === 0) { + throw "[Error]: The file to be uploaded cannot be empty."; + } + + return new Promise((resolve, reject) => { + helper._confirmOrOverwritePartSize(totalSize, calculatedPartSize, calculatedPartsNumber, (partSize: number, partsNumber: number) => { + smapiClient.catalog.createCatalogUpload(catalogId, partsNumber, (createCatalogUploadError: string, createResponse: any) => { + if (createCatalogUploadError) { + return reject(createCatalogUploadError); + } + if (!createResponse.body) { + return process.nextTick(() => { + reject("[Error]: The response from create-catalog-upload should not be empty."); + }); + } + const uploadId = createResponse.body.id; + if (!uploadId || !createResponse.body.presignedUploadParts) { + return reject("[Error]: The response of create-catalog-upload is not valid."); + } + const uploadPartsMap = helper._transformUploadArrayToMap(createResponse.body.presignedUploadParts); + if (!uploadPartsMap) { + return reject("[Error]: The response from create-catalog-upload is empty."); + } + + Messenger.getInstance().info(`Upload (upload-id: ${uploadId}) created successfully. Upload starts...`); + S3Client.multipartsUploadToPresignedUrls( + uploadPartsMap, + filePath, + totalSize, + partSize, + partsNumber, + (err: any, partETagsList: any) => { + if (err) { + return reject(err); + } + smapiClient.catalog.completeCatalogUpload(catalogId, uploadId, partETagsList, (completeCatalogUploadError: any) => { + if (completeCatalogUploadError) { + return reject(completeCatalogUploadError); + } + resolve(); + }); + }, + ); + }); + }); + }); +} + +export const createCommand = new UploadCatalogCommand(optionModel as OptionModel).createCommand(); diff --git a/lib/commands/smapi/before-send-processor.js b/lib/commands/smapi/before-send-processor.js index f44ee739..cebea718 100644 --- a/lib/commands/smapi/before-send-processor.js +++ b/lib/commands/smapi/before-send-processor.js @@ -1,49 +1,49 @@ -const AppConfig = require('@src/model/app-config'); +const AppConfig = require("../../model/app-config"); class BeforeSendProcessor { - constructor(commandName, paramsObject, modelIntrospector, profile) { - this.params = modelIntrospector.operations.get(commandName).params; - this.definitions = modelIntrospector.definitions; - this.paramsObject = paramsObject; - this.profile = profile; - } + constructor(commandName, paramsObject, modelIntrospector, profile) { + this.params = modelIntrospector.operations.get(commandName).params; + this.definitions = modelIntrospector.definitions; + this.paramsObject = paramsObject; + this.profile = profile; + } - processAll() { - this.appendVendorId(); - this.mapTestersEmails(); - } + processAll() { + this.appendVendorId(); + this.mapTestersEmails(); + } - appendVendorId() { - const vendorId = AppConfig.getInstance().getVendorId(this.profile); - const nonBodyParam = this.params.find(p => p.name === 'vendorId'); - if (nonBodyParam) { - this.paramsObject.vendorId = vendorId; - return; - } + appendVendorId() { + const vendorId = AppConfig.getInstance().getVendorId(this.profile); + const nonBodyParam = this.params.find((p) => p.name === "vendorId"); + if (nonBodyParam) { + this.paramsObject.vendorId = vendorId; + return; + } - const bodyParam = this.params.find(p => p.in === 'body'); - if (bodyParam && bodyParam.required && bodyParam.schema && bodyParam.schema.$ref) { - const key = bodyParam.schema.$ref.split('/').pop(); - const definition = this.definitions.get(key); - if (!definition.properties) return; - if (Object.keys(definition.properties).includes('vendorId')) { - this.paramsObject[bodyParam.name] = this.paramsObject[bodyParam.name] || {}; - this.paramsObject[bodyParam.name].vendorId = vendorId; - } - } + const bodyParam = this.params.find((p) => p.in === "body"); + if (bodyParam && bodyParam.required && bodyParam.schema && bodyParam.schema.$ref) { + const key = bodyParam.schema.$ref.split("/").pop(); + const definition = this.definitions.get(key); + if (!definition.properties) return; + if (Object.keys(definition.properties).includes("vendorId")) { + this.paramsObject[bodyParam.name] = this.paramsObject[bodyParam.name] || {}; + this.paramsObject[bodyParam.name].vendorId = vendorId; + } } + } - mapTestersEmails() { - const hasTestersParam = this.params.find(p => p.in === 'body' && p.name === 'TestersRequest'); - if (hasTestersParam) { - const { testersEmails } = this.paramsObject; - this.paramsObject.testersRequest = { - testers: testersEmails.map(email => ({ emailId: email })) - }; + mapTestersEmails() { + const hasTestersParam = this.params.find((p) => p.in === "body" && p.name === "TestersRequest"); + if (hasTestersParam) { + const {testersEmails} = this.paramsObject; + this.paramsObject.testersRequest = { + testers: testersEmails.map((email) => ({emailId: email})), + }; - delete this.paramsObject.testersEmails; - } + delete this.paramsObject.testersEmails; } + } } module.exports = BeforeSendProcessor; diff --git a/lib/commands/smapi/cli-customization-processor.js b/lib/commands/smapi/cli-customization-processor.js index 0edbc379..6164c712 100644 --- a/lib/commands/smapi/cli-customization-processor.js +++ b/lib/commands/smapi/cli-customization-processor.js @@ -1,186 +1,189 @@ -const { kebabCase, standardize } = require('@src/utils/string-utils'); -const CliError = require('@src/exceptions/cli-error'); -const { customizationMap } = require('@src/commands/smapi/customizations/parameters-map'); +const {kebabCase, standardize} = require("../../utils/string-utils"); +const CliError = require("../../exceptions/cli-error"); +const {customizationMap} = require("./customizations/parameters-map"); -const BODY_PATH_DELIMITER = '>>>'; -const ARRAY_SPLIT_DELIMITER = ','; +const BODY_PATH_DELIMITER = ">>>"; +const ARRAY_SPLIT_DELIMITER = ","; const MAX_NESTED_PROPERTIES = 10; class CliCustomizationProcessor { - /** - * Processes each operation name. - * @param {string} operationName Operation name. - */ - processOperationName(operationName) { - return kebabCase(operationName.substring(0, operationName.length - 2)); + /** + * Processes each operation name. + * @param {string} operationName Operation name. + */ + processOperationName(operationName) { + return kebabCase(operationName.substring(0, operationName.length - 2)); + } + + /** + * Processes each operation. + * @param {string} operationName Operation name. + * @param {Object} operation Operation object. + */ + processOperation(operationName, operation) { + operation.customizationMetadata.flatParamsMap = new Map(); + } + + /** + * Processes each parameter. + * @param {Object} parameter Parameter object. + * @param {Object} parentOperation Parent object of the parameter. + * @param {Map} definitions Map with all Swagger definitions. + */ + processParameter(parameter, parentOperation, definitions) { + if (parameter.in === "body") { + this._processBodyParameter(parameter, parentOperation, definitions); + } else { + this._processNonBodyParameter(parameter, parentOperation, definitions); } - - /** - * Processes each operation. - * @param {string} operationName Operation name. - * @param {Object} operation Operation object. - */ - processOperation(operationName, operation) { - operation.customizationMetadata.flatParamsMap = new Map(); - } - - /** - * Processes each parameter. - * @param {Object} parameter Parameter object. - * @param {Object} parentOperation Parent object of the parameter. - * @param {Map} definitions Map with all Swagger definitions. - */ - processParameter(parameter, parentOperation, definitions) { - if (parameter.in === 'body') { - this._processBodyParameter(parameter, parentOperation, definitions); - } else { - this._processNonBodyParameter(parameter, parentOperation, definitions); - } - } - - _processBodyParameter(parameter, parentOperation, definitions) { - const rootName = parameter.name; - const { description, required } = parameter; - const { properties } = this._getDefinitionSchema(parameter.schema.$ref, definitions); - const customization = customizationMap.get(parameter.name); - if (!properties || (customization && customization.skipUnwrap)) { - const customizedParameter = { name: parameter.name, description, required, json: true }; - this._addCustomizedParameter(parentOperation.customizationMetadata, customizedParameter); - } else if (customization && customization.customParameters) { - customization.customParameters.forEach(customParameter => { - this._addCustomizedParameter(parentOperation.customizationMetadata, customParameter); - }); - } else { - this._processNestedBodyParam(parameter, properties, parentOperation.customizationMetadata, rootName, definitions); - } - } - - _processNonBodyParameter(parameter, parentOperation, definitions) { - let customizedParameter = { ...parameter }; - const { type } = parameter; - let enumOptions = parameter.enum; - let { description } = parameter; - if (parameter.items && parameter.items.$ref) { - const schema = this._getDefinitionSchema(parameter.items.$ref, definitions); - const enumValue = this._mapEnum(parameter.description, schema); - enumOptions = enumValue.enumOptions; - description = enumValue.description; - } - customizedParameter = { ...customizedParameter, description, type, enum: enumOptions }; - this._addCustomizedParameter(parentOperation.customizationMetadata, customizedParameter); + } + + _processBodyParameter(parameter, parentOperation, definitions) { + const rootName = parameter.name; + const {description, required} = parameter; + const {properties} = this._getDefinitionSchema(parameter.schema.$ref, definitions); + const customization = customizationMap.get(parameter.name); + if (!properties || (customization && customization.skipUnwrap)) { + const customizedParameter = {name: parameter.name, description, required, json: true}; + this._addCustomizedParameter(parentOperation.customizationMetadata, customizedParameter); + } else if (customization && customization.customParameters) { + customization.customParameters.forEach((customParameter) => { + this._addCustomizedParameter(parentOperation.customizationMetadata, customParameter); + }); + } else { + this._processNestedBodyParam(parameter, properties, parentOperation.customizationMetadata, rootName, definitions); } - - _mapEnum(parentDescription, schema) { - const description = schema.description || parentDescription; - const enumOptions = schema.enum; - return { description, enumOptions }; + } + + _processNonBodyParameter(parameter, parentOperation, definitions) { + let customizedParameter = {...parameter}; + const {type} = parameter; + let enumOptions = parameter.enum; + let {description} = parameter; + if (parameter.items && parameter.items.$ref) { + const schema = this._getDefinitionSchema(parameter.items.$ref, definitions); + const enumValue = this._mapEnum(parameter.description, schema); + enumOptions = enumValue.enumOptions; + description = enumValue.description; } - - _addCustomizedParameter(customizationMetadata, customizedParameter) { - const customization = customizationMap.get(customizedParameter.name) || {}; - const skip = customization.skip || false; - if (skip) return; - - const isArray = customizedParameter.type === 'array' && !customizedParameter.json; // the array of object is treated as json type - const isNumber = ['number', 'integer'].includes(customizedParameter.type); - const isBoolean = customizedParameter.type === 'boolean'; - const flags = { isArray, isNumber, isBoolean }; - Object.keys(flags).forEach(key => { - if (flags[key]) { - customizedParameter[key] = true; - } - }); - customizationMetadata.flatParamsMap.set(standardize(customizedParameter.name), customizedParameter); + customizedParameter = {...customizedParameter, description, type, enum: enumOptions}; + this._addCustomizedParameter(parentOperation.customizationMetadata, customizedParameter); + } + + _mapEnum(parentDescription, schema) { + const description = schema.description || parentDescription; + const enumOptions = schema.enum; + return {description, enumOptions}; + } + + _addCustomizedParameter(customizationMetadata, customizedParameter) { + const customization = customizationMap.get(customizedParameter.name) || {}; + const skip = customization.skip || false; + if (skip) return; + + const isArray = customizedParameter.type === "array" && !customizedParameter.json; // the array of object is treated as json type + const isNumber = ["number", "integer"].includes(customizedParameter.type); + const isBoolean = customizedParameter.type === "boolean"; + const flags = {isArray, isNumber, isBoolean}; + Object.keys(flags).forEach((key) => { + if (flags[key]) { + customizedParameter[key] = true; + } + }); + customizationMetadata.flatParamsMap.set(standardize(customizedParameter.name), customizedParameter); + } + + _getDefinitionSchema(ref, definitions) { + const schema = ref.replace("#/definitions/", ""); + return definitions.get(schema); + } + + _shouldParseAsJson(property, definitions) { + if (property.type === "object") return true; + if (property.type === "array" && "$ref" in property.items) { + const schema = this._getDefinitionSchema(property.items.$ref, definitions); + if (schema.type === "object") return true; } + return false; + } - _getDefinitionSchema(ref, definitions) { - const schema = ref.replace('#/definitions/', ''); - return definitions.get(schema); + _isRequired(definition, key, parentRequired) { + if (definition.required) { + return definition.required.includes(key); } - - _shouldParseAsJson(property, definitions) { - if (property.type === 'object') return true; - if (property.type === 'array' && '$ref' in property.items) { - const schema = this._getDefinitionSchema(property.items.$ref, definitions); - if (schema.type === 'object') return true; - } - return false; - } - - _isRequired(definition, key, parentRequired) { - if (definition.required) { - return definition.required.includes(key); + return !!parentRequired; + } + + _appendSecondLevelProperty(customizationMetadata, parentName, rootName, secondLevelDefinition, parentRequired, definitions) { + let customizedParameter; + const parentDescription = secondLevelDefinition.description; + this._ensureNumberOfProperties(rootName, secondLevelDefinition.properties); + Object.keys(secondLevelDefinition.properties || []).forEach((key) => { + const property = secondLevelDefinition.properties[key]; + let enumOptions = null; + const {type} = property; + let description = property.description || parentDescription; + if (property.$ref) { + const schema = this._getDefinitionSchema(property.$ref, definitions); + if (!schema.enum) { + throw new CliError( + "Cannot unwrap more then 2 levels deep. Please use customParameters or " + + `set skipUnwrap for parameter ${rootName} in lib/commands/smapi/customizations/parameters.json.`, + ); } - return !!parentRequired; + enumOptions = schema.enum; + description = schema.description || description; + } + const json = this._shouldParseAsJson(property, definitions); + const bodyPath = `${parentName}${BODY_PATH_DELIMITER}${key}`; + const required = this._isRequired(secondLevelDefinition, key, parentRequired); + customizedParameter = {name: `${parentName} ${key}`, description, rootName, required, bodyPath, enum: enumOptions, json, type}; + this._addCustomizedParameter(customizationMetadata, customizedParameter); + }); + if (secondLevelDefinition.enum) { + const {type} = secondLevelDefinition; + const {description, enumOptions} = this._mapEnum(parentDescription, secondLevelDefinition); + customizedParameter = { + name: parentName, + description, + rootName, + required: parentRequired, + bodyPath: parentName, + enum: enumOptions, + type, + }; + this._addCustomizedParameter(customizationMetadata, customizedParameter); } - - _appendSecondLevelProperty(customizationMetadata, parentName, rootName, secondLevelDefinition, parentRequired, definitions) { - let customizedParameter; - const parentDescription = secondLevelDefinition.description; - this._ensureNumberOfProperties(rootName, secondLevelDefinition.properties); - Object.keys(secondLevelDefinition.properties || []).forEach(key => { - const property = secondLevelDefinition.properties[key]; - let enumOptions = null; - const { type } = property; - let description = property.description || parentDescription; - if (property.$ref) { - const schema = this._getDefinitionSchema(property.$ref, definitions); - if (!schema.enum) { - throw new CliError('Cannot unwrap more then 2 levels deep. Please use customParameters or ' - + `set skipUnwrap for parameter ${rootName} in lib/commands/smapi/customizations/parameters.json.`); - } - enumOptions = schema.enum; - description = schema.description || description; - } - const json = this._shouldParseAsJson(property, definitions); - const bodyPath = `${parentName}${BODY_PATH_DELIMITER}${key}`; - const required = this._isRequired(secondLevelDefinition, key, parentRequired); - customizedParameter = { name: `${parentName} ${key}`, description, rootName, required, bodyPath, enum: enumOptions, json, type }; - this._addCustomizedParameter(customizationMetadata, customizedParameter); - }); - if (secondLevelDefinition.enum) { - const { type } = secondLevelDefinition; - const { description, enumOptions } = this._mapEnum(parentDescription, secondLevelDefinition); - customizedParameter = { - name: parentName, - description, - rootName, - required: parentRequired, - bodyPath: parentName, - enum: enumOptions, - type - }; - this._addCustomizedParameter(customizationMetadata, customizedParameter); - } - } - - _processNestedBodyParam(param, properties, customizationMetadata, rootName, definitions) { - this._ensureNumberOfProperties(rootName, properties); - const parentRequired = this._getDefinitionSchema(param.schema.$ref, definitions).required; - Object.keys(properties).forEach(key => { - const property = properties[key]; - const isParentRequired = parentRequired && parentRequired.includes(key); - if (property.$ref) { - const secondLevelDefinition = this._getDefinitionSchema(property.$ref, definitions); - const isRequired = this._isRequired(secondLevelDefinition, key, isParentRequired); - this._appendSecondLevelProperty(customizationMetadata, key, rootName, secondLevelDefinition, isRequired, definitions); - } else { - const { description, type } = property; - const json = this._shouldParseAsJson(property, definitions); - const parentDefinition = this._getDefinitionSchema(param.schema.$ref, definitions); - const required = this._isRequired(parentDefinition, key, isParentRequired); - const customizedParameter = { name: key, description, rootName, required, bodyPath: key, json, type }; - this._addCustomizedParameter(customizationMetadata, customizedParameter); - } - }); - } - - _ensureNumberOfProperties(parameterName, properties) { - if (properties && Object.keys(properties).length >= MAX_NESTED_PROPERTIES) { - throw new CliError(`${parameterName} - number of body properties ` - + `exceeds ${MAX_NESTED_PROPERTIES}. Please use customParameters.`); - } + } + + _processNestedBodyParam(param, properties, customizationMetadata, rootName, definitions) { + this._ensureNumberOfProperties(rootName, properties); + const parentRequired = this._getDefinitionSchema(param.schema.$ref, definitions).required; + Object.keys(properties).forEach((key) => { + const property = properties[key]; + const isParentRequired = parentRequired && parentRequired.includes(key); + if (property.$ref) { + const secondLevelDefinition = this._getDefinitionSchema(property.$ref, definitions); + const isRequired = this._isRequired(secondLevelDefinition, key, isParentRequired); + this._appendSecondLevelProperty(customizationMetadata, key, rootName, secondLevelDefinition, isRequired, definitions); + } else { + const {description, type} = property; + const json = this._shouldParseAsJson(property, definitions); + const parentDefinition = this._getDefinitionSchema(param.schema.$ref, definitions); + const required = this._isRequired(parentDefinition, key, isParentRequired); + const customizedParameter = {name: key, description, rootName, required, bodyPath: key, json, type}; + this._addCustomizedParameter(customizationMetadata, customizedParameter); + } + }); + } + + _ensureNumberOfProperties(parameterName, properties) { + if (properties && Object.keys(properties).length >= MAX_NESTED_PROPERTIES) { + throw new CliError( + `${parameterName} - number of body properties ` + `exceeds ${MAX_NESTED_PROPERTIES}. Please use customParameters.`, + ); } + } } -module.exports = { CliCustomizationProcessor, BODY_PATH_DELIMITER, ARRAY_SPLIT_DELIMITER, MAX_NESTED_PROPERTIES }; +module.exports = {CliCustomizationProcessor, BODY_PATH_DELIMITER, ARRAY_SPLIT_DELIMITER, MAX_NESTED_PROPERTIES}; diff --git a/lib/commands/smapi/customizations/aliases.json b/lib/commands/smapi/customizations/aliases.json index c082d8bf..fe14bd84 100644 --- a/lib/commands/smapi/customizations/aliases.json +++ b/lib/commands/smapi/customizations/aliases.json @@ -1,19 +1,19 @@ { - "profile": "p", - "skill-id": "s", - "isp-id": "i", - "stage": "g", - "locale": "l", - "locales": "l", - "file": "f", - "catalog-id": "c", - "validation-id": "i", - "utterance": "u", - "simulation-id": "i", - "json": "j", - "text": "t", - "certification-id": "c", - "task-name": "t", - "task-version": "v", - "keywords": "k" -} \ No newline at end of file + "profile": "p", + "skill-id": "s", + "isp-id": "i", + "stage": "g", + "locale": "l", + "locales": "l", + "file": "f", + "catalog-id": "c", + "validation-id": "i", + "utterance": "u", + "simulation-id": "i", + "json": "j", + "text": "t", + "certification-id": "c", + "task-name": "t", + "task-version": "v", + "keywords": "k" +} diff --git a/lib/commands/smapi/customizations/parameters-map.js b/lib/commands/smapi/customizations/parameters-map.js index 6e8a9d5b..0a7fef81 100644 --- a/lib/commands/smapi/customizations/parameters-map.js +++ b/lib/commands/smapi/customizations/parameters-map.js @@ -1,14 +1,14 @@ -const parameterRename = require('@src/commands/smapi/customizations/parameters.json'); +const parameterRename = require("./parameters.json"); const apiToCommanderMap = new Map(); const customizationMap = new Map(); -Object.keys(parameterRename).forEach(key => { - const value = parameterRename[key]; - customizationMap.set(key, value); - if (value.name) { - apiToCommanderMap.set(key, value.name); - } +Object.keys(parameterRename).forEach((key) => { + const value = parameterRename[key]; + customizationMap.set(key, value); + if (value.name) { + apiToCommanderMap.set(key, value.name); + } }); -module.exports = { apiToCommanderMap, customizationMap }; +module.exports = {apiToCommanderMap, customizationMap}; diff --git a/lib/commands/smapi/customizations/parameters.json b/lib/commands/smapi/customizations/parameters.json index 990d7bfb..47b11cf3 100644 --- a/lib/commands/smapi/customizations/parameters.json +++ b/lib/commands/smapi/customizations/parameters.json @@ -1,62 +1,64 @@ { - "stageV2": { - "name": "stage" - }, - "skill stage": { - "name": "stage" - }, - "skill locale": { - "name": "locale" - }, - "vendorId": { - "skip": true - }, - "version": { - "name": "vers" - }, - "createSkillRequest": { - "skipUnwrap": true, - "name": "manifest" - }, - "updateSkillRequest": { - "skipUnwrap": true, - "name": "manifest" - }, - "TestersRequest": { - "customParameters": [{ - "name": "testersEmails", - "description": "List of email address of beta testers.", - "required": true, - "isArray": true - }] - }, - "createInSkillProductRequest": { - "skipUnwrap": true - }, - "updateInSkillProductRequest": { - "skipUnwrap": true, - "name": "inSkillProduct" - }, - "CreateSubscriberRequest": { - "skipUnwrap": true - }, - "UpdateSubscriberRequest": { - "skipUnwrap": true - }, - "accountLinkingRequest": { - "skipUnwrap": true - }, - "interactionModel": { - "skipUnwrap": true - }, - "slotType": { - "skipUnwrap": true - }, - "sslCertificatePayload": { - "skipUnwrap": true - }, - "createJobDefinitionRequest": { - "skipUnwrap": true, - "name": "jobDefinition" - } -} \ No newline at end of file + "stageV2": { + "name": "stage" + }, + "skill stage": { + "name": "stage" + }, + "skill locale": { + "name": "locale" + }, + "vendorId": { + "skip": true + }, + "version": { + "name": "vers" + }, + "createSkillRequest": { + "skipUnwrap": true, + "name": "manifest" + }, + "updateSkillRequest": { + "skipUnwrap": true, + "name": "manifest" + }, + "TestersRequest": { + "customParameters": [ + { + "name": "testersEmails", + "description": "List of email address of beta testers.", + "required": true, + "isArray": true + } + ] + }, + "createInSkillProductRequest": { + "skipUnwrap": true + }, + "updateInSkillProductRequest": { + "skipUnwrap": true, + "name": "inSkillProduct" + }, + "CreateSubscriberRequest": { + "skipUnwrap": true + }, + "UpdateSubscriberRequest": { + "skipUnwrap": true + }, + "accountLinkingRequest": { + "skipUnwrap": true + }, + "interactionModel": { + "skipUnwrap": true + }, + "slotType": { + "skipUnwrap": true + }, + "sslCertificatePayload": { + "skipUnwrap": true + }, + "createJobDefinitionRequest": { + "skipUnwrap": true, + "name": "jobDefinition" + } +} diff --git a/lib/commands/smapi/smapi-command-handler.js b/lib/commands/smapi/smapi-command-handler.js index 74a58db4..3fdd328a 100644 --- a/lib/commands/smapi/smapi-command-handler.js +++ b/lib/commands/smapi/smapi-command-handler.js @@ -1,135 +1,141 @@ -const { CustomSmapiClientBuilder, ModelIntrospector } = require('ask-smapi-sdk'); -const fs = require('fs-extra'); -const R = require('ramda'); -const queryString = require('querystring'); - -const { apiToCommanderMap, customizationMap } = require('@src/commands/smapi/customizations/parameters-map'); -const AppConfig = require('@src/model/app-config'); -const AuthorizationController = require('@src/controllers/authorization-controller'); -const CONSTANTS = require('@src/utils/constants'); -const DynamicConfig = require('@src/utils/dynamic-config'); -const jsonView = require('@src/view/json-view'); -const Messenger = require('@src/view/messenger'); -const profileHelper = require('@src/utils/profile-helper'); -const unflatten = require('@src/utils/unflatten'); -const { getParamNames, standardize, canParseAsJson, kebabCase } = require('@src/utils/string-utils'); - -const BeforeSendProcessor = require('./before-send-processor'); -const { BODY_PATH_DELIMITER, ARRAY_SPLIT_DELIMITER, CliCustomizationProcessor } = require('./cli-customization-processor'); +const {CustomSmapiClientBuilder, ModelIntrospector} = require("ask-smapi-sdk"); +const fs = require("fs-extra"); +const R = require("ramda"); +const queryString = require("querystring"); + +const {apiToCommanderMap, customizationMap} = require("./customizations/parameters-map"); +const AppConfig = require("../../model/app-config"); +const AuthorizationController = require("../../controllers/authorization-controller"); +const CONSTANTS = require("../../utils/constants"); +const DynamicConfig = require("../../utils/dynamic-config"); +const jsonView = require("../../view/json-view"); +const Messenger = require("../../view/messenger"); +const profileHelper = require("../../utils/profile-helper"); +const unflatten = require("../../utils/unflatten"); +const {getParamNames, standardize, canParseAsJson, kebabCase} = require("../../utils/string-utils"); + +const BeforeSendProcessor = require("./before-send-processor"); +const {BODY_PATH_DELIMITER, ARRAY_SPLIT_DELIMITER, CliCustomizationProcessor} = require("./cli-customization-processor"); const _mapToArgs = (params, paramsObject) => { - const res = []; - params.forEach(param => { - let value = null; - Object.keys(paramsObject).forEach(k => { - if (standardize(k) === standardize(param)) { - value = paramsObject[k]; - } - }); - res.push(value); + const res = []; + params.forEach((param) => { + let value = null; + Object.keys(paramsObject).forEach((k) => { + if (standardize(k) === standardize(param)) { + value = paramsObject[k]; + } }); - return res; + res.push(value); + }); + return res; }; const _loadValue = (param, value) => { - let result = value; - if (param.json) { - const filePrefix = 'file:'; - if (value.startsWith(filePrefix)) { - const filePath = value.split(filePrefix).pop(); - const fileContent = fs.readFileSync(filePath, { encoding: 'utf8' }); - result = canParseAsJson(fileContent) ? JSON.parse(fileContent) : fileContent; - } else { - result = canParseAsJson(value) ? JSON.parse(value) : value; - } + let result = value; + if (param.json) { + const filePrefix = "file:"; + if (value.startsWith(filePrefix)) { + const filePath = value.split(filePrefix).pop(); + const fileContent = fs.readFileSync(filePath, {encoding: "utf8"}); + result = canParseAsJson(fileContent) ? JSON.parse(fileContent) : fileContent; + } else { + result = canParseAsJson(value) ? JSON.parse(value) : value; } - return result; + } + return result; }; const _mapToParams = (optionsValues, flatParamsMap, commanderToApiCustomizationMap) => { - const res = {}; - const bodyParam = Array.from(flatParamsMap.values()).find(p => p.rootName); - if (bodyParam) { - res[bodyParam.rootName] = {}; + const res = {}; + const bodyParam = Array.from(flatParamsMap.values()).find((p) => p.rootName); + if (bodyParam) { + res[bodyParam.rootName] = {}; + } + Object.keys(optionsValues).forEach((key) => { + const apiName = commanderToApiCustomizationMap.get(key) || key; + const param = flatParamsMap.get(standardize(apiName)); + if (param) { + let value = optionsValues[key]; + value = param.isArray ? value.split(ARRAY_SPLIT_DELIMITER) : value; + value = param.isNumber ? Number(value) : value; + value = param.isBoolean ? Boolean(value) : value; + if (param.rootName) { + let mergeObject = {}; + mergeObject[param.bodyPath] = _loadValue(param, value); + mergeObject = unflatten(mergeObject, BODY_PATH_DELIMITER); + res[param.rootName] = R.mergeDeepRight(res[param.rootName], mergeObject); + } else { + res[param.name] = _loadValue(param, value); + } } - Object.keys(optionsValues).forEach(key => { - const apiName = commanderToApiCustomizationMap.get(key) || key; - const param = flatParamsMap.get(standardize(apiName)); - if (param) { - let value = optionsValues[key]; - value = param.isArray ? value.split(ARRAY_SPLIT_DELIMITER) : value; - value = param.isNumber ? Number(value) : value; - value = param.isBoolean ? Boolean(value) : value; - if (param.rootName) { - let mergeObject = {}; - mergeObject[param.bodyPath] = _loadValue(param, value); - mergeObject = unflatten(mergeObject, BODY_PATH_DELIMITER); - res[param.rootName] = R.mergeDeepRight(res[param.rootName], mergeObject); - } else { - res[param.name] = _loadValue(param, value); - } - } - }); - return res; + }); + return res; }; -const _sdkFunctionName = (swaggerApiOperationName) => `call${swaggerApiOperationName.charAt(0).toUpperCase() + swaggerApiOperationName.slice(1)}`; +const _sdkFunctionName = (swaggerApiOperationName) => + `call${swaggerApiOperationName.charAt(0).toUpperCase() + swaggerApiOperationName.slice(1)}`; const _matchSwaggerPattern = (url, swaggerPatternUrl) => { - const urlParts = url.split('/'); - const swaggerParts = swaggerPatternUrl.split('/'); - if (urlParts.length !== swaggerParts.length) return false; - - const params = {}; - - for (let i = 0; i < swaggerParts.length; i++) { - const swaggerPart = swaggerParts[i]; - const urlPart = urlParts[i]; - if (swaggerPart.startsWith('{')) { - const paramName = swaggerPart.slice(0, -1).substring(1); - params[paramName] = urlPart; - continue; - } - - if (swaggerPart !== urlPart) { - return false; - } + const urlParts = url.split("/"); + const swaggerParts = swaggerPatternUrl.split("/"); + if (urlParts.length !== swaggerParts.length) return false; + + const params = {}; + + for (let i = 0; i < swaggerParts.length; i++) { + const swaggerPart = swaggerParts[i]; + const urlPart = urlParts[i]; + if (swaggerPart.startsWith("{")) { + const paramName = swaggerPart.slice(0, -1).substring(1); + params[paramName] = urlPart; + continue; + } + + if (swaggerPart !== urlPart) { + return false; } + } - return { swaggerPatternUrl, params }; + return {swaggerPatternUrl, params}; }; const _showCheckStatusHint = (locationHeader, profile) => { - const { value } = locationHeader; - const [baseUrl, queryStringPart] = value.split('?'); - const modelIntrospector = new ModelIntrospector(); - const paths = Object.keys(modelIntrospector.modelJson.paths); - let swaggerMatch; - let statusCheckHintCommand; - let parameters = {}; - for (const path of paths) { - swaggerMatch = _matchSwaggerPattern(baseUrl, path); - if (swaggerMatch) break; - } - if (swaggerMatch && modelIntrospector.modelJson.paths[swaggerMatch.swaggerPatternUrl].get) { - const operationName = modelIntrospector.modelJson.paths[swaggerMatch.swaggerPatternUrl].get['x-operation-name']; - const processor = new CliCustomizationProcessor(); - const baseCliCommand = processor.processOperationName(operationName); - const queryStringParameters = queryString.parse(queryStringPart); - parameters = { ...swaggerMatch.params, ...queryStringParameters }; - const cliParams = Object.keys(parameters).map(key => { - const customization = customizationMap.get(key); - if (customization && customization.skip) return ''; - // mapping custom command option if exists - const commandOption = kebabCase(apiToCommanderMap.get(key) || key); - return `--${commandOption} ${parameters[key]}`; - }).join(' ').trim(); - const profileFlag = profile ? ` --profile ${profile}` : ''; - statusCheckHintCommand = `ask smapi ${baseCliCommand} ${cliParams}${profileFlag}`; - Messenger.getInstance().warn(`This is an asynchronous operation. Check the progress using the following command: ${statusCheckHintCommand}`); - } else { - Messenger.getInstance().warn(`This is an asynchronous operation. Check the progress using the following url: ${value}`); - } + const {value} = locationHeader; + const [baseUrl, queryStringPart] = value.split("?"); + const modelIntrospector = new ModelIntrospector(); + const paths = Object.keys(modelIntrospector.modelJson.paths); + let swaggerMatch; + let statusCheckHintCommand; + let parameters = {}; + for (const path of paths) { + swaggerMatch = _matchSwaggerPattern(baseUrl, path); + if (swaggerMatch) break; + } + if (swaggerMatch && modelIntrospector.modelJson.paths[swaggerMatch.swaggerPatternUrl].get) { + const operationName = modelIntrospector.modelJson.paths[swaggerMatch.swaggerPatternUrl].get["x-operation-name"]; + const processor = new CliCustomizationProcessor(); + const baseCliCommand = processor.processOperationName(operationName); + const queryStringParameters = queryString.parse(queryStringPart); + parameters = {...swaggerMatch.params, ...queryStringParameters}; + const cliParams = Object.keys(parameters) + .map((key) => { + const customization = customizationMap.get(key); + if (customization && customization.skip) return ""; + // mapping custom command option if exists + const commandOption = kebabCase(apiToCommanderMap.get(key) || key); + return `--${commandOption} ${parameters[key]}`; + }) + .join(" ") + .trim(); + const profileFlag = profile ? ` --profile ${profile}` : ""; + statusCheckHintCommand = `ask smapi ${baseCliCommand} ${cliParams}${profileFlag}`; + Messenger.getInstance().warn( + `This is an asynchronous operation. Check the progress using the following command: ${statusCheckHintCommand}`, + ); + } else { + Messenger.getInstance().warn(`This is an asynchronous operation. Check the progress using the following url: ${value}`); + } }; /** @@ -137,21 +143,21 @@ const _showCheckStatusHint = (locationHeader, profile) => { * @param {Object} response object */ const parseSmapiResponse = (response, profile) => { - let result = ''; - const { body, headers, statusCode } = response; - const contentType = headers.find((h) => h.key === 'content-type'); - const locationHeader = headers.find((h) => h.key === 'location'); - // json if no content type or content type is application/json - const isJson = !contentType || contentType.value.includes('application/json'); - if (!process.env.ASK_SKIP_LOCATION_HEADER_HINT && statusCode === CONSTANTS.HTTP_REQUEST.STATUS_CODE.ACCEPTED && locationHeader) { - _showCheckStatusHint(locationHeader, profile); - } - if (body && Object.keys(body).length) { - result = isJson ? jsonView.toString(body) : body; - } else { - result = 'Command executed successfully!'; - } - return result; + let result = ""; + const {body, headers, statusCode} = response; + const contentType = headers.find((h) => h.key === "content-type"); + const locationHeader = headers.find((h) => h.key === "location"); + // json if no content type or content type is application/json + const isJson = !contentType || contentType.value.includes("application/json"); + if (statusCode === CONSTANTS.HTTP_REQUEST.STATUS_CODE.ACCEPTED && locationHeader) { + _showCheckStatusHint(locationHeader, profile); + } + if (body && Object.keys(body).length) { + result = isJson ? jsonView.toString(body) : body; + } else { + result = "Command executed successfully!"; + } + return result; }; /** @@ -165,61 +171,60 @@ const parseSmapiResponse = (response, profile) => { * @param {Object} cmdObj Commander object with passed values. */ const smapiCommandHandler = (swaggerApiOperationName, flatParamsMap, commanderToApiCustomizationMap, inputCmdObj, modelIntrospector) => { - new AppConfig(); - const inputOpts = inputCmdObj.opts(); - const authorizationController = new AuthorizationController({ - auth_client_type: 'LWA', - doDebug: inputOpts.debug + new AppConfig(); + const inputOpts = inputCmdObj.opts(); + const authorizationController = new AuthorizationController({ + auth_client_type: "LWA", + doDebug: inputOpts.debug, + }); + const profile = profileHelper.runtimeProfile(inputOpts.profile); + const refreshTokenConfig = { + clientId: authorizationController.oauthClient.config.clientId, + clientSecret: authorizationController.oauthClient.config.clientConfirmation, + refreshToken: AppConfig.getInstance().getToken(profile).refresh_token, + }; + const authEndpoint = DynamicConfig.lwaTokenHost; + const smapiEndpoint = DynamicConfig.smapiBaseUrl; + + const client = new CustomSmapiClientBuilder() + .withAuthEndpoint(authEndpoint) + .withApiEndpoint(smapiEndpoint) + .withRefreshTokenConfig(refreshTokenConfig) + .withCustomUserAgent(DynamicConfig.userAgent) + .client(); + + const paramsObject = _mapToParams(inputOpts, flatParamsMap, commanderToApiCustomizationMap); + + const beforeSendProcessor = new BeforeSendProcessor(inputCmdObj._name, paramsObject, modelIntrospector, profile); + beforeSendProcessor.processAll(); + + const functionName = _sdkFunctionName(swaggerApiOperationName); + const params = getParamNames(client[functionName]); + const args = _mapToArgs(params, paramsObject); + + if (inputOpts.debug) { + const payload = {}; + params.forEach((k, i) => { + payload[k] = args[i]; }); - const profile = profileHelper.runtimeProfile(inputOpts.profile); - const refreshTokenConfig = { - clientId: authorizationController.oauthClient.config.clientId, - clientSecret: authorizationController.oauthClient.config.clientConfirmation, - refreshToken: AppConfig.getInstance().getToken(profile).refresh_token - }; - const authEndpoint = DynamicConfig.lwaTokenHost; - const smapiEndpoint = DynamicConfig.smapiBaseUrl; - - const client = new CustomSmapiClientBuilder() - .withAuthEndpoint(authEndpoint) - .withApiEndpoint(smapiEndpoint) - .withRefreshTokenConfig(refreshTokenConfig) - .withCustomUserAgent(DynamicConfig.userAgent) - .client(); - - const paramsObject = _mapToParams(inputOpts, flatParamsMap, commanderToApiCustomizationMap); - - const beforeSendProcessor = new BeforeSendProcessor(inputCmdObj._name, paramsObject, modelIntrospector, profile); - beforeSendProcessor.processAll(); - - const functionName = _sdkFunctionName(swaggerApiOperationName); - const params = getParamNames(client[functionName]); - const args = _mapToArgs(params, paramsObject); - + Messenger.getInstance().info(`Operation: ${swaggerApiOperationName}`); + Messenger.getInstance().info("Payload:"); + Messenger.getInstance().info(`${jsonView.toString(payload)}\n`); + } + + return client[functionName](...args).then((response) => { + const {body, headers, statusCode} = response; + let result = ""; if (inputOpts.debug) { - const payload = {}; - params.forEach((k, i) => { - payload[k] = args[i]; - }); - Messenger.getInstance().info(`Operation: ${swaggerApiOperationName}`); - Messenger.getInstance().info('Payload:'); - Messenger.getInstance().info(`${jsonView.toString(payload)}\n`); + Messenger.getInstance().info("Response:"); + Messenger.getInstance().info(jsonView.toString({body, headers, statusCode})); + } else if (inputOpts.fullResponse) { + result = jsonView.toString({body, headers, statusCode}); + } else { + result = parseSmapiResponse(response, profile); } - - return client[functionName](...args) - .then(response => { - const { body, headers, statusCode } = response; - let result = ''; - if (inputOpts.debug) { - Messenger.getInstance().info('Response:'); - Messenger.getInstance().info(jsonView.toString({ body, headers, statusCode })); - } else if (inputOpts.fullResponse) { - result = jsonView.toString({ body, headers, statusCode }); - } else { - result = parseSmapiResponse(response, profile); - } - return result; - }); + return result; + }); }; -module.exports = { smapiCommandHandler, parseSmapiResponse }; +module.exports = {smapiCommandHandler, parseSmapiResponse}; diff --git a/lib/commands/smapi/smapi-commander.js b/lib/commands/smapi/smapi-commander.js deleted file mode 100644 index e901dda4..00000000 --- a/lib/commands/smapi/smapi-commander.js +++ /dev/null @@ -1,135 +0,0 @@ -const commander = require('commander'); -const { ModelIntrospector } = require('ask-smapi-sdk'); -const { kebabCase } = require('@src/utils/string-utils'); -const { CliCustomizationProcessor } = require('@src/commands/smapi/cli-customization-processor'); -const optionModel = require('@src/commands/option-model.json'); -const handler = require('@src/commands/smapi/smapi-command-handler'); -const aliases = require('@src/commands/smapi/customizations/aliases.json'); -const { apiToCommanderMap } = require('@src/commands/smapi/customizations/parameters-map'); -const metricClient = require('@src/utils/metrics'); - -const uploadCatalog = require('./appended-commands/upload-catalog'); -const exportPackage = require('./appended-commands/export-package'); -const getTask = require('./appended-commands/get-task'); -const searchTask = require('./appended-commands/search-task'); - -const defaultOptions = [ - { - flags: `-${optionModel.profile.alias}, --profile `, - description: optionModel.profile.description - }, - { - flags: '--full-response', - description: optionModel['full-response'].description - }, - { - flags: '--debug', - description: optionModel.debug.description - } -]; - -const defaultValues = new Map(); -defaultValues.set('stage', 'development'); - -const requiredTemplate = { true: '[REQUIRED]', false: '[OPTIONAL]' }; -const jsonTemplate = { true: '[JSON]: Option value is JSON string, accepts JSON file by using either:' -+ '\n- "$(cat {filePath})", use "type" command to replace "cat" command in Windows.' -+ '\n- "file:{filePath}", file descriptor with either absolute or relative file path.\n', -false: '' }; - -const _makeEnumTemplate = (param) => (param.enum ? `[ENUM]: ${param.enum.join()}.\n` : ''); -const _makeArrayTemplate = (param) => (param.isArray ? '[MULTIPLE]: Values can be separated by comma.\n' : ''); - -const _makeAlias = (kebabName) => (aliases[kebabName] ? `-${aliases[kebabName]},` : ''); - -const _makeOption = (param) => { - const name = apiToCommanderMap.get(param.name) || param.name; - const defaultValue = defaultValues.get(name); - const shouldMakeOptional = param.required && defaultValue; - if (shouldMakeOptional) { - param.required = false; - } - const paramName = kebabCase(name); - const alias = _makeAlias(paramName); - const json = param.json || false; - const enumTemplate = _makeEnumTemplate(param); - const arrayTemplate = _makeArrayTemplate(param); - return { - name: `${alias}--${paramName} <${paramName}>`, - description: - (`${requiredTemplate[param.required]} ${(param.description || '').trim()} \n` - + `${arrayTemplate}` - + `${jsonTemplate[json]}` - + `${enumTemplate} `).trim(), - defaultValue: shouldMakeOptional ? defaultValue : undefined - }; -}; -/** - * Creates commander instance for Smapi operations. - */ -const makeSmapiCommander = () => { - const customizationProcessor = new CliCustomizationProcessor(); - const modelIntrospector = new ModelIntrospector(null, customizationProcessor); - const operations = modelIntrospector.getOperations(); - - const program = new commander.Command(); - - let commanderInstance; - - operations.forEach((operation, commandName) => { - const commanderToApiCustomizationMap = new Map(); - const { apiOperationName, description } = operation; - commanderInstance = program - .command(commandName) - .description(description) - .storeOptionsAsProperties(false); - const { flatParamsMap } = operation.customizationMetadata; - flatParamsMap.forEach(param => { - const customizationValue = apiToCommanderMap.get(param.name); - if (customizationValue) { - commanderToApiCustomizationMap.set(customizationValue, param.name); - } - const option = _makeOption(param); - if (param.required) { - commanderInstance.requiredOption(option.name, option.description); - } else { - commanderInstance.option(option.name, option.description, option.defaultValue); - } - }); - - defaultOptions.forEach(option => { - commanderInstance.option(option.flags, option.description); - }); - commanderInstance.action((inputCmdObj) => { - metricClient.startAction('smapi', inputCmdObj.name()); - return handler.smapiCommandHandler( - apiOperationName, - flatParamsMap, - commanderToApiCustomizationMap, - inputCmdObj, - modelIntrospector - ).then(res => metricClient.sendData().then(() => res)) - .catch(err => metricClient.sendData(err).then(() => Promise.reject(err))); - }); - }); - - // register hand-written appended commands - uploadCatalog.createCommand(program); - exportPackage.createCommand(program); - getTask.createCommand(program); - searchTask.createCommand(program); - - program._name = 'ask smapi'; - program - .description('The smapi command provides a number of sub-commands that ' - + 'enable you to manage Alexa skills associated with your developer account.'); - - program.on('command:*', () => { - console.error(`Command not recognized. Please run "${program._name}" to check the user instructions.`); - process.exit(1); - }); - - return program; -}; - -module.exports = { makeSmapiCommander }; diff --git a/lib/commands/smapi/smapi-commander.ts b/lib/commands/smapi/smapi-commander.ts new file mode 100644 index 00000000..7d46eed1 --- /dev/null +++ b/lib/commands/smapi/smapi-commander.ts @@ -0,0 +1,198 @@ +import {Command} from "commander"; +import {ModelIntrospector} from "ask-smapi-sdk"; +import {kebabCase, camelCase} from "../../utils/string-utils"; +import {CliCustomizationProcessor} from "./cli-customization-processor"; +import optionModel from "../option-model.json"; +import {OptionModel, OptionModelEntry, validateOptionRules, validateOptionString} from "../option-validator"; +import handler from "./smapi-command-handler"; +import {apiToCommanderMap} from "./customizations/parameters-map"; +import metricClient from "../../utils/metrics"; +import aliases from "./customizations/aliases.json"; +import {createCommand as uploadCreateCommand} from "./appended-commands/upload-catalog"; +import {createCommand as exportPackageCreateCommand} from "./appended-commands/export-package"; +import {createCommand as getTaskCreateCommand} from "./appended-commands/get-task"; +import {createCommand as searchTaskCreateCommand} from "./appended-commands/search-task"; + +interface SmapiOption { + flags: string; + description: string; + defaultValue?: string; + shortName: string; + longName: string; +} + +const defaultOptions: SmapiOption[] = [ + { + flags: `-${optionModel.profile.alias}, --profile `, + description: optionModel.profile.description, + shortName: optionModel.profile.alias, + longName: "profile", + }, + { + flags: "--full-response", + description: optionModel["full-response"].description, + shortName: "", + longName: "full-response", + }, + { + flags: "--debug", + description: optionModel.debug.description, + shortName: "", + longName: "debug", + }, +]; + +const defaultValues = new Map(); +defaultValues.set("stage", "development"); + +const requiredTemplate = {true: "[REQUIRED]", false: "[OPTIONAL]"}; +const jsonTemplate = { + true: + "[JSON]: Option value is JSON string, accepts JSON file by using either:" + + '\n- "$(cat {filePath})", use "type" command to replace "cat" command in Windows.' + + '\n- "file:{filePath}", file descriptor with either absolute or relative file path.\n', + false: "", +}; + +const _makeEnumTemplate = (param: any) => (param.enum ? `[ENUM]: ${param.enum.join()}.\n` : ""); +const _makeArrayTemplate = (param: any) => (param.isArray ? "[MULTIPLE]: Values can be separated by comma.\n" : ""); + +const _makeAlias = (kebabName: keyof typeof aliases) => (aliases[kebabName] ? `-${aliases[kebabName]},` : ""); + +const _makeOption = (param: any): SmapiOption => { + const name = apiToCommanderMap.get(param.name) || param.name; + const defaultValue = defaultValues.get(name); + const shouldMakeOptional = param.required && defaultValue; + if (shouldMakeOptional) { + param.required = false; + } + const paramName = kebabCase(name); + const alias = _makeAlias(paramName); + const json: keyof typeof jsonTemplate = param.json || "false"; + const enumTemplate = _makeEnumTemplate(param); + const arrayTemplate = _makeArrayTemplate(param); + return { + flags: `${alias}--${paramName} <${paramName}>`, + description: ( + `${requiredTemplate[param.required as keyof typeof requiredTemplate]} ${(param.description || "").trim()} \n` + + `${arrayTemplate}` + + `${jsonTemplate[json]}` + + `${enumTemplate} ` + ).trim(), + defaultValue: shouldMakeOptional ? defaultValue : undefined, + shortName: alias, + longName: paramName, + }; +}; + +/** + * Simple validation for options for which rules have been defined + * @param options option-value pairs that were specified + * @param id option id to lookup and validate + * @throws error if no rules found or input was invalid + */ +const _validateOption = (options: {[key: string]: any}, id: string): void => { + const model: OptionModel = optionModel as OptionModel; + const entry: OptionModelEntry = model[id]; + if (!entry) throw `No entry with validation rules for ${id}.`; + + const optionName = camelCase(id); + try { + const value = options[optionName]; + if (value) { + if (entry.stringInput === "REQUIRED") validateOptionString(options, optionName); + // validate remaining rules + validateOptionRules(options, optionName, entry.rule); + } + } catch (error) { + throw `Please provide valid input for option: ${entry.name}. ${error}`; + } +}; + +/** + * Initialize metrics for smapi operations + * @param command the command instance + * @param optionsList the list of options + */ +const _initializeMetrics = (command: Command, optionsList: SmapiOption[]): void => { + metricClient.startAction("smapi", command.name()); + const optionsProvided = command.opts(); + optionsList.forEach((option: SmapiOption) => { + const name = option.longName, + value = optionsProvided[camelCase(name)]; + if (value === undefined) return; // option was not set + + // metric client requires input validation when storing values + try { + _validateOption(optionsProvided, name); + metricClient.setOption(name, value); + } catch (error) { + metricClient.setOption(name, ""); + } + }); +}; + +/** + * Creates commander instance for Smapi operations. + */ +export const makeSmapiCommander = () => { + const customizationProcessor = new CliCustomizationProcessor(); + const modelIntrospector = new ModelIntrospector(null, customizationProcessor); + const operations = modelIntrospector.getOperations(); + + const program = new Command(); + let commanderInstance: Command; + + operations.forEach((operation, commandName) => { + const commanderToApiCustomizationMap = new Map(); + const {apiOperationName, description} = operation; + commanderInstance = program.command(commandName).description(description).storeOptionsAsProperties(false); + const {flatParamsMap} = operation.customizationMetadata; + const optionsList: SmapiOption[] = []; + flatParamsMap.forEach((param: any) => { + const customizationValue = apiToCommanderMap.get(param.name); + if (customizationValue) { + commanderToApiCustomizationMap.set(customizationValue, param.name); + } + const option = _makeOption(param); + optionsList.push(option); + if (param.required) { + commanderInstance.requiredOption(option.flags, option.description); + } else { + commanderInstance.option(option.flags, option.description, option.defaultValue); + } + }); + + defaultOptions.forEach((option) => { + commanderInstance.option(option.flags, option.description); + optionsList.push(option); + }); + commanderInstance.action((inputCmdObj: Command) => { + _initializeMetrics(inputCmdObj, optionsList); + + return handler + .smapiCommandHandler(apiOperationName, flatParamsMap, commanderToApiCustomizationMap, inputCmdObj, modelIntrospector) + .then((res: any) => metricClient.sendData().then(() => res)) + .catch((err: any) => metricClient.sendData(err).then(() => Promise.reject(err))); + }); + }); + + // register hand-written appended commands + uploadCreateCommand(program); + exportPackageCreateCommand(program); + getTaskCreateCommand(program); + searchTaskCreateCommand(program); + + program.name("ask smapi"); + program.description( + "The smapi command provides a number of sub-commands that " + + "enable you to manage Alexa skills associated with your developer account.", + ); + + program.on("command:*", () => { + console.error(`Command not recognized. Please run "${program.name}" to check the user instructions.`); + process.exit(1); + }); + + return program; +}; diff --git a/lib/commands/smapi/smapi-docs.js b/lib/commands/smapi/smapi-docs.js index 4fe155c1..f438f1f4 100644 --- a/lib/commands/smapi/smapi-docs.js +++ b/lib/commands/smapi/smapi-docs.js @@ -1,47 +1,48 @@ -const smapiCommandDescription = 'Provides a number of subcommands that ' -+ 'map 1:1 to the underlying API operations in Alexa Skill Management API (SMAPI).' -+ 'The commands allow detailed control of API inputs and expose raw outputs. ' -+ 'There are subcommands for creating and updating the skill, interaction model, ' -+ 'and account linking information as well as starting the skill certification process.'; +const smapiCommandDescription = + "Provides a number of subcommands that " + + "map 1:1 to the underlying API operations in Alexa Skill Management API (SMAPI)." + + "The commands allow detailed control of API inputs and expose raw outputs. " + + "There are subcommands for creating and updating the skill, interaction model, " + + "and account linking information as well as starting the skill certification process."; class SmapiDocs { - constructor(commander) { - this.commander = commander; - this.commands = commander.commands; - } + constructor(commander) { + this.commander = commander; + this.commands = commander.commands; + } - _makeOptionsString(options) { - return options.map(option => { - const { mandatory, flags } = option; - const prefix = mandatory ? '<' : '['; - const suffix = mandatory ? '>' : ']'; - return `${prefix}${flags.split(',').join('|')}${suffix}`; - }).join(' '); - } + _makeOptionsString(options) { + return options + .map((option) => { + const {mandatory, flags} = option; + const prefix = mandatory ? "<" : "["; + const suffix = mandatory ? ">" : "]"; + return `${prefix}${flags.split(",").join("|")}${suffix}`; + }) + .join(" "); + } - _cleanDescription(description = '') { - let cleanedDescription = description.trim(); - if (cleanedDescription.length > 1 && !cleanedDescription.endsWith('.')) { - cleanedDescription = `${cleanedDescription}.`; - } - // adding new line before * to correctly render list in markdown - return cleanedDescription.replace('*', '\n*'); + _cleanDescription(description = "") { + let cleanedDescription = description.trim(); + if (cleanedDescription.length > 1 && !cleanedDescription.endsWith(".")) { + cleanedDescription = `${cleanedDescription}.`; } + // adding new line before * to correctly render list in markdown + return cleanedDescription.replace("*", "\n*"); + } - generateViewData() { - const commands = this.commands.map(command => { - const parsedCommand = { - name: command._name, - description: this._cleanDescription(command._description), - optionsString: this._makeOptionsString(command.options), - options: command.options.map(option => ({ name: option.flags, description: this._cleanDescription(option.description) })) - }; - return parsedCommand; - }); - return { smapiCommandDescription, - baseCommand: 'ask smapi', - commands }; - } + generateViewData() { + const commands = this.commands.map((command) => { + const parsedCommand = { + name: command._name, + description: this._cleanDescription(command._description), + optionsString: this._makeOptionsString(command.options), + options: command.options.map((option) => ({name: option.flags, description: this._cleanDescription(option.description)})), + }; + return parsedCommand; + }); + return {smapiCommandDescription, baseCommand: "ask smapi", commands}; + } } -module.exports = { SmapiDocs }; +module.exports = {SmapiDocs}; diff --git a/lib/commands/util/generate-lwa-tokens/index.js b/lib/commands/util/generate-lwa-tokens/index.js deleted file mode 100644 index db8438c7..00000000 --- a/lib/commands/util/generate-lwa-tokens/index.js +++ /dev/null @@ -1,72 +0,0 @@ -const { AbstractCommand } = require('@src/commands/abstract-command'); -const configureUi = require('@src/commands/configure/ui'); -const optionModel = require('@src/commands/option-model'); -const AuthorizationController = require('@src/controllers/authorization-controller'); -const CONSTANTS = require('@src/utils/constants'); -const jsonView = require('@src/view/json-view'); -const Messenger = require('@src/view/messenger'); - -class GenerateLwaTokensCommand extends AbstractCommand { - name() { - return 'generate-lwa-tokens'; - } - - description() { - return 'generate Login with Amazon tokens from any LWA client'; - } - - requiredOptions() { - return []; - } - - optionalOptions() { - return ['client-id', 'client-confirmation', 'scopes', 'no-browser', 'debug']; - } - - handle(cmd, cb) { - const authConfig = { - auth_client_type: 'LWA', - clientId: cmd.clientId, - clientConfirmation: cmd.clientConfirmation, - scope: cmd.scopes || CONSTANTS.LWA.DEFAULT_PUBLIC_SCOPES, - doDebug: cmd.debug - }; // redirect_url must be pre-set depending on the CLI mode and with the trusted domain - - if (cmd.browser === false) { - authConfig.redirectUri = CONSTANTS.LWA.S3_RESPONSE_PARSER_URL; - const lwaController = new AuthorizationController(authConfig); - const authorizeUrl = lwaController.getAuthorizeUrl(); - Messenger.getInstance().info(`Paste the following url to your browser:\n ${authorizeUrl}`); - configureUi.getAuthCode((uiErr, authCode) => { - if (uiErr) { - Messenger.getInstance().error(uiErr); - return cb(uiErr); - } - lwaController.getAccessTokenUsingAuthCode(authCode, (getTokenErr, accessToken) => { - if (getTokenErr) { - Messenger.getInstance().error(getTokenErr); - return cb(getTokenErr); - } - Messenger.getInstance().info('\nThe LWA tokens result:'); - Messenger.getInstance().info(jsonView.toString(accessToken)); - return cb(); - }); - }); - } else { - authConfig.redirectUri = `http://127.0.0.1:${CONSTANTS.LWA.LOCAL_PORT}/cb`; - const lwaController = new AuthorizationController(authConfig); - lwaController.getTokensByListeningOnPort((browserGetTokenErr, accessToken) => { - if (browserGetTokenErr) { - Messenger.getInstance().error(browserGetTokenErr); - return cb(browserGetTokenErr); - } - Messenger.getInstance().info('The LWA tokens result:'); - Messenger.getInstance().info(jsonView.toString(accessToken)); - cb(); - }); - } - } -} - -module.exports = GenerateLwaTokensCommand; -module.exports.createCommand = new GenerateLwaTokensCommand(optionModel).createCommand(); diff --git a/lib/commands/util/generate-lwa-tokens/index.ts b/lib/commands/util/generate-lwa-tokens/index.ts new file mode 100644 index 00000000..404a80f5 --- /dev/null +++ b/lib/commands/util/generate-lwa-tokens/index.ts @@ -0,0 +1,75 @@ +import {OptionModel} from "../../option-validator"; + +import {AbstractCommand} from "../../abstract-command"; +import configureUi from "../../configure/ui"; +import optionModel from "../../option-model.json"; +import AuthorizationController from "../../../controllers/authorization-controller"; +import CONSTANTS from "../../../utils/constants"; +import jsonView from "../../../view/json-view"; +import Messenger from "../../../view/messenger"; + +export default class GenerateLwaTokensCommand extends AbstractCommand { + name() { + return "generate-lwa-tokens"; + } + + description() { + return "generate Login with Amazon tokens from any LWA client"; + } + + requiredOptions() { + return []; + } + + optionalOptions() { + return ["client-id", "client-confirmation", "scopes", "no-browser", "debug"]; + } + + async handle(cmd: Record): Promise { + const authConfig = { + auth_client_type: "LWA", + clientId: cmd.clientId, + clientConfirmation: cmd.clientConfirmation, + scope: cmd.scopes || CONSTANTS.LWA.DEFAULT_PUBLIC_SCOPES, + doDebug: cmd.debug, + }; // redirect_url must be pre-set depending on the CLI mode and with the trusted domain + + if (cmd.browser === false) { + const lwaController = new AuthorizationController({...authConfig, redirectUri: CONSTANTS.LWA.S3_RESPONSE_PARSER_URL}); + const authorizeUrl = lwaController.getAuthorizeUrl(); + Messenger.getInstance().info(`Paste the following url to your browser:\n ${authorizeUrl}`); + return new Promise((resolve, reject) => { + configureUi.getAuthCode((uiErr: any, authCode: string) => { + if (uiErr) { + Messenger.getInstance().error(uiErr); + return reject(uiErr); + } + lwaController.getAccessTokenUsingAuthCode(authCode, (getTokenErr: any, accessToken: string) => { + if (getTokenErr) { + Messenger.getInstance().error(getTokenErr); + return reject(getTokenErr); + } + Messenger.getInstance().info("\nThe LWA tokens result:"); + Messenger.getInstance().info(jsonView.toString(accessToken)); + return resolve(); + }); + }); + }); + } else { + const lwaController = new AuthorizationController({...authConfig, redirectUri: `http://127.0.0.1:${CONSTANTS.LWA.LOCAL_PORT}/cb`}); + return new Promise((resolve, reject) => { + lwaController.getTokensByListeningOnPort((browserGetTokenErr: any, accessToken: string) => { + if (browserGetTokenErr) { + Messenger.getInstance().error(browserGetTokenErr); + return reject(browserGetTokenErr); + } + Messenger.getInstance().info("The LWA tokens result:"); + Messenger.getInstance().info(jsonView.toString(accessToken)); + resolve(); + }); + }); + } + } +} + +export const createCommand = new GenerateLwaTokensCommand(optionModel as OptionModel).createCommand(); diff --git a/lib/commands/util/git-credentials-helper/index.js b/lib/commands/util/git-credentials-helper/index.js deleted file mode 100644 index 72bf2d50..00000000 --- a/lib/commands/util/git-credentials-helper/index.js +++ /dev/null @@ -1,89 +0,0 @@ -const path = require('path'); - -const SmapiClient = require('@src/clients/smapi-client'); -const { AbstractCommand } = require('@src/commands/abstract-command'); -const optionModel = require('@src/commands/option-model'); -const ResourcesConfig = require('@src/model/resources-config'); -const CONSTANTS = require('@src/utils/constants'); -const profileHelper = require('@src/utils/profile-helper'); -const jsonView = require('@src/view/json-view'); -const Messenger = require('@src/view/messenger'); - -class GitCredentialsHelperCommand extends AbstractCommand { - name() { - return 'git-credentials-helper'; - } - - description() { - return 'gets git credentials for hosted skill repository'; - } - - requiredOptions() { - return []; - } - - optionalOptions() { - return ['profile', 'debug']; - } - - handle(cmd, cb, remaining) { - if (remaining && !['get', 'store', 'erase'].includes(remaining[0])) { - const NON_GET_OPERATION_ERR = `The ask-cli git credentials helper doesn't support operation "${remaining[0]}".`; - Messenger.getInstance().error(NON_GET_OPERATION_ERR); - return cb(NON_GET_OPERATION_ERR); - } - if (remaining && (remaining[0] === 'store' || remaining[0] === 'erase')) { - // TODO: add "erase" enhancement to clean through the entire providerchain: oskeychain, sys, local - return cb(); - } - - let profile; - try { - profile = profileHelper.runtimeProfile(cmd.profile); - new ResourcesConfig(path.join(process.cwd(), CONSTANTS.FILE_PATH.ASK_RESOURCES_JSON_CONFIG)); - } catch (err) { - Messenger.getInstance().error(err); - return cb(err); - } - - const skillId = ResourcesConfig.getInstance().getSkillId(profile); - - const smapiClient = new SmapiClient({ - profile, - doDebug: cmd.debug - }); - - smapiClient.skill.alexaHosted.getAlexaHostedSkillMetadata(skillId, (metadataErr, metaDataResponse) => { - let error = this._checkError(metadataErr, metaDataResponse); - if (error) { - return cb(error); - } - const { repository } = metaDataResponse.body.alexaHosted; - smapiClient.skill.alexaHosted.getGitCredentials(skillId, repository.url, (err, response) => { - error = this._checkError(err, response); - if (error) { - return cb(error); - } - const { repositoryCredentials } = response.body; - const output = `username=${repositoryCredentials.username}\npassword=${repositoryCredentials.password}`; - Messenger.getInstance().info(output); - cb(); - }); - }); - } - - _checkError(err, response) { - if (err) { - Messenger.getInstance().error(err); - return err; - } - if (response.statusCode >= 300) { - const error = jsonView.toString(response.body); - Messenger.getInstance().error(error); - return error; - } - } -} - -module.exports = GitCredentialsHelperCommand; -module.exports.createCommand = new GitCredentialsHelperCommand(optionModel).createCommand(); diff --git a/lib/commands/util/git-credentials-helper/index.ts b/lib/commands/util/git-credentials-helper/index.ts new file mode 100644 index 00000000..73098982 --- /dev/null +++ b/lib/commands/util/git-credentials-helper/index.ts @@ -0,0 +1,90 @@ +import path from "path"; +import SmapiClient from "../../../clients/smapi-client"; +import {AbstractCommand} from "../../abstract-command"; +import optionModel from "../../option-model.json"; +import ResourcesConfig from "../../../model/resources-config"; +import CONSTANTS from "../../../utils/constants"; +import profileHelper from "../../../utils/profile-helper"; +import jsonView from "../../../view/json-view"; +import Messenger from "../../../view/messenger"; +import {OptionModel} from "../../option-validator"; + +export default class GitCredentialsHelperCommand extends AbstractCommand { + name() { + return "git-credentials-helper"; + } + + description() { + return "gets git credentials for hosted skill repository"; + } + + requiredOptions() { + return []; + } + + optionalOptions() { + return ["profile", "debug"]; + } + + async handle(cmd: Record, remaining?: string[]): Promise { + if (remaining && !["get", "store", "erase"].includes(remaining[0])) { + const NON_GET_OPERATION_ERR = `The ask-cli git credentials helper doesn't support operation "${remaining[0]}".`; + Messenger.getInstance().error(NON_GET_OPERATION_ERR); + throw NON_GET_OPERATION_ERR; + } + if (remaining && (remaining[0] === "store" || remaining[0] === "erase")) { + // TODO: add "erase" enhancement to clean through the entire providerchain: oskeychain, sys, local + return; + } + + let profile; + try { + profile = profileHelper.runtimeProfile(cmd.profile); + new ResourcesConfig(path.join(process.cwd(), CONSTANTS.FILE_PATH.ASK_RESOURCES_JSON_CONFIG)); + } catch (err) { + Messenger.getInstance().error(err); + throw err; + } + + const skillId = ResourcesConfig.getInstance().getSkillId(profile); + + const smapiClient = new SmapiClient({ + profile, + doDebug: cmd.debug, + }); + + return new Promise((resolve, reject) => { + smapiClient.skill.alexaHosted.getAlexaHostedSkillMetadata(skillId, (metadataErr: any, metaDataResponse: any) => { + let error = this._checkError(metadataErr, metaDataResponse); + if (error) { + reject(error); + } + const {repository} = metaDataResponse.body.alexaHosted; + smapiClient.skill.alexaHosted.getGitCredentials(skillId, repository.url, (err: any, response: any) => { + error = this._checkError(err, response); + if (error) { + reject(error); + } + const {repositoryCredentials} = response.body; + const output = `username=${repositoryCredentials.username}\npassword=${repositoryCredentials.password}`; + Messenger.getInstance().info(output); + resolve(); + }); + }); + }); + } + + _checkError(err: any, response: any) { + if (err) { + Messenger.getInstance().error(err); + return err; + } + if (response.statusCode >= 300) { + const error = jsonView.toString(response.body); + Messenger.getInstance().error(error); + return error; + } + } +} + +export const createCommand = new GitCredentialsHelperCommand(optionModel as OptionModel).createCommand(); diff --git a/lib/commands/util/upgrade-project/helper.js b/lib/commands/util/upgrade-project/helper.js index 1e9689dc..432ab69b 100644 --- a/lib/commands/util/upgrade-project/helper.js +++ b/lib/commands/util/upgrade-project/helper.js @@ -1,44 +1,44 @@ -const fs = require('fs-extra'); -const path = require('path'); -const R = require('ramda'); +const fs = require("fs-extra"); +const path = require("path"); +const R = require("ramda"); -const SkillMetadataController = require('@src/controllers/skill-metadata-controller'); -const awsUtil = require('@src/clients/aws-client/aws-util'); -const CliError = require('@src/exceptions/cli-error'); -const ResourcesConfig = require('@src/model/resources-config'); -const AskResources = require('@src/model/resources-config/ask-resources'); -const AskStates = require('@src/model/resources-config/ask-states'); -const Messenger = require('@src/view/messenger'); -const CONSTANTS = require('@src/utils/constants'); -const stringUtils = require('@src/utils/string-utils'); -const hashUtils = require('@src/utils/hash-utils'); -const urlUtils = require('@src/utils/url-utils'); +const SkillMetadataController = require("../../../controllers/skill-metadata-controller"); +const awsUtil = require("../../../clients/aws-client/aws-util"); +const CliError = require("../../../exceptions/cli-error"); +const ResourcesConfig = require("../../../model/resources-config"); +const AskResources = require("../../../model/resources-config/ask-resources"); +const AskStates = require("../../../model/resources-config/ask-states"); +const Messenger = require("../../../view/messenger"); +const CONSTANTS = require("../../../utils/constants"); +const stringUtils = require("../../../utils/string-utils"); +const hashUtils = require("../../../utils/hash-utils"); +const urlUtils = require("../../../utils/url-utils"); -const ui = require('./ui'); +const ui = require("./ui"); module.exports = { - loadV1ProjConfig, - extractUpgradeInformation, - previewUpgrade, - moveOldProjectToLegacyFolder, - createV2ProjectSkeletonAndLoadModel, - downloadSkillPackage, - handleExistingLambdaCode, - attemptUpgradeUndeployedProject + loadV1ProjConfig, + extractUpgradeInformation, + previewUpgrade, + moveOldProjectToLegacyFolder, + createV2ProjectSkeletonAndLoadModel, + downloadSkillPackage, + handleExistingLambdaCode, + attemptUpgradeUndeployedProject, }; function loadV1ProjConfig(v1RootPath, profile) { - const hiddenConfigPath = path.join(v1RootPath, CONSTANTS.FILE_PATH.HIDDEN_ASK_FOLDER, 'config'); - if (!fs.existsSync(hiddenConfigPath)) { - throw new CliError('Failed to find ask-cli v1 project. Please make sure this command is called at the root of the skill project.'); - } - const v1Config = fs.readJSONSync(hiddenConfigPath, 'utf-8'); - if (!R.hasPath(['deploy_settings', profile], v1Config)) { - throw new CliError(`Profile [${profile}] is not configured in the v1 ask-cli's project. \ + const hiddenConfigPath = path.join(v1RootPath, CONSTANTS.FILE_PATH.HIDDEN_ASK_FOLDER, "config"); + if (!fs.existsSync(hiddenConfigPath)) { + throw new CliError("Failed to find ask-cli v1 project. Please make sure this command is called at the root of the skill project."); + } + const v1Config = fs.readJSONSync(hiddenConfigPath, "utf-8"); + if (!R.hasPath(["deploy_settings", profile], v1Config)) { + throw new CliError(`Profile [${profile}] is not configured in the v1 ask-cli's project. \ Please check ".ask/config" file and run again with the existing profile.`); - } - const isDeployed = stringUtils.isNonBlankString(R.view(R.lensPath(['deploy_settings', profile, 'skill_id']), v1Config)) || false; - return { v1Config, isDeployed }; + } + const isDeployed = stringUtils.isNonBlankString(R.view(R.lensPath(["deploy_settings", profile, "skill_id"]), v1Config)) || false; + return {v1Config, isDeployed}; } /** @@ -50,85 +50,85 @@ Please check ".ask/config" file and run again with the existing profile.`); * @throws validationError */ function extractUpgradeInformation(v1Config, profile) { - // 1.check v1 .ask/config exists - const v1ProjData = { - skillId: R.view(R.lensPath(['deploy_settings', profile, 'skill_id']), v1Config), - isHosted: R.view(R.lensPath(['alexaHosted', 'isAlexaHostedSkill']), v1Config) || false, - lambdaList: R.view(R.lensPath(['deploy_settings', profile, 'resources', 'lambda']), v1Config) || [] - }; - // 2.check if skillId exists - if (!stringUtils.isNonBlankString(v1ProjData.skillId)) { - throw new CliError(`Failed to find skill_id for profile [${profile}]. \ + // 1.check v1 .ask/config exists + const v1ProjData = { + skillId: R.view(R.lensPath(["deploy_settings", profile, "skill_id"]), v1Config), + isHosted: R.view(R.lensPath(["alexaHosted", "isAlexaHostedSkill"]), v1Config) || false, + lambdaList: R.view(R.lensPath(["deploy_settings", profile, "resources", "lambda"]), v1Config) || [], + }; + // 2.check if skillId exists + if (!stringUtils.isNonBlankString(v1ProjData.skillId)) { + throw new CliError(`Failed to find skill_id for profile [${profile}]. \ If the skill has never been deployed in v1 ask-cli, please start from v2 structure.`); - } - if (v1ProjData.isHosted) { - // 3. check git credentials - const hostInfo = R.view(R.lensPath(['alexaHosted', 'gitCredentialsCache']), v1Config); - if (!hostInfo) { - throw new CliError('Failed to find gitCredentialsCache for an Alexa hosted skill.'); - } - return { - skillId: v1ProjData.skillId, - isHosted: v1ProjData.isHosted, - gitRepoUrl: `${hostInfo.protocol}://${hostInfo.host}/${hostInfo.path}` - }; - } - - // 3.resolve Lambda codebase for each region - const lambdaMapByRegion = {}; - for (const lambdaResource of v1ProjData.lambdaList) { - _collectLambdaMapFromResource(lambdaMapByRegion, lambdaResource); + } + if (v1ProjData.isHosted) { + // 3. check git credentials + const hostInfo = R.view(R.lensPath(["alexaHosted", "gitCredentialsCache"]), v1Config); + if (!hostInfo) { + throw new CliError("Failed to find gitCredentialsCache for an Alexa hosted skill."); } return { - skillId: v1ProjData.skillId, - lambdaResources: lambdaMapByRegion + skillId: v1ProjData.skillId, + isHosted: v1ProjData.isHosted, + gitRepoUrl: `${hostInfo.protocol}://${hostInfo.host}/${hostInfo.path}`, }; + } + + // 3.resolve Lambda codebase for each region + const lambdaMapByRegion = {}; + for (const lambdaResource of v1ProjData.lambdaList) { + _collectLambdaMapFromResource(lambdaMapByRegion, lambdaResource); + } + return { + skillId: v1ProjData.skillId, + lambdaResources: lambdaMapByRegion, + }; } function _collectLambdaMapFromResource(lambdaMapByRegion, lambdaResource) { - const { alexaUsage, arn, codeUri, runtime, handler, revisionId } = _validateLambdaResource(lambdaResource); - if (!urlUtils.isLambdaArn(arn)) { - Messenger.getInstance().warn(`Skip Lambda resource with alexaUsage "${lambdaResource.alexaUsage}" since this Lambda is not deployed.`); - return; - } - for (let index = 0; index < alexaUsage.length; index++) { - const region = alexaUsage[index].split('/')[1]; - // make sure there aren't multiple codebases for a single region - if (lambdaMapByRegion[region]) { - if (lambdaMapByRegion[region].codeUri !== codeUri) { - Messenger.getInstance().warn(`Currently ask-cli requires one Lambda codebase per region. \ + const {alexaUsage, arn, codeUri, runtime, handler, revisionId} = _validateLambdaResource(lambdaResource); + if (!urlUtils.isLambdaArn(arn)) { + Messenger.getInstance().warn(`Skip Lambda resource with alexaUsage "${lambdaResource.alexaUsage}" since this Lambda is not deployed.`); + return; + } + for (let index = 0; index < alexaUsage.length; index++) { + const region = alexaUsage[index].split("/")[1]; + // make sure there aren't multiple codebases for a single region + if (lambdaMapByRegion[region]) { + if (lambdaMapByRegion[region].codeUri !== codeUri) { + Messenger.getInstance().warn(`Currently ask-cli requires one Lambda codebase per region. \ You have multiple Lambda codebases for region ${region}, we will use "${lambdaMapByRegion[region].codeUri}" as the codebase for this region.`); - } - } else { - // set Lambda info for each alexaRegion and only re-use the Lambda ARN for the first alexaRegion (let the rest create their own Lambda) - const v2CodeUri = `.${path.sep}${CONSTANTS.FILE_PATH.SKILL_CODE.LAMBDA}${path.sep}${stringUtils.filterNonAlphanumeric(codeUri)}`; - lambdaMapByRegion[region] = { - arn: index === 0 ? arn : undefined, - codeUri, - v2CodeUri, - runtime: index === 0 ? runtime : undefined, - handler: index === 0 ? handler : undefined, - revisionId: index === 0 ? revisionId : undefined, - }; - } + } + } else { + // set Lambda info for each alexaRegion and only re-use the Lambda ARN for the first alexaRegion (let the rest create their own Lambda) + const v2CodeUri = `.${path.sep}${CONSTANTS.FILE_PATH.SKILL_CODE.LAMBDA}${path.sep}${stringUtils.filterNonAlphanumeric(codeUri)}`; + lambdaMapByRegion[region] = { + arn: index === 0 ? arn : undefined, + codeUri, + v2CodeUri, + runtime: index === 0 ? runtime : undefined, + handler: index === 0 ? handler : undefined, + revisionId: index === 0 ? revisionId : undefined, + }; } + } } function _validateLambdaResource(lambdaResource) { - const { alexaUsage, codeUri, runtime, handler } = lambdaResource; - if (!alexaUsage || alexaUsage.length === 0) { - throw new CliError('Please make sure your alexaUsage is not empty.'); - } - if (!stringUtils.isNonBlankString(codeUri)) { - throw new CliError('Please make sure your codeUri is set to the path of your Lambda code.'); - } - if (!stringUtils.isNonBlankString(runtime)) { - throw new CliError(`Please make sure your runtime for codeUri ${codeUri} is set.`); - } - if (!stringUtils.isNonBlankString(handler)) { - throw new CliError(`Please make sure your handler for codeUri ${codeUri} is set.`); - } - return lambdaResource; + const {alexaUsage, codeUri, runtime, handler} = lambdaResource; + if (!alexaUsage || alexaUsage.length === 0) { + throw new CliError("Please make sure your alexaUsage is not empty."); + } + if (!stringUtils.isNonBlankString(codeUri)) { + throw new CliError("Please make sure your codeUri is set to the path of your Lambda code."); + } + if (!stringUtils.isNonBlankString(runtime)) { + throw new CliError(`Please make sure your runtime for codeUri ${codeUri} is set.`); + } + if (!stringUtils.isNonBlankString(handler)) { + throw new CliError(`Please make sure your handler for codeUri ${codeUri} is set.`); + } + return lambdaResource; } /** @@ -137,10 +137,10 @@ function _validateLambdaResource(lambdaResource) { * @param {callback} callback { err, previewConfirm } */ function previewUpgrade(upgradeInfo, callback) { - ui.displayPreview(upgradeInfo); - ui.confirmPreview((confirmErr, previewConfirm) => { - callback(confirmErr, confirmErr ? null : previewConfirm); - }); + ui.displayPreview(upgradeInfo); + ui.confirmPreview((confirmErr, previewConfirm) => { + callback(confirmErr, confirmErr ? null : previewConfirm); + }); } /** @@ -148,16 +148,16 @@ function previewUpgrade(upgradeInfo, callback) { * @param {string} v1RootPath the v1 root path */ function moveOldProjectToLegacyFolder(v1RootPath) { - const oldFiles = fs.readdirSync(v1RootPath); - const legacyPath = path.join(v1RootPath, CONSTANTS.FILE_PATH.LEGACY_PATH); - fs.ensureDirSync(legacyPath); - oldFiles.forEach((file) => { - if (file.startsWith('.') && file !== '.ask') { - return; - } - const filePathInLegacy = path.join(legacyPath, file); - fs.moveSync(file, filePathInLegacy); - }); + const oldFiles = fs.readdirSync(v1RootPath); + const legacyPath = path.join(v1RootPath, CONSTANTS.FILE_PATH.LEGACY_PATH); + fs.ensureDirSync(legacyPath); + oldFiles.forEach((file) => { + if (file.startsWith(".") && file !== ".ask") { + return; + } + const filePathInLegacy = path.join(legacyPath, file); + fs.moveSync(file, filePathInLegacy); + }); } /** @@ -167,29 +167,29 @@ function moveOldProjectToLegacyFolder(v1RootPath) { * @param {String} profile the profile */ function createV2ProjectSkeletonAndLoadModel(rootPath, skillId, profile) { - // prepare skill package folder - const skillPackagePath = path.join(rootPath, CONSTANTS.FILE_PATH.SKILL_PACKAGE.PACKAGE); - fs.ensureDirSync(skillPackagePath); - // prepare skill code folder - const skillCodePath = path.join(rootPath, CONSTANTS.FILE_PATH.SKILL_CODE.LAMBDA); - fs.ensureDirSync(skillCodePath); - // prepare resources config - const askResourcesFilePath = path.join(rootPath, CONSTANTS.FILE_PATH.ASK_RESOURCES_JSON_CONFIG); - const askStatesFilePath = path.join(rootPath, CONSTANTS.FILE_PATH.HIDDEN_ASK_FOLDER, CONSTANTS.FILE_PATH.ASK_STATES_JSON_CONFIG); - const askResources = R.clone(AskResources.BASE); - askResources.profiles[profile] = { - skillMetadata: {}, - code: {} - }; - const askStates = R.clone(AskStates.BASE); - askStates.profiles[profile] = { - skillId, - skillMetadata: {}, - code: {} - }; - AskResources.withContent(askResourcesFilePath, askResources); - AskStates.withContent(askStatesFilePath, askStates); - new ResourcesConfig(askResourcesFilePath); + // prepare skill package folder + const skillPackagePath = path.join(rootPath, CONSTANTS.FILE_PATH.SKILL_PACKAGE.PACKAGE); + fs.ensureDirSync(skillPackagePath); + // prepare skill code folder + const skillCodePath = path.join(rootPath, CONSTANTS.FILE_PATH.SKILL_CODE.LAMBDA); + fs.ensureDirSync(skillCodePath); + // prepare resources config + const askResourcesFilePath = path.join(rootPath, CONSTANTS.FILE_PATH.ASK_RESOURCES_JSON_CONFIG); + const askStatesFilePath = path.join(rootPath, CONSTANTS.FILE_PATH.HIDDEN_ASK_FOLDER, CONSTANTS.FILE_PATH.ASK_STATES_JSON_CONFIG); + const askResources = R.clone(AskResources.BASE); + askResources.profiles[profile] = { + skillMetadata: {}, + code: {}, + }; + const askStates = R.clone(AskStates.BASE); + askStates.profiles[profile] = { + skillId, + skillMetadata: {}, + code: {}, + }; + AskResources.withContent(askResourcesFilePath, askResources); + AskStates.withContent(askStatesFilePath, askStates); + new ResourcesConfig(askResourcesFilePath); } /** @@ -202,21 +202,21 @@ function createV2ProjectSkeletonAndLoadModel(rootPath, skillId, profile) { * @param {callback} callback { err } */ function downloadSkillPackage(rootPath, skillId, skillStage, profile, doDebug, callback) { - const skillMetaController = new SkillMetadataController({ profile, doDebug }); - skillMetaController.getSkillPackage(rootPath, skillId, skillStage, (packageErr) => { - if (packageErr) { - return callback(`Failed to retrieve the skill-package for skillId: ${skillId}.\n${packageErr}`); - } - hashUtils.getHash(CONSTANTS.FILE_PATH.SKILL_PACKAGE.PACKAGE, (hashErr, currentHash) => { - if (hashErr) { - return callback(hashErr); - } - ResourcesConfig.getInstance().setSkillMetaSrc(profile, './skill-package'); - ResourcesConfig.getInstance().setSkillMetaLastDeployHash(profile, currentHash); - ResourcesConfig.getInstance().write(); - callback(); - }); + const skillMetaController = new SkillMetadataController({profile, doDebug}); + skillMetaController.getSkillPackage(rootPath, skillId, skillStage, (packageErr) => { + if (packageErr) { + return callback(`Failed to retrieve the skill-package for skillId: ${skillId}.\n${packageErr}`); + } + hashUtils.getHash(CONSTANTS.FILE_PATH.SKILL_PACKAGE.PACKAGE, (hashErr, currentHash) => { + if (hashErr) { + return callback(hashErr); + } + ResourcesConfig.getInstance().setSkillMetaSrc(profile, "./skill-package"); + ResourcesConfig.getInstance().setSkillMetaLastDeployHash(profile, currentHash); + ResourcesConfig.getInstance().write(); + callback(); }); + }); } /** @@ -227,124 +227,124 @@ function downloadSkillPackage(rootPath, skillId, skillStage, profile, doDebug, c * @param {String} profile the profile */ function handleExistingLambdaCode(rootPath, lambdaResourcesMap, profile) { - // 1.update skill infra type - ResourcesConfig.getInstance().setSkillInfraType(profile, CONSTANTS.DEPLOYER_TYPE.LAMBDA.NAME); - // 2.set userConfig from default region Lambda configuration - // default will always exist as it's required in a set of valid Lambda resources from the v1 project - let defaultRuntime, defaultHandler; - if (lambdaResourcesMap.default) { - const { runtime, handler } = lambdaResourcesMap.default; - defaultRuntime = runtime; - defaultHandler = handler; - const awsProfile = awsUtil.getAWSProfile(profile); - const awsDefaultRegion = awsUtil.getCLICompatibleDefaultRegion(awsProfile); // use system default Lambda regardless of Lambda ARN - const userConfig = { runtime, handler, awsRegion: awsDefaultRegion }; + // 1.update skill infra type + ResourcesConfig.getInstance().setSkillInfraType(profile, CONSTANTS.DEPLOYER_TYPE.LAMBDA.NAME); + // 2.set userConfig from default region Lambda configuration + // default will always exist as it's required in a set of valid Lambda resources from the v1 project + let defaultRuntime, defaultHandler; + if (lambdaResourcesMap.default) { + const {runtime, handler} = lambdaResourcesMap.default; + defaultRuntime = runtime; + defaultHandler = handler; + const awsProfile = awsUtil.getAWSProfile(profile); + const awsDefaultRegion = awsUtil.getCLICompatibleDefaultRegion(awsProfile); // use system default Lambda regardless of Lambda ARN + const userConfig = {runtime, handler, awsRegion: awsDefaultRegion}; + ResourcesConfig.getInstance().setSkillInfraUserConfig(profile, userConfig); + } + // 3.copy Lambda code from legacy folder and set deployState for each region + const legacyFolderPath = path.join(rootPath, CONSTANTS.FILE_PATH.LEGACY_PATH); + R.keys(lambdaResourcesMap).forEach((region) => { + const {arn, codeUri, v2CodeUri, runtime, handler, revisionId} = lambdaResourcesMap[region]; + // 3.1 copy code from v1 project to v2 + const v1CodePath = path.join(legacyFolderPath, codeUri); + const v2CodePath = path.join(rootPath, v2CodeUri); + fs.copySync(v1CodePath, v2CodePath); + // 3.2 update skill code setting + ResourcesConfig.getInstance().setCodeSrcByRegion(profile, region, path.relative(rootPath, v2CodePath)); + // 3.3 update regional skill infrastructure deployState + const deployState = ResourcesConfig.getInstance().getSkillInfraDeployState(profile) || {}; + deployState[region] = { + lambda: { + arn, + revisionId, + }, + }; + ResourcesConfig.getInstance().setSkillInfraDeployState(profile, deployState); + // 3.4 update skill infra userConfig with regionalOverrides excluding default region + if (region !== "default") { + if (defaultRuntime !== runtime || defaultHandler !== handler) { + const userConfig = ResourcesConfig.getInstance().getSkillInfraUserConfig(profile); + if (!userConfig.regionalOverrides) { + userConfig.regionalOverrides = {}; + } + userConfig.regionalOverrides[region] = {runtime, handler}; ResourcesConfig.getInstance().setSkillInfraUserConfig(profile, userConfig); + } } - // 3.copy Lambda code from legacy folder and set deployState for each region - const legacyFolderPath = path.join(rootPath, CONSTANTS.FILE_PATH.LEGACY_PATH); - R.keys(lambdaResourcesMap).forEach((region) => { - const { arn, codeUri, v2CodeUri, runtime, handler, revisionId } = lambdaResourcesMap[region]; - // 3.1 copy code from v1 project to v2 - const v1CodePath = path.join(legacyFolderPath, codeUri); - const v2CodePath = path.join(rootPath, v2CodeUri); - fs.copySync(v1CodePath, v2CodePath); - // 3.2 update skill code setting - ResourcesConfig.getInstance().setCodeSrcByRegion(profile, region, path.relative(rootPath, v2CodePath)); - // 3.3 update regional skill infrastructure deployState - const deployState = ResourcesConfig.getInstance().getSkillInfraDeployState(profile) || {}; - deployState[region] = { - lambda: { - arn, - revisionId - } - }; - ResourcesConfig.getInstance().setSkillInfraDeployState(profile, deployState); - // 3.4 update skill infra userConfig with regionalOverrides excluding default region - if (region !== 'default') { - if (defaultRuntime !== runtime || defaultHandler !== handler) { - const userConfig = ResourcesConfig.getInstance().getSkillInfraUserConfig(profile); - if (!userConfig.regionalOverrides) { - userConfig.regionalOverrides = {}; - } - userConfig.regionalOverrides[region] = { runtime, handler }; - ResourcesConfig.getInstance().setSkillInfraUserConfig(profile, userConfig); - } - } - }); - ResourcesConfig.getInstance().write(); + }); + ResourcesConfig.getInstance().write(); } function attemptUpgradeUndeployedProject(v1RootPath, v1Config, profile) { - const skillJsonPath = path.join(v1RootPath, CONSTANTS.FILE_PATH.SKILL_PACKAGE.MANIFEST); - if (!fs.existsSync(skillJsonPath)) { - throw new CliError('Unable to upgrade the project. skill.json file must exist.'); - } - // 1.extract codebase path and runtime - let skillJson = fs.readJSONSync(skillJsonPath, 'utf-8'); - if (skillJson.skillManifest) { - // some templates still use "skillManifest" which is the v0 manifest structure - skillJson.manifest = R.clone(skillJson.skillManifest); - skillJson = R.omit(['skillManifest'], skillJson); - } - const apisCustom = R.view(R.lensPath(['manifest', 'apis', 'custom']), skillJson); - const lambdaResources = R.view(R.lensPath(['deploy_settings', profile, 'resources', 'lambda']), v1Config); - const askResourcesJson = _decideAskResourcesJson(apisCustom, lambdaResources, profile); - // 2.re-arrange the project structure - fs.removeSync(path.join(v1RootPath, CONSTANTS.FILE_PATH.HIDDEN_ASK_FOLDER)); - fs.removeSync(path.join(v1RootPath, 'hooks')); - fs.writeJSONSync(path.join(v1RootPath, CONSTANTS.FILE_PATH.ASK_RESOURCES_JSON_CONFIG), askResourcesJson); - // upgrade to skill package format: skill, iModel, isps - const skillPackagePath = path.join(v1RootPath, CONSTANTS.FILE_PATH.SKILL_PACKAGE.PACKAGE); - fs.mkdirpSync(skillPackagePath); - skillJson.manifest.apis.custom = R.omit(['endpoint'], skillJson.manifest.apis.custom); - fs.writeJSONSync(path.join(skillPackagePath, CONSTANTS.FILE_PATH.SKILL_PACKAGE.MANIFEST), skillJson); - fs.removeSync(skillJsonPath); - const modelsPath = path.join(v1RootPath, 'models'); - if (fs.existsSync(modelsPath)) { - fs.moveSync(modelsPath, path.join(skillPackagePath, 'interactionModels', 'custom')); - } - const ispsPath = path.join(v1RootPath, 'isps'); - if (fs.existsSync(ispsPath)) { - fs.moveSync(ispsPath, path.join(skillPackagePath, 'isps')); - } + const skillJsonPath = path.join(v1RootPath, CONSTANTS.FILE_PATH.SKILL_PACKAGE.MANIFEST); + if (!fs.existsSync(skillJsonPath)) { + throw new CliError("Unable to upgrade the project. skill.json file must exist."); + } + // 1.extract codebase path and runtime + let skillJson = fs.readJSONSync(skillJsonPath, "utf-8"); + if (skillJson.skillManifest) { + // some templates still use "skillManifest" which is the v0 manifest structure + skillJson.manifest = R.clone(skillJson.skillManifest); + skillJson = R.omit(["skillManifest"], skillJson); + } + const apisCustom = R.view(R.lensPath(["manifest", "apis", "custom"]), skillJson); + const lambdaResources = R.view(R.lensPath(["deploy_settings", profile, "resources", "lambda"]), v1Config); + const askResourcesJson = _decideAskResourcesJson(apisCustom, lambdaResources, profile); + // 2.re-arrange the project structure + fs.removeSync(path.join(v1RootPath, CONSTANTS.FILE_PATH.HIDDEN_ASK_FOLDER)); + fs.removeSync(path.join(v1RootPath, "hooks")); + fs.writeJSONSync(path.join(v1RootPath, CONSTANTS.FILE_PATH.ASK_RESOURCES_JSON_CONFIG), askResourcesJson); + // upgrade to skill package format: skill, iModel, isps + const skillPackagePath = path.join(v1RootPath, CONSTANTS.FILE_PATH.SKILL_PACKAGE.PACKAGE); + fs.mkdirpSync(skillPackagePath); + skillJson.manifest.apis.custom = R.omit(["endpoint"], skillJson.manifest.apis.custom); + fs.writeJSONSync(path.join(skillPackagePath, CONSTANTS.FILE_PATH.SKILL_PACKAGE.MANIFEST), skillJson); + fs.removeSync(skillJsonPath); + const modelsPath = path.join(v1RootPath, "models"); + if (fs.existsSync(modelsPath)) { + fs.moveSync(modelsPath, path.join(skillPackagePath, "interactionModels", "custom")); + } + const ispsPath = path.join(v1RootPath, "isps"); + if (fs.existsSync(ispsPath)) { + fs.moveSync(ispsPath, path.join(skillPackagePath, "isps")); + } } function _decideAskResourcesJson(apisCustom, lambdaResources, profile) { - if (!apisCustom || !apisCustom.endpoint) { - throw new CliError('Invalid v1 project without "apis.custom.endpoint" field set in skill.json.'); + if (!apisCustom || !apisCustom.endpoint) { + throw new CliError('Invalid v1 project without "apis.custom.endpoint" field set in skill.json.'); + } + // decide runtime and handler + let runtime = "nodejs16.x"; + let handler = "index.handler"; + if (lambdaResources) { + for (const lambda of lambdaResources) { + if (lambda.alexaUsage && lambda.alexaUsage.includes("custom/default")) { + runtime = lambda.runtime; + handler = lambda.handler; + break; + } } - // decide runtime and handler - let runtime = 'nodejs12.x'; - let handler = 'index.handler'; - if (lambdaResources) { - for (const lambda of lambdaResources) { - if (lambda.alexaUsage && lambda.alexaUsage.includes('custom/default')) { - runtime = lambda.runtime; - handler = lambda.handler; - break; - } - } - } - // form askResources json object - const askResources = R.clone(AskResources.BASE); - askResources.profiles[profile] = { - skillMetadata: { - src: `./${CONSTANTS.FILE_PATH.SKILL_PACKAGE.PACKAGE}` - }, - code: { - default: { - src: apisCustom.endpoint.sourceDir - } - }, - skillInfrastructure: { - type: CONSTANTS.DEPLOYER_TYPE.LAMBDA.NAME, - userConfig: { - awsRegion: awsUtil.getCLICompatibleDefaultRegion(awsUtil.getAWSProfile(profile)), - runtime, - handler - } - } - }; - return askResources; + } + // form askResources json object + const askResources = R.clone(AskResources.BASE); + askResources.profiles[profile] = { + skillMetadata: { + src: `./${CONSTANTS.FILE_PATH.SKILL_PACKAGE.PACKAGE}`, + }, + code: { + default: { + src: apisCustom.endpoint.sourceDir, + }, + }, + skillInfrastructure: { + type: CONSTANTS.DEPLOYER_TYPE.LAMBDA.NAME, + userConfig: { + awsRegion: awsUtil.getCLICompatibleDefaultRegion(awsUtil.getAWSProfile(profile)), + runtime, + handler, + }, + }, + }; + return askResources; } diff --git a/lib/commands/util/upgrade-project/hosted-skill-helper.js b/lib/commands/util/upgrade-project/hosted-skill-helper.js index 2bf3088c..93cc3eab 100644 --- a/lib/commands/util/upgrade-project/hosted-skill-helper.js +++ b/lib/commands/util/upgrade-project/hosted-skill-helper.js @@ -1,23 +1,23 @@ -const fs = require('fs-extra'); -const os = require('os'); -const path = require('path'); -const R = require('ramda'); +const fs = require("fs-extra"); +const os = require("os"); +const path = require("path"); +const R = require("ramda"); -const HostedSkillController = require('@src/controllers/hosted-skill-controller'); -const SkillMetadataController = require('@src/controllers/skill-metadata-controller'); -const CliError = require('@src/exceptions/cli-error'); -const ResourcesConfig = require('@src/model/resources-config'); -const AskResources = require('@src/model/resources-config/ask-resources'); -const AskStates = require('@src/model/resources-config/ask-states'); -const CONSTANTS = require('@src/utils/constants'); -const stringUtils = require('@src/utils/string-utils'); +const HostedSkillController = require("../../../controllers/hosted-skill-controller"); +const SkillMetadataController = require("../../../controllers/skill-metadata-controller"); +const CliError = require("../../../exceptions/cli-error"); +const ResourcesConfig = require("../../../model/resources-config"); +const AskResources = require("../../../model/resources-config/ask-resources"); +const AskStates = require("../../../model/resources-config/ask-states"); +const CONSTANTS = require("../../../utils/constants"); +const stringUtils = require("../../../utils/string-utils"); module.exports = { - checkIfDevBranchClean, - createV2ProjectSkeletonAndLoadModel, - downloadSkillPackage, - handleExistingLambdaCode, - postUpgradeGitSetup + checkIfDevBranchClean, + createV2ProjectSkeletonAndLoadModel, + downloadSkillPackage, + handleExistingLambdaCode, + postUpgradeGitSetup, }; /** @@ -25,28 +25,29 @@ module.exports = { * @param {Object} gitClient the git client */ function checkIfDevBranchClean(gitClient) { - gitClient.checkoutBranch('dev'); - const statusOutput = gitClient.shortStatus(); - if (statusOutput.toString()) { - throw new CliError(`Commit the following files in the dev branch before upgrading project:\n${statusOutput}`); - } - try { - _compareCommitsWithDev(gitClient, 'origin/dev'); - _compareCommitsWithDev(gitClient, 'master'); - } catch (error) { - throw error.message; - } + gitClient.checkoutBranch("dev"); + const statusOutput = gitClient.shortStatus(); + if (statusOutput.toString()) { + throw new CliError(`Commit the following files in the dev branch before upgrading project:\n${statusOutput}`); + } + try { + _compareCommitsWithDev(gitClient, "origin/dev"); + _compareCommitsWithDev(gitClient, "master"); + } catch (error) { + throw error.message; + } } function _compareCommitsWithDev(gitClient, branch) { - const upgradeInstruction = 'Please follow the project upgrade instruction from ' - + 'https://github.com/alexa/ask-cli/blob/develop/docs/Upgrade-Project-From-V1.md#upgrade-steps ' - + 'to clean your working branch before upgrading project.'; - let diffCount = gitClient.countCommitDifference(branch, 'dev'); - diffCount = diffCount.toString().replace(/\D/g, ''); - if (stringUtils.isNonBlankString(diffCount) && diffCount !== '0') { - throw new CliError(`Upgrade project failed. Your branch is ahead of ${branch} by ${diffCount} commit(s), ${upgradeInstruction}`); - } + const upgradeInstruction = + "Please follow the project upgrade instruction from " + + "https://github.com/alexa/ask-cli/blob/develop/docs/Upgrade-Project-From-V1.md#upgrade-steps " + + "to clean your working branch before upgrading project."; + let diffCount = gitClient.countCommitDifference(branch, "dev"); + diffCount = diffCount.toString().replace(/\D/g, ""); + if (stringUtils.isNonBlankString(diffCount) && diffCount !== "0") { + throw new CliError(`Upgrade project failed. Your branch is ahead of ${branch} by ${diffCount} commit(s), ${upgradeInstruction}`); + } } /** @@ -56,24 +57,24 @@ function _compareCommitsWithDev(gitClient, branch) { * @param {String} profile the profile */ function createV2ProjectSkeletonAndLoadModel(rootPath, skillId, profile) { - // prepare skill package folder - const skillPackagePath = path.join(rootPath, CONSTANTS.FILE_PATH.SKILL_PACKAGE.PACKAGE); - fs.ensureDirSync(skillPackagePath); - // prepare skill code folder - const skillCodePath = path.join(rootPath, CONSTANTS.FILE_PATH.SKILL_CODE.LAMBDA); - fs.ensureDirSync(skillCodePath); - // prepare resources config - const askResourcesFilePath = path.join(rootPath, CONSTANTS.FILE_PATH.ASK_RESOURCES_JSON_CONFIG); - const askStatesFilePath = path.join(rootPath, CONSTANTS.FILE_PATH.HIDDEN_ASK_FOLDER, CONSTANTS.FILE_PATH.ASK_STATES_JSON_CONFIG); - const askResources = R.clone(AskResources.BASE); - askResources.profiles[profile] = {}; - const askStates = R.clone(AskStates.BASE); - askStates.profiles[profile] = { - skillId - }; - AskResources.withContent(askResourcesFilePath, askResources); - AskStates.withContent(askStatesFilePath, askStates); - new ResourcesConfig(askResourcesFilePath); + // prepare skill package folder + const skillPackagePath = path.join(rootPath, CONSTANTS.FILE_PATH.SKILL_PACKAGE.PACKAGE); + fs.ensureDirSync(skillPackagePath); + // prepare skill code folder + const skillCodePath = path.join(rootPath, CONSTANTS.FILE_PATH.SKILL_CODE.LAMBDA); + fs.ensureDirSync(skillCodePath); + // prepare resources config + const askResourcesFilePath = path.join(rootPath, CONSTANTS.FILE_PATH.ASK_RESOURCES_JSON_CONFIG); + const askStatesFilePath = path.join(rootPath, CONSTANTS.FILE_PATH.HIDDEN_ASK_FOLDER, CONSTANTS.FILE_PATH.ASK_STATES_JSON_CONFIG); + const askResources = R.clone(AskResources.BASE); + askResources.profiles[profile] = {}; + const askStates = R.clone(AskStates.BASE); + askStates.profiles[profile] = { + skillId, + }; + AskResources.withContent(askResourcesFilePath, askResources); + AskStates.withContent(askStatesFilePath, askStates); + new ResourcesConfig(askResourcesFilePath); } /** @@ -86,13 +87,13 @@ function createV2ProjectSkeletonAndLoadModel(rootPath, skillId, profile) { * @param {callback} callback { error } */ function downloadSkillPackage(rootPath, skillId, skillStage, profile, doDebug, callback) { - const skillMetaController = new SkillMetadataController({ profile, doDebug }); - skillMetaController.getSkillPackage(rootPath, skillId, skillStage, (packageErr) => { - if (packageErr) { - return callback(packageErr); - } - callback(); - }); + const skillMetaController = new SkillMetadataController({profile, doDebug}); + skillMetaController.getSkillPackage(rootPath, skillId, skillStage, (packageErr) => { + if (packageErr) { + return callback(packageErr); + } + callback(); + }); } /** @@ -102,56 +103,58 @@ function downloadSkillPackage(rootPath, skillId, skillStage, profile, doDebug, c * @param {String} profile the profile */ function handleExistingLambdaCode(rootPath, gitRepoUrl, profile) { - // 1.update skill infra type - ResourcesConfig.getInstance().setSkillInfraType(profile, CONSTANTS.DEPLOYER_TYPE.HOSTED.NAME); - // 2. set git repository url - const legacyFolderPath = path.join(rootPath, CONSTANTS.FILE_PATH.LEGACY_PATH); - // 3. copy code from v1 project to v2 - const v1CodePath = path.join(legacyFolderPath, CONSTANTS.FILE_PATH.SKILL_CODE.LAMBDA); - const v2CodePath = path.join(rootPath, CONSTANTS.FILE_PATH.SKILL_CODE.LAMBDA); - fs.copySync(v1CodePath, v2CodePath); - ResourcesConfig.getInstance().write(); + // 1.update skill infra type + ResourcesConfig.getInstance().setSkillInfraType(profile, CONSTANTS.DEPLOYER_TYPE.HOSTED.NAME); + // 2. set git repository url + const legacyFolderPath = path.join(rootPath, CONSTANTS.FILE_PATH.LEGACY_PATH); + // 3. copy code from v1 project to v2 + const v1CodePath = path.join(legacyFolderPath, CONSTANTS.FILE_PATH.SKILL_CODE.LAMBDA); + const v2CodePath = path.join(rootPath, CONSTANTS.FILE_PATH.SKILL_CODE.LAMBDA); + fs.copySync(v1CodePath, v2CodePath); + ResourcesConfig.getInstance().write(); } /** * To update git credential, checkout mater as default branch and set git pre-push template * @param {String} profile the profile * @param {Boolean} doDebug the debug flag - * @param {String} gitClient the git client + * @param {Object} gitClient the git client * @param {callback} callback { error } */ function postUpgradeGitSetup(profile, doDebug, gitClient, repositoryUrl, skillId, callback) { - try { - _setGitCredentialHelper(profile, gitClient, repositoryUrl, skillId); - _setMasterAsDefault(gitClient); - _updateGitIgnoreWithAskResourcesJson(gitClient); - } catch (error) { - return callback(error); - } - _setPrePushHookTemplate(profile, doDebug, (hooksErr) => callback(hooksErr || null)); + try { + _setGitCredentialHelper(profile, gitClient, repositoryUrl, skillId); + _setMasterAsDefault(gitClient); + _updateGitIgnoreWithAskResourcesJson(gitClient); + } catch (error) { + return callback(error); + } + _setPrePushHookTemplate(profile, doDebug, (hooksErr) => callback(hooksErr || null)); } function _setGitCredentialHelper(profile, gitClient, repositoryUrl, skillId) { - const credentialScriptPath = path.join(os.homedir(), - CONSTANTS.FILE_PATH.ASK.HIDDEN_FOLDER, - CONSTANTS.FILE_PATH.ASK.SCRIPTS_FOLDER.NAME, - CONSTANTS.FILE_PATH.ASK.SCRIPTS_FOLDER.GIT_CREDENTIAL_HELPER); - const credentialScriptExecution = `'${credentialScriptPath}' ${profile} ${skillId}`; - gitClient.configureCredentialHelper(credentialScriptExecution, repositoryUrl); + const credentialScriptPath = path.join( + os.homedir(), + CONSTANTS.FILE_PATH.ASK.HIDDEN_FOLDER, + CONSTANTS.FILE_PATH.ASK.SCRIPTS_FOLDER.NAME, + CONSTANTS.FILE_PATH.ASK.SCRIPTS_FOLDER.GIT_CREDENTIAL_HELPER, + ); + const credentialScriptExecution = `'${credentialScriptPath}' ${profile} ${skillId}`; + gitClient.configureCredentialHelper(credentialScriptExecution, repositoryUrl); } function _updateGitIgnoreWithAskResourcesJson(gitClient) { - const fileToAdd = ['ask-resources.json', '.ask/']; - gitClient.setupGitIgnore(fileToAdd); + const fileToAdd = ["ask-resources.json", ".ask/"]; + gitClient.setupGitIgnore(fileToAdd); } function _setMasterAsDefault(gitClient) { - gitClient.checkoutBranch('master'); - gitClient.merge('dev'); - gitClient.deleteBranch('dev'); + gitClient.checkoutBranch("master"); + gitClient.merge("dev"); + gitClient.deleteBranch("dev"); } function _setPrePushHookTemplate(profile, doDebug, callback) { - const hostedSkillController = new HostedSkillController(profile, doDebug); - hostedSkillController.downloadAskScripts('./', (hooksErr) => callback(hooksErr || null)); + const hostedSkillController = new HostedSkillController(profile, doDebug); + hostedSkillController.downloadAskScripts("./", (hooksErr) => callback(hooksErr || null)); } diff --git a/lib/commands/util/upgrade-project/index.js b/lib/commands/util/upgrade-project/index.js deleted file mode 100644 index 01074f22..00000000 --- a/lib/commands/util/upgrade-project/index.js +++ /dev/null @@ -1,145 +0,0 @@ -const GitClient = require('@src/clients/git-client'); -const { AbstractCommand } = require('@src/commands/abstract-command'); -const optionModel = require('@src/commands/option-model'); -const Messenger = require('@src/view/messenger'); -const profileHelper = require('@src/utils/profile-helper'); -const CONSTANTS = require('@src/utils/constants'); - -const helper = require('./helper'); -const hostedSkillHelper = require('./hosted-skill-helper'); - -class UpgradeProjectCommand extends AbstractCommand { - name() { - return 'upgrade-project'; - } - - description() { - return 'upgrade the v1 ask-cli skill project to v2 structure'; - } - - requiredOptions() { - return []; - } - - optionalOptions() { - return ['profile', 'debug']; - } - - handle(cmd, cb) { - let profile, upgradeInfo; - try { - profile = profileHelper.runtimeProfile(cmd.profile); - const { v1Config, isDeployed } = helper.loadV1ProjConfig(process.cwd(), profile); - // 0.upgrade if project is un-deployed v1 template - if (!isDeployed) { - helper.attemptUpgradeUndeployedProject(process.cwd(), v1Config, profile); - Messenger.getInstance().info('Template project migration finished.'); - return cb(); - } - // 1.extract upgrade-necessary information and confirm project is upgrade-able - upgradeInfo = helper.extractUpgradeInformation(v1Config, profile); - } catch (checkErr) { - Messenger.getInstance().error(checkErr); - return cb(checkErr); - } - // 2.preview new project structure - helper.previewUpgrade(upgradeInfo, (previewErr, previewConfirm) => { - if (previewErr) { - Messenger.getInstance().error(previewErr); - return cb(previewErr); - } - if (!previewConfirm) { - Messenger.getInstance().info('Command upgrade-project aborted.'); - return cb(); - } - // 3.create v2 project based on the upgrade info - if (upgradeInfo.isHosted) { - _createV2HostedSkillProject(upgradeInfo, profile, cmd.debug, (v2Err) => { - if (v2Err) { - Messenger.getInstance().error(v2Err); - return cb(v2Err); - } - Messenger.getInstance().info('Project migration finished.'); - cb(); - }); - } else { - _createV2NonHostedSkillProject(upgradeInfo, profile, cmd.debug, (v2Err) => { - if (v2Err) { - Messenger.getInstance().error(v2Err); - return cb(v2Err); - } - Messenger.getInstance().info('Project migration finished.'); - cb(); - }); - } - }); - } -} - -function _createV2HostedSkillProject(upgradeInfo, profile, doDebug, callback) { - const rootPath = process.cwd(); - const { skillId, gitRepoUrl } = upgradeInfo; - const verbosityOptions = { - showCommand: !!doDebug, - showOutput: !!doDebug - }; - const gitClient = new GitClient(rootPath, verbosityOptions); - try { - hostedSkillHelper.checkIfDevBranchClean(gitClient); - // 1.move v1 skill project content into legacy folder - helper.moveOldProjectToLegacyFolder(rootPath); - // 2.instantiate MVC and ask-resource config - hostedSkillHelper.createV2ProjectSkeletonAndLoadModel(rootPath, skillId, profile); - } catch (initProjErr) { - return callback(initProjErr); - } - // 3.import skill metadata - hostedSkillHelper.downloadSkillPackage(rootPath, skillId, CONSTANTS.SKILL.STAGE.DEVELOPMENT, profile, doDebug, (packageErr) => { - if (packageErr) { - return callback(packageErr); - } - // 4.copy Lambda code to skill code and update deploy state - try { - hostedSkillHelper.handleExistingLambdaCode(rootPath, gitRepoUrl, profile); - } catch (codeErr) { - return callback(codeErr); - } - // 5. config git setting - hostedSkillHelper.postUpgradeGitSetup(profile, doDebug, gitClient, gitRepoUrl, skillId, (gitErr) => { - if (gitErr) { - return callback(gitErr); - } - callback(); - }); - }); -} - -function _createV2NonHostedSkillProject(upgradeInfo, profile, doDebug, callback) { - const rootPath = process.cwd(); - const { skillId, lambdaResources } = upgradeInfo; - try { - // 1.move v1 skill project content into legacy folder - helper.moveOldProjectToLegacyFolder(rootPath); - // 2.instantiate MVC and ask-resource config - helper.createV2ProjectSkeletonAndLoadModel(rootPath, skillId, profile); - } catch (initProjErr) { - return callback(initProjErr); - } - - // 3.import skill metadata from skillId - helper.downloadSkillPackage(rootPath, skillId, CONSTANTS.SKILL.STAGE.DEVELOPMENT, profile, doDebug, (packageErr) => { - if (packageErr) { - return callback(packageErr); - } - // 4.copy Lambda code to skill code - try { - helper.handleExistingLambdaCode(rootPath, lambdaResources, profile); - callback(); - } catch (codeErr) { - callback(codeErr); - } - }); -} - -module.exports = UpgradeProjectCommand; -module.exports.createCommand = new UpgradeProjectCommand(optionModel).createCommand(); diff --git a/lib/commands/util/upgrade-project/index.ts b/lib/commands/util/upgrade-project/index.ts new file mode 100644 index 00000000..11e4e117 --- /dev/null +++ b/lib/commands/util/upgrade-project/index.ts @@ -0,0 +1,144 @@ +import {OptionModel} from "../../option-validator"; +import GitClient from "../../../clients/git-client"; +import {AbstractCommand} from "../../abstract-command"; +import optionModel from "../../option-model.json"; +import Messenger from "../../../view/messenger"; +import profileHelper from "../../../utils/profile-helper"; +import CONSTANTS from "../../../utils/constants"; +import helper from "./helper"; +import hostedSkillHelper from "./hosted-skill-helper"; + +export default class UpgradeProjectCommand extends AbstractCommand { + name() { + return "upgrade-project"; + } + + description() { + return "upgrade the v1 ask-cli skill project to v2 structure"; + } + + requiredOptions() { + return []; + } + + optionalOptions() { + return ["profile", "debug"]; + } + + async handle(cmd: Record): Promise { + let profile: string, upgradeInfo: any; + try { + profile = profileHelper.runtimeProfile(cmd.profile); + const {v1Config, isDeployed} = helper.loadV1ProjConfig(process.cwd(), profile); + // 0.upgrade if project is un-deployed v1 template + if (!isDeployed) { + helper.attemptUpgradeUndeployedProject(process.cwd(), v1Config, profile); + Messenger.getInstance().info("Template project migration finished."); + return; + } + // 1.extract upgrade-necessary information and confirm project is upgrade-able + upgradeInfo = helper.extractUpgradeInformation(v1Config, profile); + } catch (checkErr) { + Messenger.getInstance().error(checkErr); + throw checkErr; + } + return new Promise((resolve, reject) => { + // 2.preview new project structure + helper.previewUpgrade(upgradeInfo, (previewErr: string, previewConfirm: boolean) => { + if (previewErr) { + Messenger.getInstance().error(previewErr); + return reject(previewErr); + } + if (!previewConfirm) { + Messenger.getInstance().info("Command upgrade-project aborted."); + return resolve(); + } + // 3.create v2 project based on the upgrade info + if (upgradeInfo.isHosted) { + return _createV2HostedSkillProject(upgradeInfo, profile, cmd.debug) + .then(() => { + Messenger.getInstance().info("Project migration finished."); + return resolve(); + }) + .catch((v2Err) => { + Messenger.getInstance().error(v2Err); + return reject(v2Err); + }); + } else { + _createV2NonHostedSkillProject(upgradeInfo, profile, cmd.debug) + .then(() => { + Messenger.getInstance().info("Project migration finished."); + return resolve(); + }) + .catch((v2Err) => { + Messenger.getInstance().error(v2Err); + return reject(v2Err); + }); + } + }); + }); + } +} + +async function _createV2HostedSkillProject(upgradeInfo: any, profile: string, doDebug: boolean): Promise { + const rootPath = process.cwd(); + const {skillId, gitRepoUrl} = upgradeInfo; + const verbosityOptions = { + showCommand: !!doDebug, + showOutput: !!doDebug, + }; + const gitClient = new GitClient(rootPath, verbosityOptions); + hostedSkillHelper.checkIfDevBranchClean(gitClient); + // 1.move v1 skill project content into legacy folder + helper.moveOldProjectToLegacyFolder(rootPath); + // 2.instantiate MVC and ask-resource config + hostedSkillHelper.createV2ProjectSkeletonAndLoadModel(rootPath, skillId, profile); + // 3.import skill metadata + return new Promise((resolve, reject) => { + hostedSkillHelper.downloadSkillPackage(rootPath, skillId, CONSTANTS.SKILL.STAGE.DEVELOPMENT, profile, doDebug, (packageErr: any) => { + if (packageErr) { + return reject(packageErr); + } + // 4.copy Lambda code to skill code and update deploy state + try { + hostedSkillHelper.handleExistingLambdaCode(rootPath, gitRepoUrl, profile); + } catch (codeErr) { + return reject(codeErr); + } + // 5. config git setting + hostedSkillHelper.postUpgradeGitSetup(profile, doDebug, gitClient, gitRepoUrl, skillId, (gitErr: any) => { + if (gitErr) { + return reject(gitErr); + } + resolve(); + }); + }); + }); +} + +async function _createV2NonHostedSkillProject(upgradeInfo: any, profile: string, doDebug: boolean): Promise { + const rootPath = process.cwd(); + const {skillId, lambdaResources} = upgradeInfo; + // 1.move v1 skill project content into legacy folder + helper.moveOldProjectToLegacyFolder(rootPath); + // 2.instantiate MVC and ask-resource config + helper.createV2ProjectSkeletonAndLoadModel(rootPath, skillId, profile); + + // 3.import skill metadata from skillId + return new Promise((resolve, reject) => { + helper.downloadSkillPackage(rootPath, skillId, CONSTANTS.SKILL.STAGE.DEVELOPMENT, profile, doDebug, (packageErr: any) => { + if (packageErr) { + return reject(packageErr); + } + // 4.copy Lambda code to skill code + try { + helper.handleExistingLambdaCode(rootPath, lambdaResources, profile); + resolve(); + } catch (codeErr) { + reject(codeErr); + } + }); + }); +} + +export const createCommand = new UpgradeProjectCommand(optionModel as OptionModel).createCommand(); diff --git a/lib/commands/util/upgrade-project/ui.js b/lib/commands/util/upgrade-project/ui.js index af27cb32..066b538c 100644 --- a/lib/commands/util/upgrade-project/ui.js +++ b/lib/commands/util/upgrade-project/ui.js @@ -1,13 +1,13 @@ -const path = require('path'); -const R = require('ramda'); -const inquirer = require('inquirer'); +const path = require("path"); +const R = require("ramda"); +const inquirer = require("inquirer"); -const Messenger = require('@src/view/messenger'); -const CONSTANTS = require('@src/utils/constants'); +const Messenger = require("../../../view/messenger"); +const CONSTANTS = require("../../../utils/constants"); module.exports = { - displayPreview, - confirmPreview + displayPreview, + confirmPreview, }; /** @@ -16,10 +16,12 @@ module.exports = { * upgradeInfo.lambdaResources { $alexaRegion: { arn, codeUri, v2CodeUri, runtime, handler, revisionId } } */ function displayPreview(upgradeInfo) { - const { skillId, isHosted, lambdaResources } = upgradeInfo; - Messenger.getInstance().info(`Preview of the upgrade result from v1 to v2: + const {skillId, isHosted, lambdaResources} = upgradeInfo; + Messenger.getInstance().info(`Preview of the upgrade result from v1 to v2: - The original v1 skill project will be entirely moved to .${path.sep}${CONSTANTS.FILE_PATH.LEGACY_PATH}${path.sep} -- JSON files for Skill ID ${skillId} (such as skill.json) will be moved to .${path.sep}${CONSTANTS.FILE_PATH.SKILL_PACKAGE.PACKAGE}${path.sep} +- JSON files for Skill ID ${skillId} (such as skill.json) will be moved to .${path.sep}${CONSTANTS.FILE_PATH.SKILL_PACKAGE.PACKAGE}${ + path.sep + } ${_displayLambdaCodePreview(isHosted, lambdaResources)}`); } @@ -28,34 +30,37 @@ ${_displayLambdaCodePreview(isHosted, lambdaResources)}`); * @param {callback} callback { err, confirmPreview } */ function confirmPreview(callback) { - const question = { - type: 'confirm', - name: 'confirmPreview', - message: 'Do you want to execute the upgrade based on the preview above? ' - }; - inquirer.prompt(question).then((answer) => { - callback(null, answer.confirmPreview); - }).catch((err) => { - callback(err); + const question = { + type: "confirm", + name: "confirmPreview", + message: "Do you want to execute the upgrade based on the preview above? ", + }; + inquirer + .prompt(question) + .then((answer) => { + callback(null, answer.confirmPreview); + }) + .catch((err) => { + callback(err); }); } function _displayLambdaCodePreview(isHosted, lambdaResources) { - let lambdaPreview = `- Existing Lambda codebase will be moved into "${CONSTANTS.FILE_PATH.SKILL_CODE.LAMBDA}" folder`; - if (isHosted) { - return lambdaPreview; - } - if (R.keys(lambdaResources).length === 0) { - return '- No existing Lambda in the v1 "lambda" resource thus no action for Lambda codebase.'; - } - R.keys(lambdaResources).forEach((region) => { - const { codeUri, v2CodeUri, arn } = lambdaResources[region]; - // TODO check when codeUri is a single file - if (arn) { - lambdaPreview += `\n - Region ${region}: v1 "${codeUri}" -> v2 "${v2CodeUri}" for existing Lambda ARN ${arn}`; - } else { - lambdaPreview += `\n - Region ${region}: v1 "${codeUri}" -> v2 "${v2CodeUri}" and will create new Lambda`; - } - }); + let lambdaPreview = `- Existing Lambda codebase will be moved into "${CONSTANTS.FILE_PATH.SKILL_CODE.LAMBDA}" folder`; + if (isHosted) { return lambdaPreview; + } + if (R.keys(lambdaResources).length === 0) { + return '- No existing Lambda in the v1 "lambda" resource thus no action for Lambda codebase.'; + } + R.keys(lambdaResources).forEach((region) => { + const {codeUri, v2CodeUri, arn} = lambdaResources[region]; + // TODO check when codeUri is a single file + if (arn) { + lambdaPreview += `\n - Region ${region}: v1 "${codeUri}" -> v2 "${v2CodeUri}" for existing Lambda ARN ${arn}`; + } else { + lambdaPreview += `\n - Region ${region}: v1 "${codeUri}" -> v2 "${v2CodeUri}" and will create new Lambda`; + } + }); + return lambdaPreview; } diff --git a/lib/commands/util/util-commander.js b/lib/commands/util/util-commander.js deleted file mode 100644 index 9a2190c2..00000000 --- a/lib/commands/util/util-commander.js +++ /dev/null @@ -1,18 +0,0 @@ -const commander = require('commander'); - -const UTIL_COMMAND_MAP = { - 'upgrade-project': '@src/commands/util/upgrade-project', - 'git-credentials-helper': '@src/commands/util/git-credentials-helper', - 'generate-lwa-tokens': '@src/commands/util/generate-lwa-tokens' -}; - -Object.keys(UTIL_COMMAND_MAP).forEach((cmd) => { - // eslint-disable-next-line global-require - require(UTIL_COMMAND_MAP[cmd]).createCommand(commander); -}); - -commander._name = 'ask util'; -commander - .description('tooling functions when using ask-cli to manage Alexa Skill'); - -module.exports = { commander, UTIL_COMMAND_MAP }; diff --git a/lib/commands/util/util-commander.ts b/lib/commands/util/util-commander.ts new file mode 100644 index 00000000..3a8f5258 --- /dev/null +++ b/lib/commands/util/util-commander.ts @@ -0,0 +1,19 @@ +import {createCommand as upgradeCreateCommand} from "./upgrade-project"; +import {createCommand as gitCredsCreateCommand} from "./git-credentials-helper"; +import {createCommand as generateLwaTokenCommand} from "./generate-lwa-tokens"; +import {Command} from "commander"; + +const commander = new Command(); + +const UTIL_COMMAND_MAP: Record void> = { + "upgrade-project": upgradeCreateCommand, + "git-credentials-helper": gitCredsCreateCommand, + "generate-lwa-tokens": generateLwaTokenCommand, +}; + +Object.values(UTIL_COMMAND_MAP).forEach((createCommand) => createCommand(commander)); + +commander.name("ask util"); +commander.description("tooling functions when using ask-cli to manage Alexa Skill"); + +export {commander, UTIL_COMMAND_MAP}; diff --git a/lib/controllers/authorization-controller/index.js b/lib/controllers/authorization-controller/index.js index 7a670316..1f4aad65 100644 --- a/lib/controllers/authorization-controller/index.js +++ b/lib/controllers/authorization-controller/index.js @@ -1,173 +1,175 @@ -const open = require('open'); -const portscanner = require('portscanner'); -const url = require('url'); +const open = require("open"); +const portscanner = require("portscanner"); +const url = require("url"); -const LWAAuthCodeClient = require('@src/clients/lwa-auth-code-client'); -const AppConfig = require('@src/model/app-config'); -const CONSTANTS = require('@src/utils/constants'); -const LocalHostServer = require('@src/utils/local-host-server'); -const stringUtils = require('@src/utils/string-utils'); -const Messenger = require('@src/view/messenger'); -const SpinnerView = require('@src/view/spinner-view'); +const LWAAuthCodeClient = require("../../clients/lwa-auth-code-client"); +const AppConfig = require("../../model/app-config"); +const CONSTANTS = require("../../utils/constants"); +const LocalHostServer = require("../../utils/local-host-server"); +const stringUtils = require("../../utils/string-utils"); +const Messenger = require("../../view/messenger"); +const SpinnerView = require("../../view/spinner-view"); -const messages = require('./messages'); +const messages = require("./messages"); module.exports = class AuthorizationController { - /** - * Constructor for AuthorizationController. - * @param {Object} config | contains default scopes, default state, auth_client_type (LWA), - * redirectUri, askProfile config file path, needBrowser, debug information. For more details, - * see @src/commands/configure/helper.js - */ - constructor(config) { - this.authConfig = config; - this.oauthClient = this._getAuthClientInstance(); - } + /** + * Constructor for AuthorizationController. + * @param {Object} config | contains default scopes, default state, auth_client_type (LWA), + * redirectUri, askProfile config file path, needBrowser, debug information. For more details, + * see ../../../commands/configure/helper.js + */ + constructor(config) { + this.authConfig = config; + this.oauthClient = this._getAuthClientInstance(); + } - /** - * Generates Authorization URL. - */ - getAuthorizeUrl() { - return this.oauthClient.generateAuthorizeUrl(); - } + /** + * Generates Authorization URL. + */ + getAuthorizeUrl() { + return this.oauthClient.generateAuthorizeUrl(); + } - /** - * Retrieves access token. - * @param {String} authCode | authorization code. - * @param {Function} callback - */ - getAccessTokenUsingAuthCode(authCode, callback) { - return this.oauthClient.getAccessTokenUsingAuthCode(authCode, (err, accessToken) => callback(err, err == null ? accessToken : err)); - } + /** + * Retrieves access token. + * @param {String} authCode | authorization code. + * @param {Function} callback + */ + getAccessTokenUsingAuthCode(authCode, callback) { + return this.oauthClient.getAccessTokenUsingAuthCode(authCode, (err, accessToken) => callback(err, err == null ? accessToken : err)); + } - /** - * Refreshes token and sets up authorization param. - * @param {String} profile | current profile in use. - * @param {Function} callback - */ - tokenRefreshAndRead(profile, callback) { - if (profile === CONSTANTS.PLACEHOLDER.ENVIRONMENT_VAR.PROFILE_NAME) { - const askRefreshToken = process.env.ASK_REFRESH_TOKEN; - const askAccessToken = process.env.ASK_ACCESS_TOKEN; + /** + * Refreshes token and sets up authorization param. + * @param {String} profile | current profile in use. + * @param {Function} callback + */ + tokenRefreshAndRead(profile, callback) { + if (profile === CONSTANTS.PLACEHOLDER.ENVIRONMENT_VAR.PROFILE_NAME) { + const askRefreshToken = process.env.ASK_REFRESH_TOKEN; + const askAccessToken = process.env.ASK_ACCESS_TOKEN; - // '!== undefined' check is required because environment variables return values as strings instead of objects. - const isNonBlankRefreshToken = stringUtils.isNonBlankString(askRefreshToken) && askRefreshToken !== 'undefined'; - const isNonBlankAccessToken = stringUtils.isNonBlankString(askAccessToken) && askAccessToken !== 'undefined'; - if (!isNonBlankRefreshToken && !isNonBlankAccessToken) { - return callback(messages.ASK_ENV_VARIABLES_ERROR_MESSAGE); - } - if (isNonBlankRefreshToken) { - this.oauthClient.refreshToken({ refresh_token: askRefreshToken }, (err, token) => { - if (err) { - return callback(err); - } - callback(null, token.access_token); - }); - } else if (isNonBlankAccessToken) { - return callback(null, askAccessToken); - } - } else if (this.oauthClient.isValidToken(AppConfig.getInstance().getToken(profile))) { - callback(null, AppConfig.getInstance().getToken(profile).access_token); - } else { - this._getRefreshTokenAndUpdateConfig(profile, AppConfig.getInstance().getToken(profile), - (err, token) => callback(err, err === null ? token : err)); - } - } - - /** - * @param {String} profile | profile in use currently. - * @param {String} configFilePath | path for the config file. - * @param {Function} callback - * @private - */ - _getRefreshTokenAndUpdateConfig(profile, token, callback) { - this.oauthClient.refreshToken(token, (err, refreshedAccessToken) => { - if (err) { - return callback(err); - } - AppConfig.getInstance().setToken(profile, refreshedAccessToken); - AppConfig.getInstance().write(); - callback(null, refreshedAccessToken.access_token); + // '!== undefined' check is required because environment variables return values as strings instead of objects. + const isNonBlankRefreshToken = stringUtils.isNonBlankString(askRefreshToken) && askRefreshToken !== "undefined"; + const isNonBlankAccessToken = stringUtils.isNonBlankString(askAccessToken) && askAccessToken !== "undefined"; + if (!isNonBlankRefreshToken && !isNonBlankAccessToken) { + return callback(messages.ASK_ENV_VARIABLES_ERROR_MESSAGE); + } + if (isNonBlankRefreshToken) { + this.oauthClient.refreshToken({refresh_token: askRefreshToken}, (err, token) => { + if (err) { + return callback(err); + } + callback(null, token.access_token); }); + } else if (isNonBlankAccessToken) { + return callback(null, askAccessToken); + } + } else if (this.oauthClient.isValidToken(AppConfig.getInstance().getToken(profile))) { + callback(null, AppConfig.getInstance().getToken(profile).access_token); + } else { + this._getRefreshTokenAndUpdateConfig(profile, AppConfig.getInstance().getToken(profile), (err, token) => + callback(err, err === null ? token : err), + ); } + } - /** - * Helper method to keep listening to LWA response. - * @param {Function} callback - */ - getTokensByListeningOnPort(callback) { - const PORT = CONSTANTS.LWA.LOCAL_PORT; - this.oauthClient.config.redirectUri = `http://127.0.0.1:${PORT}/cb`; - portscanner.checkPortStatus(PORT, (err, currentStatus) => { - if (err) { - return callback(err); - } - if (currentStatus !== 'closed') { - return callback(messages.PORT_OCCUPIED_WARN_MESSAGE); - } - Messenger.getInstance().info(messages.AUTH_MESSAGE); - - setTimeout(() => { - open(this.oauthClient.generateAuthorizeUrl()); - }, CONSTANTS.CONFIGURATION.OPEN_BROWSER_DELAY); + /** + * @param {String} profile | profile in use currently. + * @param {String} configFilePath | path for the config file. + * @param {Function} callback + * @private + */ + _getRefreshTokenAndUpdateConfig(profile, token, callback) { + this.oauthClient.refreshToken(token, (err, refreshedAccessToken) => { + if (err) { + return callback(err); + } + AppConfig.getInstance().setToken(profile, refreshedAccessToken); + AppConfig.getInstance().write(); + callback(null, refreshedAccessToken.access_token); + }); + } - this._listenResponseFromLWA(PORT, (error, authCode) => { - if (error) { - return callback(error); - } - this.oauthClient.getAccessTokenUsingAuthCode(authCode, - (accessTokenError, accessToken) => callback(accessTokenError, accessTokenError == null ? accessToken : accessTokenError)); - }); - }); - } + /** + * Helper method to keep listening to LWA response. + * @param {Function} callback + */ + getTokensByListeningOnPort(callback) { + const PORT = CONSTANTS.LWA.LOCAL_PORT; + this.oauthClient.config.redirectUri = `http://127.0.0.1:${PORT}/cb`; + portscanner.checkPortStatus(PORT, (err, currentStatus) => { + if (err) { + return callback(err); + } + if (currentStatus !== "closed") { + return callback(messages.PORT_OCCUPIED_WARN_MESSAGE); + } + Messenger.getInstance().info(messages.AUTH_MESSAGE); - /** - * Helper method to facilitate spinner view and handle clean up process. - * @param {String} PORT | port to be listened on. - * @param {Function} callback - * @private - */ - _listenResponseFromLWA(PORT, callback) { - const listenSpinner = new SpinnerView(); - const server = new LocalHostServer(PORT); - server.create(serverCallback); - server.listen(() => { - listenSpinner.start(` Listening on http://localhost:${PORT}...`); - }); - server.registerEvent('connection', (socket) => { - socket.unref(); - }); + setTimeout(() => { + open(this.oauthClient.generateAuthorizeUrl()); + }, CONSTANTS.CONFIGURATION.OPEN_BROWSER_DELAY); - function serverCallback(request, response) { - response.on('close', () => { - request.socket.destroy(); - }); - listenSpinner.terminate(); - const requestUrl = request.url; - const requestQuery = url.parse(requestUrl, true).query; - server.destroy(); - if (requestUrl.startsWith('/cb?code')) { - response.end(messages.ASK_SIGN_IN_SUCCESS_MESSAGE); - callback(null, requestQuery.code); - } - if (requestUrl.startsWith('/cb?error')) { - response.statusCode = 403; - const errorMessage = `Error: ${requestQuery.error}\nReason: ${requestQuery.error_description}`; - response.end(messages.ASK_SIGN_IN_FAILURE_MESSAGE(errorMessage)); - callback(errorMessage); - } + this._listenResponseFromLWA(PORT, (error, authCode) => { + if (error) { + return callback(error); } + this.oauthClient.getAccessTokenUsingAuthCode(authCode, (accessTokenError, accessToken) => + callback(accessTokenError, accessTokenError == null ? accessToken : accessTokenError), + ); + }); + }); + } + + /** + * Helper method to facilitate spinner view and handle clean up process. + * @param {String} PORT | port to be listened on. + * @param {Function} callback + * @private + */ + _listenResponseFromLWA(PORT, callback) { + const listenSpinner = new SpinnerView(); + const server = new LocalHostServer(PORT); + server.create(serverCallback); + server.listen(() => { + listenSpinner.start(` Listening on http://localhost:${PORT}...`); + }); + server.registerEvent("connection", (socket) => { + socket.unref(); + }); + + function serverCallback(request, response) { + response.on("close", () => { + request.socket.destroy(); + }); + listenSpinner.terminate(); + const requestUrl = request.url; + const requestQuery = url.parse(requestUrl, true).query; + server.destroy(); + if (requestUrl.startsWith("/cb?code")) { + response.end(messages.ASK_SIGN_IN_SUCCESS_MESSAGE); + callback(null, requestQuery.code); + } + if (requestUrl.startsWith("/cb?error")) { + response.statusCode = 403; + const errorMessage = `Error: ${requestQuery.error}\nReason: ${requestQuery.error_description}`; + response.end(messages.ASK_SIGN_IN_FAILURE_MESSAGE(errorMessage)); + callback(errorMessage); + } } + } - /** - * Factory method to facilitate substitution of other OAuth2 clients. - * @returns LWA client object. - * @private - */ - _getAuthClientInstance() { - if (this.authConfig.auth_client_type === 'LWA') { - const { clientId, clientConfirmation, authorizeHost, tokenHost, scope, state, doDebug, redirectUri } = this.authConfig; - return new LWAAuthCodeClient({ clientId, clientConfirmation, authorizeHost, tokenHost, scope, state, doDebug, redirectUri }); - } + /** + * Factory method to facilitate substitution of other OAuth2 clients. + * @returns LWA client object. + * @private + */ + _getAuthClientInstance() { + if (this.authConfig.auth_client_type === "LWA") { + const {clientId, clientConfirmation, authorizeHost, tokenHost, scope, state, doDebug, redirectUri} = this.authConfig; + return new LWAAuthCodeClient({clientId, clientConfirmation, authorizeHost, tokenHost, scope, state, doDebug, redirectUri}); } + } }; diff --git a/lib/controllers/authorization-controller/messages.js b/lib/controllers/authorization-controller/messages.js index e43b4b88..a9ce9185 100644 --- a/lib/controllers/authorization-controller/messages.js +++ b/lib/controllers/authorization-controller/messages.js @@ -1,9 +1,11 @@ -module.exports.AUTH_MESSAGE = 'Switch to "Login with Amazon" page and sign-in with your Amazon developer credentials.\n' -+ 'If your browser did not open the page, try to run the command again with "--no-browser" option.\n'; +module.exports.AUTH_MESSAGE = + 'Switch to "Login with Amazon" page and sign-in with your Amazon developer credentials.\n' + + 'If your browser did not open the page, try to run the command again with "--no-browser" option.\n'; -module.exports.PORT_OCCUPIED_WARN_MESSAGE = '[Warn]: 9090 port on localhost has been occupied, ' -+ 'ask-cli cannot start a local server for receiving authorization code.\nPlease either abort any processes running on port 9090\n' -+ 'or add `--no-browser` flag to the command as an alternative approach.'; +module.exports.PORT_OCCUPIED_WARN_MESSAGE = + "[Warn]: 9090 port on localhost has been occupied, " + + "ask-cli cannot start a local server for receiving authorization code.\nPlease either abort any processes running on port 9090\n" + + "or add `--no-browser` flag to the command as an alternative approach."; module.exports.ASK_SIGN_IN_SUCCESS_MESSAGE = ` @@ -53,4 +55,4 @@ module.exports.ASK_SIGN_IN_FAILURE_MESSAGE = (error) => ` `; -module.exports.ASK_ENV_VARIABLES_ERROR_MESSAGE = 'Could not find either of the environment variables: ASK_ACCESS_TOKEN, ASK_REFRESH_TOKEN'; +module.exports.ASK_ENV_VARIABLES_ERROR_MESSAGE = "Could not find either of the environment variables: ASK_ACCESS_TOKEN, ASK_REFRESH_TOKEN"; diff --git a/lib/controllers/dialog-controller/index.js b/lib/controllers/dialog-controller/index.js deleted file mode 100644 index 5ef11cfc..00000000 --- a/lib/controllers/dialog-controller/index.js +++ /dev/null @@ -1,177 +0,0 @@ -const chalk = require('chalk'); -const fs = require('fs-extra'); -const R = require('ramda'); - -const stringUtils = require('@src/utils/string-utils'); -const Messenger = require('@src/view/messenger'); -const responseParser = require('@src/controllers/dialog-controller/simulation-response-parser'); -const SkillSimulationController = require('@src/controllers/skill-simulation-controller'); - -const RECORD_FORMAT = 'Please use the format: ".record " or ".record --append-quit"'; -module.exports = class DialogController extends SkillSimulationController { - /** - * Constructor for DialogModeController. - * @param {Object} configuration | config object includes information such as skillId, locale, profile, stage. - */ - constructor(configuration) { - super(configuration); - this.newSession = configuration.newSession === false ? configuration.newSession : true; - this.utteranceCache = []; - } - - /** - * Evaluate individual utterance input by the User/replay_file. - * @param {String} input Utterance by the user sent to Alexa. - * @param {Object} replView Dialog command's repl view. - * @param {Function} replCallback - */ - evaluateUtterance(input, replView, replCallback) { - replView.startProgressSpinner('Sending simulation request to Alexa...'); - this.startSkillSimulation(input.trim(), (startErr, startResponse) => { - if (startErr) { - replView.terminateProgressSpinner(); - Messenger.getInstance().error(startErr); - replCallback(); - } else if (startResponse.statusCode >= 300) { - replView.terminateProgressSpinner(); - Messenger.getInstance().error(R.view(R.lensPath(['body', 'error', 'message']), startResponse)); - replCallback(); - } else { - replView.updateProgressSpinner('Waiting for the simulation response...'); - const simulationId = R.view(R.lensPath(['body', 'id']), startResponse); - - this.getSkillSimulationResult(simulationId, (getErr, getResponse) => { - replView.terminateProgressSpinner(); - if (getErr) { - Messenger.getInstance().error(getErr); - } else { - if (responseParser.shouldEndSession(getResponse.body)) { - Messenger.getInstance().info('Session ended'); - this.clearSession(); - } - const captions = responseParser.getCaption(getResponse.body); - captions.forEach((caption) => { - Messenger.getInstance().info(chalk.yellow.bold('Alexa > ') + caption); - }); - } - replCallback(); - }); - } - }); - } - - /** - * Registers special commands with the REPL server. - * @param {Object} dialogReplView dialog command's repl view. - * @param {Function} callback - */ - setupSpecialCommands(dialogReplView, callback) { - dialogReplView.registerRecordCommand((recordArgs) => { - const recordArgsList = recordArgs.trim().split(' '); - if (!stringUtils.isNonBlankString(recordArgs) || recordArgsList.length > 2) { - return Messenger.getInstance().warn(`Incorrect format. ${RECORD_FORMAT}`); - } - const { filePath, shouldAppendQuit } = this._validateRecordCommandInput(recordArgsList, RECORD_FORMAT); - const utteranceCacheCopy = [...this.utteranceCache]; - if (shouldAppendQuit) { - utteranceCacheCopy.push('.quit'); - } - if (filePath) { - try { - this.createReplayFile(filePath, utteranceCacheCopy); - Messenger.getInstance().info(`Created replay file at ${filePath}` - + `${shouldAppendQuit ? ' (appended ".quit" to list of utterances).' : ''}`); - } catch (replayFileCreationError) { - return callback(replayFileCreationError); - } - } - }); - const self = this; - dialogReplView.registerQuitCommand(() => { - self.skillIOInstance.save(); - }); - } - - /** - * Validate record command arguments. - * @param {Array} recordArgsList - * @param {String} recordCommandFormat - */ - _validateRecordCommandInput(recordArgsList) { - const filePath = recordArgsList[0]; - const appendQuitArgument = recordArgsList[1]; - let shouldAppendQuit = false; - - if (stringUtils.isNonBlankString(appendQuitArgument)) { - if (appendQuitArgument !== '--append-quit') { - Messenger.getInstance().warn(`Unable to validate arguments: "${appendQuitArgument}". ${RECORD_FORMAT}`); - return {}; - } - shouldAppendQuit = true; - } - return { filePath, shouldAppendQuit }; - } - - /** - * Start skill simulation by calling SMAPI POST skill simulation endpoint. - * @param {String} utterance text utterance to simulate against. - * @param {Function} onSuccess callback to execute upon a successful request. - * @param {Function} onError callback to execute upon a failed request. - */ - startSkillSimulation(utterance, callback) { - super.startSkillSimulation( - utterance, - this.newSession, - (err, response) => { - if (response) { - this.utteranceCache.push(utterance); - } - return callback(err, response); - } - ); - } - - /** - * Poll for skill simulation results. - * @param {String} simulationId simulation ID associated to the current simulation. - * @param {Function} onSuccess callback to execute upon a successful request. - * @param {Function} onError callback to execute upon a failed request. - */ - getSkillSimulationResult(simulationId, callback) { - super.getSkillSimulationResult(simulationId, (err, response) => { - if (err) { - return callback(err); - } - const errorMsg = responseParser.getErrorMessage(response.body); - if (errorMsg) { - return callback(errorMsg); - } - this.newSession = false; - return callback(null, response); - }); - } - - /** - * Clears dialog session by resetting to a new session and clearing caches. - */ - clearSession() { - this.newSession = true; - this.utteranceCache = []; - } - - /** - * Function to create replay file. - * @param {String} filename name of file to save replay JSON. - */ - createReplayFile(filename, utterances) { - if (stringUtils.isNonBlankString(filename)) { - const content = { - skillId: this.skillId, - locale: this.locale, - type: 'text', - userInput: utterances - }; - fs.outputJSONSync(filename, content); - } - } -}; diff --git a/lib/controllers/dialog-controller/index.ts b/lib/controllers/dialog-controller/index.ts new file mode 100644 index 00000000..cbefe190 --- /dev/null +++ b/lib/controllers/dialog-controller/index.ts @@ -0,0 +1,176 @@ +import chalk from "chalk"; +import * as fs from "fs-extra"; + +import * as stringUtils from "../../utils/string-utils"; +import Messenger from "../../view/messenger"; +import {SkillSimulationController, SkillSimulationControllerProps} from "../skill-simulation-controller"; +import {DialogReplView} from "../../view/dialog-repl-view"; + +const RECORD_FORMAT = 'Please use the format: ".record " or ".record --append-quit"'; + +export interface DialogControllerProps extends SkillSimulationControllerProps { + newSession?: boolean; +} + +export class DialogController extends SkillSimulationController { + newSession: boolean; + utteranceCache: string[] = []; + + /** + * Constructor for DialogModeController. + * @param {Object} configuration | config object includes information such as skillId, locale, profile, stage. + */ + constructor(configuration: DialogControllerProps) { + super(configuration); + this.newSession = configuration.newSession === false ? configuration.newSession : true; + } + + /** + * Evaluate individual utterance input by the User/replay_file. + * @param {String} input Utterance by the user sent to Alexa. + * @param {Object} replView Dialog command's repl view. + * @param {Function} replCallback + */ + async evaluateUtterance(input: any, replView: DialogReplView): Promise { + replView.startProgressSpinner("Sending simulation request to Alexa..."); + try { + const startResponse = await this.startSkillSimulation(input.trim()); + + replView.updateProgressSpinner("Waiting for the simulation response..."); + const simulationId = startResponse?.body?.id; + + const response = await this.getSkillSimulationResult(simulationId); + this.newSession = false; + replView.terminateProgressSpinner(); + if (this.shouldEndSession(response.body)) { + Messenger.getInstance().info("Session ended"); + this.clearSession(); + } + const captions = this.getCaption(response.body); + captions.forEach((caption: string) => { + Messenger.getInstance().info(chalk.yellow.bold("Alexa > ") + caption); + }); + } catch (startErr) { + replView.terminateProgressSpinner(); + Messenger.getInstance().error((startErr).message ? (startErr).message : startErr); + throw startErr; + } + } + + shouldEndSession(response: any): boolean { + const invocations = response?.result?.skillExecutionInfo?.invocations; + + if (!invocations) { + return false; + } + + for (const invocation of invocations) { + if (invocation?.invocationResponse?.body?.response?.shouldEndSession) { + return true; + } + } + return false; + } + + getCaption(response: any): string[] { + const alexaResponses = response?.result?.alexaExecutionInfo?.alexaResponses as any[]; + if (!alexaResponses) { + return []; + } + return alexaResponses.map((element) => element?.content?.caption); + } + + /** + * Registers special commands with the REPL server. + * @param {Object} dialogReplView dialog command's repl view. + * @param {Function} callback + */ + async setupSpecialCommands(dialogReplView: DialogReplView): Promise { + return new Promise((resolve, reject) => { + dialogReplView.registerRecordCommand((recordArgs) => { + const recordArgsList = recordArgs.trim().split(" "); + if (!stringUtils.isNonBlankString(recordArgs) || recordArgsList.length > 2) { + Messenger.getInstance().warn(`Incorrect format. ${RECORD_FORMAT}`); + return reject(); + } + const {filePath, shouldAppendQuit} = this._validateRecordCommandInput(recordArgsList); + const utteranceCacheCopy = [...this.utteranceCache]; + if (shouldAppendQuit) { + utteranceCacheCopy.push(".quit"); + } + if (filePath) { + try { + this.createReplayFile(filePath, utteranceCacheCopy); + Messenger.getInstance().info( + `Created replay file at ${filePath}` + `${shouldAppendQuit ? ' (appended ".quit" to list of utterances).' : ""}`, + ); + } catch (replayFileCreationError) { + return reject(replayFileCreationError); + } + } + resolve(); + }); + const self = this; + dialogReplView.registerQuitCommand(() => { + self.skillIOInstance.save(); + }); + }); + } + + /** + * Validate record command arguments. + * @param {Array} recordArgsList + * @param {String} recordCommandFormat + */ + _validateRecordCommandInput(recordArgsList: string[]) { + const filePath = recordArgsList[0]; + const appendQuitArgument = recordArgsList[1]; + let shouldAppendQuit = false; + + if (stringUtils.isNonBlankString(appendQuitArgument)) { + if (appendQuitArgument !== "--append-quit") { + Messenger.getInstance().warn(`Unable to validate arguments: "${appendQuitArgument}". ${RECORD_FORMAT}`); + return {}; + } + shouldAppendQuit = true; + } + return { + filePath, + shouldAppendQuit, + }; + } + + /** + * Start skill simulation by calling SMAPI POST skill simulation endpoint. + * @param {String} utterance text utterance to simulate against. + */ + override async startSkillSimulation(utterance: string) { + const response = await super.startSkillSimulation(utterance, this.newSession); + this.utteranceCache.push(utterance); + return response; + } + + /** + * Clears dialog session by resetting to a new session and clearing caches. + */ + clearSession() { + this.newSession = true; + this.utteranceCache = []; + } + + /** + * Function to create replay file. + * @param {String} filename name of file to save replay JSON. + */ + createReplayFile(filename: string, utterances: any) { + if (stringUtils.isNonBlankString(filename)) { + const content = { + skillId: this.skillId, + locale: this.locale, + type: "text", + userInput: utterances, + }; + fs.outputJSONSync(filename, content); + } + } +} diff --git a/lib/controllers/dialog-controller/simulation-response-parser.js b/lib/controllers/dialog-controller/simulation-response-parser.js deleted file mode 100644 index 763ae705..00000000 --- a/lib/controllers/dialog-controller/simulation-response-parser.js +++ /dev/null @@ -1,84 +0,0 @@ -const R = require('ramda'); - -module.exports = { - getJsonInputAndOutputs, - shouldEndSession, - getConsideredIntents, - getErrorMessage, - getCaption, - getStatus, - getSimulationId -}; - -function getConsideredIntents(response) { - const consideredIntents = R.view(R.lensPath(['result', 'alexaExecutionInfo', 'consideredIntents']), response); - - if (!consideredIntents) { - return []; - } - return consideredIntents; -} - -function getJsonInputAndOutputs(response) { - const invocations = R.view(R.lensPath(['result', 'skillExecutionInfo', 'invocations']), response); - - if (!invocations) { - return []; - } - - const jsonInputs = invocations.map((invocation) => { - const invocationRequest = R.view(R.lensPath(['invocationRequest', 'body']), invocation); - return invocationRequest || { }; - }); - - const jsonOutputs = invocations.map((invocation) => { - const invocationResponse = R.view(R.lensPath(['invocationResponse']), invocation); - return invocationResponse || { }; - }); - - const result = []; - for (let i = 0; i < jsonInputs.length; i++) { - const io = { - jsonInput: jsonInputs[i], - jsonOutput: i < jsonOutputs.length ? jsonOutputs[i] : { } - }; - result.push(io); - } - - return result; -} - -function shouldEndSession(response) { - const invocations = R.view(R.lensPath(['result', 'skillExecutionInfo', 'invocations']), response); - - if (!invocations) { - return false; - } - - for (const invocation of invocations) { - if (R.view(R.lensPath(['invocationResponse', 'body', 'response', 'shouldEndSession']), invocation)) { - return true; - } - } - return false; -} - -function getErrorMessage(response) { - return R.view(R.lensPath(['result', 'error', 'message']), response); -} - -function getCaption(response) { - const alexaResponses = R.view(R.lensPath(['result', 'alexaExecutionInfo', 'alexaResponses']), response); - if (!alexaResponses) { - return []; - } - return alexaResponses.map(element => R.view(R.lensPath(['content', 'caption']), element)); -} - -function getStatus(response) { - return R.view(R.lensPath(['status']), response); -} - -function getSimulationId(response) { - return R.view(R.lensPath(['id']), response); -} diff --git a/lib/controllers/hosted-skill-controller/clone-flow.js b/lib/controllers/hosted-skill-controller/clone-flow.js index 24483f34..3ee5238a 100644 --- a/lib/controllers/hosted-skill-controller/clone-flow.js +++ b/lib/controllers/hosted-skill-controller/clone-flow.js @@ -1,20 +1,20 @@ -const fs = require('fs-extra'); -const os = require('os'); -const path = require('path'); -const R = require('ramda'); +const fs = require("fs-extra"); +const os = require("os"); +const path = require("path"); +const R = require("ramda"); -const GitClient = require('@src/clients/git-client'); -const ResourcesConfig = require('@src/model/resources-config'); -const CONSTANTS = require('@src/utils/constants'); -const Messenger = require('@src/view/messenger'); -const SpinnerView = require('@src/view/spinner-view'); +const GitClient = require("../../clients/git-client"); +const ResourcesConfig = require("../../model/resources-config"); +const CONSTANTS = require("../../utils/constants"); +const Messenger = require("../../view/messenger"); +const SpinnerView = require("../../view/spinner-view"); -const filesToIgnore = ['lambda/node_modules', '.ask/', 'ask-resources.json']; +const filesToIgnore = ["lambda/node_modules", ".ask/", "ask-resources.json"]; module.exports = { - generateProject, - cloneProjectFromGit, - doSkillPackageExist + generateProject, + cloneProjectFromGit, + doSkillPackageExist, }; /** @@ -26,23 +26,23 @@ module.exports = { * @param {string} profile The current profile */ function generateProject(projectPath, skillId, skillName, metadata, profile) { - _generateProjectDirectory(projectPath); - _updateAskResources(projectPath, skillId, metadata, profile); - Messenger.getInstance().info(`\nProject directory for ${skillName} created at\n\t${projectPath}`); + _generateProjectDirectory(projectPath); + _updateAskResources(projectPath, skillId, metadata, profile); + Messenger.getInstance().info(`\nProject directory for ${skillName} created at\n\t${projectPath}`); } function _generateProjectDirectory(projectPath) { - const askResourcesPath = path.join(projectPath, CONSTANTS.FILE_PATH.ASK_RESOURCES_JSON_CONFIG); - const askResourcesJson = R.clone(ResourcesConfig.BASE); - fs.mkdirSync(projectPath); - fs.writeJSONSync(askResourcesPath, askResourcesJson, { spaces: CONSTANTS.CONFIGURATION.JSON_DISPLAY_INDENT }); + const askResourcesPath = path.join(projectPath, CONSTANTS.FILE_PATH.ASK_RESOURCES_JSON_CONFIG); + const askResourcesJson = R.clone(ResourcesConfig.BASE); + fs.mkdirSync(projectPath); + fs.writeJSONSync(askResourcesPath, askResourcesJson, {spaces: CONSTANTS.CONFIGURATION.JSON_DISPLAY_INDENT}); } function _updateAskResources(projectPath, skillId, metadata, profile) { - new ResourcesConfig(path.join(projectPath, CONSTANTS.FILE_PATH.ASK_RESOURCES_JSON_CONFIG)); - ResourcesConfig.getInstance().setSkillId(profile, skillId); - ResourcesConfig.getInstance().setSkillInfraType(profile, '@ask-cli/hosted-skill-deployer'); - ResourcesConfig.getInstance().write(); + new ResourcesConfig(path.join(projectPath, CONSTANTS.FILE_PATH.ASK_RESOURCES_JSON_CONFIG)); + ResourcesConfig.getInstance().setSkillId(profile, skillId); + ResourcesConfig.getInstance().setSkillInfraType(profile, "@ask-cli/hosted-skill-deployer"); + ResourcesConfig.getInstance().write(); } /** @@ -55,65 +55,67 @@ function _updateAskResources(projectPath, skillId, metadata, profile) { * @param {boolean} doDebug is debug mode or not */ function cloneProjectFromGit(projectPath, skillId, skillName, profile, repositoryUrl, doDebug) { - const verbosityOptions = { - showCommand: !!doDebug, - showOutput: !!doDebug - }; - _gitCloneWorkflow(projectPath, repositoryUrl, verbosityOptions, skillId, profile); - Messenger.getInstance().info(`\nLambda code for ${skillName} created at\n\t./lambda`); + const verbosityOptions = { + showCommand: !!doDebug, + showOutput: !!doDebug, + }; + _gitCloneWorkflow(projectPath, repositoryUrl, verbosityOptions, skillId, profile); + Messenger.getInstance().info(`\nLambda code for ${skillName} created at\n\t./lambda`); } function _gitCloneWorkflow(projectPath, repositoryUrl, verbosityOptions, skillId, profile) { - const verbose = verbosityOptions.showCommand; - const progressSpinner = new SpinnerView(); - if (!verbose) { - progressSpinner.start('Cloning Alexa Hosted Skill...'); - } - - if (verbose) { - Messenger.getInstance().info('- Setting up git repo...'); - } - const gitClient = new GitClient(projectPath, verbosityOptions); - gitClient.init(); - const credentialScriptPath = path.join(os.homedir(), - CONSTANTS.FILE_PATH.ASK.HIDDEN_FOLDER, - CONSTANTS.FILE_PATH.ASK.SCRIPTS_FOLDER.NAME, - CONSTANTS.FILE_PATH.ASK.SCRIPTS_FOLDER.GIT_CREDENTIAL_HELPER); - const credentialScriptExecution = `'${credentialScriptPath}' ${profile} ${skillId}`; - gitClient.configureCredentialHelper(credentialScriptExecution, repositoryUrl); - gitClient.addOrigin(repositoryUrl); - - if (verbose) { - Messenger.getInstance().info('- Fetching git repo...'); - } - gitClient.fetchAll(projectPath, verbosityOptions); - - if (verbose) { - Messenger.getInstance().info('- Checking out master branch...'); - } - gitClient.checkoutBranch('master'); - - if (verbose) { - Messenger.getInstance().info('- Setting up .gitignore...'); - } - - gitClient.setupGitIgnore(filesToIgnore); - - if (verbose) { - Messenger.getInstance().info('- Git repo successfully setup'); - } - _makeBranchesVisible(gitClient); - - if (!verbose) { - progressSpinner.terminate(); - } + const verbose = verbosityOptions.showCommand; + const progressSpinner = new SpinnerView(); + if (!verbose) { + progressSpinner.start("Cloning Alexa Hosted Skill..."); + } + + if (verbose) { + Messenger.getInstance().info("- Setting up git repo..."); + } + const gitClient = new GitClient(projectPath, verbosityOptions); + gitClient.init(); + const credentialScriptPath = path.join( + os.homedir(), + CONSTANTS.FILE_PATH.ASK.HIDDEN_FOLDER, + CONSTANTS.FILE_PATH.ASK.SCRIPTS_FOLDER.NAME, + CONSTANTS.FILE_PATH.ASK.SCRIPTS_FOLDER.GIT_CREDENTIAL_HELPER, + ); + const credentialScriptExecution = `'${credentialScriptPath}' ${profile} ${skillId}`; + gitClient.configureCredentialHelper(credentialScriptExecution, repositoryUrl); + gitClient.addOrigin(repositoryUrl); + + if (verbose) { + Messenger.getInstance().info("- Fetching git repo..."); + } + gitClient.fetchAll(projectPath, verbosityOptions); + + if (verbose) { + Messenger.getInstance().info("- Checking out master branch..."); + } + gitClient.checkoutBranch("master"); + + if (verbose) { + Messenger.getInstance().info("- Setting up .gitignore..."); + } + + gitClient.setupGitIgnore(filesToIgnore); + + if (verbose) { + Messenger.getInstance().info("- Git repo successfully setup"); + } + _makeBranchesVisible(gitClient); + + if (!verbose) { + progressSpinner.terminate(); + } } function _makeBranchesVisible(gitClient) { - const branchesToCheckout = ['prod', 'master']; - branchesToCheckout.forEach((branch) => { - gitClient.checkoutBranch(branch); - }); + const branchesToCheckout = ["prod", "master"]; + branchesToCheckout.forEach((branch) => { + gitClient.checkoutBranch(branch); + }); } /** @@ -126,28 +128,28 @@ function _makeBranchesVisible(gitClient) { * @param {callback} callback { error, response } */ function doSkillPackageExist(skillName, projectPath, skillId, callback) { - const skillPackagePath = path.join(projectPath, 'skill-package'); - if (fs.existsSync(skillPackagePath)) { - return callback(null, true); - } - fs.mkdirSync(skillPackagePath); - const modelsPath = path.join(projectPath, 'models'); - const skillJsonPath = path.join(projectPath, 'skill.json'); - const ispsPath = path.join(projectPath, 'isps'); - const doModelsExist = fs.existsSync(modelsPath); - const doSkillJsonExist = fs.existsSync(skillJsonPath); - const doIspsExist = fs.existsSync(ispsPath); - if (!(doModelsExist || doSkillJsonExist)) { - return callback(null, false); - } - if (doModelsExist) { - fs.moveSync(modelsPath, path.join(skillPackagePath, 'interactionModels/custom')); - } - if (doSkillJsonExist) { - fs.moveSync(skillJsonPath, path.join(skillPackagePath, 'skill.json')); - } - if (doIspsExist) { - fs.moveSync(skillJsonPath, path.join(skillPackagePath, 'isps')); - } - callback(null, true); + const skillPackagePath = path.join(projectPath, "skill-package"); + if (fs.existsSync(skillPackagePath)) { + return callback(null, true); + } + fs.mkdirSync(skillPackagePath); + const modelsPath = path.join(projectPath, "models"); + const skillJsonPath = path.join(projectPath, "skill.json"); + const ispsPath = path.join(projectPath, "isps"); + const doModelsExist = fs.existsSync(modelsPath); + const doSkillJsonExist = fs.existsSync(skillJsonPath); + const doIspsExist = fs.existsSync(ispsPath); + if (!(doModelsExist || doSkillJsonExist)) { + return callback(null, false); + } + if (doModelsExist) { + fs.moveSync(modelsPath, path.join(skillPackagePath, "interactionModels/custom")); + } + if (doSkillJsonExist) { + fs.moveSync(skillJsonPath, path.join(skillPackagePath, "skill.json")); + } + if (doIspsExist) { + fs.moveSync(skillJsonPath, path.join(skillPackagePath, "isps")); + } + callback(null, true); } diff --git a/lib/controllers/hosted-skill-controller/helper.js b/lib/controllers/hosted-skill-controller/helper.js index 5c1141dd..49d0c747 100644 --- a/lib/controllers/hosted-skill-controller/helper.js +++ b/lib/controllers/hosted-skill-controller/helper.js @@ -1,150 +1,166 @@ -const fs = require('fs-extra'); -const https = require('https'); -const os = require('os'); -const path = require('path'); -const R = require('ramda'); +const fs = require("fs-extra"); +const https = require("https"); +const os = require("os"); +const path = require("path"); +const R = require("ramda"); -const CONSTANTS = require('@src/utils/constants'); -const DynamicConfig = require('@src/utils/dynamic-config'); -const retryUtils = require('@src/utils/retry-utility'); -const jsonView = require('@src/view/json-view'); +const CONSTANTS = require("../../utils/constants"); +const DynamicConfig = require("../../utils/dynamic-config"); +const retryUtils = require("../../utils/retry-utility"); +const jsonView = require("../../view/json-view"); module.exports = { - pollingSkillStatus, - handleSkillStatus, - downloadAuthInfoScript, - downloadAskPrePushScript, - downloadGitCredentialHelperScript, - downloadScriptFromS3 + pollingSkillStatus, + handleSkillStatus, + downloadAuthInfoScript, + downloadAskPrePushScript, + downloadGitCredentialHelperScript, + downloadScriptFromS3, }; const RETRY_OPTION = { - base: 500, - factor: 1.1, - maxRetry: 5 + base: 500, + factor: 1.1, + maxRetry: 5, }; function pollingSkillStatus(smapiClient, skillId, callback) { - const retryConfig = { - base: 1000, - factor: 1.2, - maxRetry: 30 - }; - const RESOURCE_LIST = [CONSTANTS.SKILL.RESOURCES.MANIFEST, - CONSTANTS.HOSTED_SKILL.RESOURCES.PROVISIONING, - CONSTANTS.SKILL.RESOURCES.INTERACTION_MODEL]; - const retryCall = (loopCallback) => { - smapiClient.skill.getSkillStatus(skillId, RESOURCE_LIST, (statusErr, statusResponse) => { - if (statusErr) { - return loopCallback(statusErr); - } - if (statusResponse.statusCode >= 300) { - return loopCallback(jsonView.toString(statusResponse.body)); - } - loopCallback(null, statusResponse); - }); - }; - const statusTracker = { - manifest: {}, - interactionModel: {}, - hostedSkillProvisioning: {} - }; - const shouldRetryCondition = (retryResponse) => { - const response = retryResponse.body; - statusTracker.manifest = R.view(R.lensPath([CONSTANTS.HOSTED_SKILL.RESOURCES.MANIFEST, 'lastUpdateRequest', 'status']), response); - if (response[CONSTANTS.HOSTED_SKILL.RESOURCES.INTERACTION_MODEL]) { - const locale = Object.keys(response[CONSTANTS.HOSTED_SKILL.RESOURCES.INTERACTION_MODEL])[0]; - statusTracker.interactionModel = R.view(R.lensPath([CONSTANTS.HOSTED_SKILL.RESOURCES.INTERACTION_MODEL, locale, - 'lastUpdateRequest', 'status']), response); - } - if (response[CONSTANTS.HOSTED_SKILL.RESOURCES.INTERACTION_MODEL]) { - statusTracker.hostedSkillProvisioning = R.view(R.lensPath([CONSTANTS.HOSTED_SKILL.RESOURCES.PROVISIONING, - 'lastUpdateRequest', 'status']), response); - } - return !statusTracker.manifest || !statusTracker.interactionModel || !statusTracker.hostedSkillProvisioning - || !(statusTracker.manifest === CONSTANTS.HOSTED_SKILL.MANIFEST_STATUS.SUCCESS - && statusTracker.interactionModel === CONSTANTS.HOSTED_SKILL.INTERACTION_MODEL_STATUS.SUCCESS - && statusTracker.hostedSkillProvisioning === CONSTANTS.HOSTED_SKILL.PROVISIONING_STATUS.SUCCESS); - }; - retryUtils.retry(retryConfig, retryCall, shouldRetryCondition, err => callback(err, err ? null : statusTracker)); + const retryConfig = { + base: 1000, + factor: 1.2, + maxRetry: 30, + }; + const RESOURCE_LIST = [ + CONSTANTS.SKILL.RESOURCES.MANIFEST, + CONSTANTS.HOSTED_SKILL.RESOURCES.PROVISIONING, + CONSTANTS.SKILL.RESOURCES.INTERACTION_MODEL, + ]; + const retryCall = (loopCallback) => { + smapiClient.skill.getSkillStatus(skillId, RESOURCE_LIST, (statusErr, statusResponse) => { + if (statusErr) { + return loopCallback(statusErr); + } + if (statusResponse.statusCode >= 300) { + return loopCallback(jsonView.toString(statusResponse.body)); + } + loopCallback(null, statusResponse); + }); + }; + const statusTracker = { + manifest: {}, + interactionModel: {}, + hostedSkillProvisioning: {}, + }; + const shouldRetryCondition = (retryResponse) => { + const response = retryResponse.body; + statusTracker.manifest = R.view(R.lensPath([CONSTANTS.HOSTED_SKILL.RESOURCES.MANIFEST, "lastUpdateRequest", "status"]), response); + if (response[CONSTANTS.HOSTED_SKILL.RESOURCES.INTERACTION_MODEL]) { + const locale = Object.keys(response[CONSTANTS.HOSTED_SKILL.RESOURCES.INTERACTION_MODEL])[0]; + statusTracker.interactionModel = R.view( + R.lensPath([CONSTANTS.HOSTED_SKILL.RESOURCES.INTERACTION_MODEL, locale, "lastUpdateRequest", "status"]), + response, + ); + } + if (response[CONSTANTS.HOSTED_SKILL.RESOURCES.INTERACTION_MODEL]) { + statusTracker.hostedSkillProvisioning = R.view( + R.lensPath([CONSTANTS.HOSTED_SKILL.RESOURCES.PROVISIONING, "lastUpdateRequest", "status"]), + response, + ); + } + return ( + !statusTracker.manifest || + !statusTracker.interactionModel || + !statusTracker.hostedSkillProvisioning || + !( + statusTracker.manifest === CONSTANTS.HOSTED_SKILL.MANIFEST_STATUS.SUCCESS && + statusTracker.interactionModel === CONSTANTS.HOSTED_SKILL.INTERACTION_MODEL_STATUS.SUCCESS && + statusTracker.hostedSkillProvisioning === CONSTANTS.HOSTED_SKILL.PROVISIONING_STATUS.SUCCESS + ) + ); + }; + retryUtils.retry(retryConfig, retryCall, shouldRetryCondition, (err) => callback(err, err ? null : statusTracker)); } function handleSkillStatus(response, skillId, callback) { - if (!response) { - return callback('Response from the creation of hosted skill is not valid.'); + if (!response) { + return callback("Response from the creation of hosted skill is not valid."); + } + if ( + response.hostedSkillProvisioning === CONSTANTS.HOSTED_SKILL.PROVISIONING_STATUS.SUCCESS && + response.interactionModel === CONSTANTS.HOSTED_SKILL.INTERACTION_MODEL_STATUS.SUCCESS && + response.manifest === CONSTANTS.HOSTED_SKILL.INTERACTION_MODEL_STATUS.SUCCESS + ) { + callback(null, skillId); + } else if ( + response.hostedSkillProvisioning === CONSTANTS.HOSTED_SKILL.PROVISIONING_STATUS.IN_PROGRESS || + response.interactionModel === CONSTANTS.HOSTED_SKILL.INTERACTION_MODEL_STATUS.IN_PROGRESS || + response.manifest === CONSTANTS.HOSTED_SKILL.MANIFEST_STATUS.IN_PROGRESS + ) { + callback("Timeout when checking the status of hosted-skill creation. Please try again."); + } else { + const errMessage = "Check skill status failed for the following reason:\n"; + let errReason = ""; + if (response.hostedSkillProvisioning === CONSTANTS.HOSTED_SKILL.PROVISIONING_STATUS.FAILURE) { + errReason = errReason.concat("Skill provisioning step failed.\n"); + } + if (response.interactionModel === CONSTANTS.HOSTED_SKILL.INTERACTION_MODEL_STATUS.FAILURE) { + errReason = errReason.concat("Skill interaction model building step failed\n"); } - if (response.hostedSkillProvisioning === CONSTANTS.HOSTED_SKILL.PROVISIONING_STATUS.SUCCESS - && response.interactionModel === CONSTANTS.HOSTED_SKILL.INTERACTION_MODEL_STATUS.SUCCESS - && response.manifest === CONSTANTS.HOSTED_SKILL.INTERACTION_MODEL_STATUS.SUCCESS) { - callback(null, skillId); - } else if (response.hostedSkillProvisioning === CONSTANTS.HOSTED_SKILL.PROVISIONING_STATUS.IN_PROGRESS - || response.interactionModel === CONSTANTS.HOSTED_SKILL.INTERACTION_MODEL_STATUS.IN_PROGRESS - || response.manifest === CONSTANTS.HOSTED_SKILL.MANIFEST_STATUS.IN_PROGRESS) { - callback('Timeout when checking the status of hosted-skill creation. Please try again.'); - } else { - const errMessage = 'Check skill status failed for the following reason:\n'; - let errReason = ''; - if (response.hostedSkillProvisioning === CONSTANTS.HOSTED_SKILL.PROVISIONING_STATUS.FAILURE) { - errReason = errReason.concat('Skill provisioning step failed.\n'); - } - if (response.interactionModel === CONSTANTS.HOSTED_SKILL.INTERACTION_MODEL_STATUS.FAILURE) { - errReason = errReason.concat('Skill interaction model building step failed\n'); - } - if (response.manifest === CONSTANTS.HOSTED_SKILL.MANIFEST_STATUS.FAILURE) { - errReason = errReason.concat('Skill manifest building step failed\n'); - } - callback(`${errMessage}${errReason}Infrastructure provision for the hosted skill failed. Please try again.`); + if (response.manifest === CONSTANTS.HOSTED_SKILL.MANIFEST_STATUS.FAILURE) { + errReason = errReason.concat("Skill manifest building step failed\n"); } + callback(`${errMessage}${errReason}Infrastructure provision for the hosted skill failed. Please try again.`); + } } function downloadAuthInfoScript(callback) { - const authInfoUrl = DynamicConfig.s3Scripts.authInfo; - const authInfoPath = path.join(os.homedir(), - CONSTANTS.FILE_PATH.ASK.HIDDEN_FOLDER, - CONSTANTS.FILE_PATH.ASK.AUTH_INFO); - this.downloadScriptFromS3(authInfoUrl, authInfoPath, (err) => callback(err || null)); + const authInfoUrl = DynamicConfig.s3Scripts.authInfo; + const authInfoPath = path.join(os.homedir(), CONSTANTS.FILE_PATH.ASK.HIDDEN_FOLDER, CONSTANTS.FILE_PATH.ASK.AUTH_INFO); + this.downloadScriptFromS3(authInfoUrl, authInfoPath, (err) => callback(err || null)); } function downloadAskPrePushScript(callback) { - const askScriptUrl = DynamicConfig.s3Scripts.askPrePush; - const scriptFolderPath = path.join(os.homedir(), - CONSTANTS.FILE_PATH.ASK.HIDDEN_FOLDER, - CONSTANTS.FILE_PATH.ASK.SCRIPTS_FOLDER.NAME); - const askFilePath = path.join(os.homedir(), - CONSTANTS.FILE_PATH.ASK.HIDDEN_FOLDER, - CONSTANTS.FILE_PATH.ASK.SCRIPTS_FOLDER.NAME, - CONSTANTS.FILE_PATH.ASK.SCRIPTS_FOLDER.ASK_PRE_PUSH); - fs.ensureDirSync(scriptFolderPath); - this.downloadScriptFromS3(askScriptUrl, askFilePath, (err) => callback(err || null)); + const askScriptUrl = DynamicConfig.s3Scripts.askPrePush; + const scriptFolderPath = path.join(os.homedir(), CONSTANTS.FILE_PATH.ASK.HIDDEN_FOLDER, CONSTANTS.FILE_PATH.ASK.SCRIPTS_FOLDER.NAME); + const askFilePath = path.join( + os.homedir(), + CONSTANTS.FILE_PATH.ASK.HIDDEN_FOLDER, + CONSTANTS.FILE_PATH.ASK.SCRIPTS_FOLDER.NAME, + CONSTANTS.FILE_PATH.ASK.SCRIPTS_FOLDER.ASK_PRE_PUSH, + ); + fs.ensureDirSync(scriptFolderPath); + this.downloadScriptFromS3(askScriptUrl, askFilePath, (err) => callback(err || null)); } function downloadGitCredentialHelperScript(callback) { - const credentialScriptUrl = DynamicConfig.s3Scripts.gitCredentialHelper; - const scriptFolderPath = path.join(os.homedir(), - CONSTANTS.FILE_PATH.ASK.HIDDEN_FOLDER, - CONSTANTS.FILE_PATH.ASK.SCRIPTS_FOLDER.NAME); - const credentialFilePath = path.join(os.homedir(), - CONSTANTS.FILE_PATH.ASK.HIDDEN_FOLDER, - CONSTANTS.FILE_PATH.ASK.SCRIPTS_FOLDER.NAME, - CONSTANTS.FILE_PATH.ASK.SCRIPTS_FOLDER.GIT_CREDENTIAL_HELPER); - fs.ensureDirSync(scriptFolderPath); - this.downloadScriptFromS3(credentialScriptUrl, credentialFilePath, (err) => callback(err || null)); + const credentialScriptUrl = DynamicConfig.s3Scripts.gitCredentialHelper; + const scriptFolderPath = path.join(os.homedir(), CONSTANTS.FILE_PATH.ASK.HIDDEN_FOLDER, CONSTANTS.FILE_PATH.ASK.SCRIPTS_FOLDER.NAME); + const credentialFilePath = path.join( + os.homedir(), + CONSTANTS.FILE_PATH.ASK.HIDDEN_FOLDER, + CONSTANTS.FILE_PATH.ASK.SCRIPTS_FOLDER.NAME, + CONSTANTS.FILE_PATH.ASK.SCRIPTS_FOLDER.GIT_CREDENTIAL_HELPER, + ); + fs.ensureDirSync(scriptFolderPath); + this.downloadScriptFromS3(credentialScriptUrl, credentialFilePath, (err) => callback(err || null)); } function downloadScriptFromS3(scriptUrl, filePath, callback) { - const DOWNLOADED = 'downloaded'; - const retryCall = (loopCallback) => { - const writeStream = fs.createWriteStream(filePath); - https.get(scriptUrl, (res) => { - res.pipe(writeStream); - writeStream.on('finish', () => { - fs.chmodSync(filePath, '700'); - loopCallback(null, DOWNLOADED); - }); - }).on('error', (err) => { - loopCallback(new Error(err)); + const DOWNLOADED = "downloaded"; + const retryCall = (loopCallback) => { + const writeStream = fs.createWriteStream(filePath); + https + .get(scriptUrl, (res) => { + res.pipe(writeStream); + writeStream.on("finish", () => { + fs.chmodSync(filePath, "700"); + loopCallback(null, DOWNLOADED); }); - }; - const shouldRetryCondition = retryResponse => retryResponse !== DOWNLOADED; - retryUtils.retry(RETRY_OPTION, retryCall, shouldRetryCondition, (err, res) => callback(err, err ? null : res)); + }) + .on("error", (err) => { + loopCallback(new Error(err)); + }); + }; + const shouldRetryCondition = (retryResponse) => retryResponse !== DOWNLOADED; + retryUtils.retry(RETRY_OPTION, retryCall, shouldRetryCondition, (err, res) => callback(err, err ? null : res)); } diff --git a/lib/controllers/hosted-skill-controller/index.js b/lib/controllers/hosted-skill-controller/index.js index 4102c355..7452cc13 100644 --- a/lib/controllers/hosted-skill-controller/index.js +++ b/lib/controllers/hosted-skill-controller/index.js @@ -1,210 +1,212 @@ -const fs = require('fs-extra'); -const os = require('os'); -const path = require('path'); +const fs = require("fs-extra"); +const os = require("os"); +const path = require("path"); -const SmapiClient = require('@src/clients/smapi-client'); -const SkillMetadataController = require('@src/controllers/skill-metadata-controller'); -const CONSTANTS = require('@src/utils/constants'); -const DynamicConfig = require('@src/utils/dynamic-config'); -const jsonView = require('@src/view/json-view'); -const Messenger = require('@src/view/messenger'); +const SmapiClient = require("../../clients/smapi-client").default; +const SkillMetadataController = require("../skill-metadata-controller"); +const CONSTANTS = require("../../utils/constants"); +const DynamicConfig = require("../../utils/dynamic-config"); +const jsonView = require("../../view/json-view"); +const Messenger = require("../../view/messenger"); -const cloneFlow = require('./clone-flow'); -const helper = require('./helper'); +const cloneFlow = require("./clone-flow"); +const helper = require("./helper"); module.exports = class HostedSkillController { - constructor(configuration) { - const { profile, doDebug } = configuration; - this.profile = profile; - this.doDebug = doDebug; - this.smapiClient = new SmapiClient({ profile, doDebug }); - this.skillMetaController = new SkillMetadataController({ profile, doDebug }); - } + constructor(configuration) { + const {profile, doDebug} = configuration; + this.profile = profile; + this.doDebug = doDebug; + this.smapiClient = new SmapiClient({profile, doDebug}); + this.skillMetaController = new SkillMetadataController({profile, doDebug}); + } - /** - * To create an Alexa hosted skill - * @param {JSON} hostedSkillPayload the JSON representation of the skill, and provides Alexa with all of the metadata required - * @param {callback} callback { error, response } - */ - createSkill(hostedSkillPayload, callback) { - this.smapiClient.skill.alexaHosted.createHostedSkill(hostedSkillPayload, (createErr, createRes) => { - if (createErr) { - return callback(createErr); - } - if (createRes.statusCode >= 300) { - return callback(jsonView.toString(createRes.body)); - } - const { skillId } = createRes.body; - helper.pollingSkillStatus(this.smapiClient, skillId, (pollErr, pollRes) => { - if (pollErr) { - return callback(pollErr); - } - helper.handleSkillStatus(pollRes, skillId, (handleErr) => { - callback(handleErr, skillId); - }); - }); + /** + * To create an Alexa hosted skill + * @param {Object} hostedSkillPayload the JSON representation of the skill, and provides Alexa with all of the metadata required + * @param {callback} callback { error, response } + */ + createSkill(hostedSkillPayload, callback) { + this.smapiClient.skill.alexaHosted.createHostedSkill(hostedSkillPayload, (createErr, createRes) => { + if (createErr) { + return callback(createErr); + } + if (createRes.statusCode >= 300) { + return callback(jsonView.toString(createRes.body)); + } + const {skillId} = createRes.body; + helper.pollingSkillStatus(this.smapiClient, skillId, (pollErr, pollRes) => { + if (pollErr) { + return callback(pollErr); + } + helper.handleSkillStatus(pollRes, skillId, (handleErr) => { + callback(handleErr, skillId); }); - } + }); + }); + } - /** - * To clone an Alexa hosted skill from git repository to local project directory - * @param {string} skillId The skill id - * @param {string} skillName The skill name - * @param {string} projectPath The skill project folder path - * @param {callback} callback { error, response } - */ - clone(skillId, skillName, projectPath, callback) { - if (fs.existsSync(projectPath)) { - return callback(`${projectPath} directory already exists.`); + /** + * To clone an Alexa hosted skill from git repository to local project directory + * @param {string} skillId The skill id + * @param {string} skillName The skill name + * @param {string} projectPath The skill project folder path + * @param {callback} callback { error, response } + */ + clone(skillId, skillName, projectPath, callback) { + if (fs.existsSync(projectPath)) { + return callback(`${projectPath} directory already exists.`); + } + // 0. get hosted skill info + this.getHostedSkillMetadata(skillId, (metadataErr, metadata) => { + if (metadataErr) { + return callback(metadataErr); + } + // 1. generate project + cloneFlow.generateProject(projectPath, skillId, skillName, metadata, this.profile); + // 2. clone project, set up git + cloneFlow.cloneProjectFromGit(projectPath, skillId, skillName, this.profile, metadata.repository.url, this.doDebug); + // 3. check skill-package content + cloneFlow.doSkillPackageExist(skillName, projectPath, skillId, (checkErr, doExist) => { + if (checkErr) { + return callback(checkErr); } - // 0. get hosted skill info - this.getHostedSkillMetadata(skillId, (metadataErr, metadata) => { - if (metadataErr) { - return callback(metadataErr); + if (!doExist) { + this.skillMetaController.getSkillPackage(projectPath, skillId, CONSTANTS.SKILL.STAGE.DEVELOPMENT, (exportErr) => { + if (exportErr) { + return callback(exportErr); } - // 1. generate project - cloneFlow.generateProject(projectPath, skillId, skillName, metadata, this.profile); - // 2. clone project, set up git - cloneFlow.cloneProjectFromGit(projectPath, skillId, skillName, this.profile, metadata.repository.url, this.doDebug); - // 3. check skill-package content - cloneFlow.doSkillPackageExist(skillName, projectPath, skillId, (checkErr, doExist) => { - if (checkErr) { - return callback(checkErr); - } - if (!doExist) { - this.skillMetaController.getSkillPackage(projectPath, skillId, CONSTANTS.SKILL.STAGE.DEVELOPMENT, (exportErr) => { - if (exportErr) { - return callback(exportErr); - } - Messenger.getInstance().info(`\nSkill schema and interactionModels for ${skillName} created at\n\t./skill-package\n`); - callback(); - }); - } else { - Messenger.getInstance().info(`\nSkill schema and interactionModels for ${skillName} created at\n\t./skill-package\n`); - callback(); - } - }); - }); - } + Messenger.getInstance().info(`\nSkill schema and interactionModels for ${skillName} created at\n\t./skill-package\n`); + callback(); + }); + } else { + Messenger.getInstance().info(`\nSkill schema and interactionModels for ${skillName} created at\n\t./skill-package\n`); + callback(); + } + }); + }); + } - /** - * To fetch Alexa hosted skill metadata - * @param {string} skillId The skill id - * @param {callback} callback { error, response } - */ - getHostedSkillMetadata(skillId, callback) { - this.smapiClient.skill.alexaHosted.getAlexaHostedSkillMetadata(skillId, (err, response) => { - if (err) { - return callback(err); - } - if (response.statusCode >= 300) { - const error = jsonView.toString(response.body); - return callback(error); - } - callback(null, response.body.alexaHosted); - }); - } + /** + * To fetch Alexa hosted skill metadata + * @param {string} skillId The skill id + * @param {callback} callback { error, response } + */ + getHostedSkillMetadata(skillId, callback) { + this.smapiClient.skill.alexaHosted.getAlexaHostedSkillMetadata(skillId, (err, response) => { + if (err) { + return callback(err); + } + if (response.statusCode >= 300) { + const error = jsonView.toString(response.body); + return callback(error); + } + callback(null, response.body.alexaHosted); + }); + } - /** - * To check if current user is allowed to invoke HostedSkill functions - * @param {string} vendorId The vendor ID - * @param {string} permissionType The permission enum type - * @param {callback} callback { error, response } - */ - getHostedSkillPermission(vendorId, permissionType, callback) { - this.smapiClient.skill.alexaHosted.getHostedSkillPermission(vendorId, permissionType, (err, response) => { - if (err) { - return callback(err); - } - if (response.statusCode >= 300) { - return callback(jsonView.toString(response.body)); - } - callback(null, response.body); - }); - } + /** + * To check if current user is allowed to invoke HostedSkill functions + * @param {string} vendorId The vendor ID + * @param {string} permissionType The permission enum type + * @param {callback} callback { error, response } + */ + getHostedSkillPermission(vendorId, permissionType, callback) { + this.smapiClient.skill.alexaHosted.getHostedSkillPermission(vendorId, permissionType, (err, response) => { + if (err) { + return callback(err); + } + if (response.statusCode >= 300) { + return callback(jsonView.toString(response.body)); + } + callback(null, response.body); + }); + } - /** - * To check skill status by keeping submitting the request - * until the resources' status are all SUCCEEDED or heat the max retry time - * @param {Object} smapiClient SMAPI client to make request - * @param {string} skillId The skill id - * @param {callback} callback { error, response } - */ - checkSkillStatus(skillId, callback) { - helper.pollingSkillStatus(this.smapiClient, skillId, (pollErr, pollRes) => { - if (pollErr) { - return callback(pollErr); - } - helper.handleSkillStatus(pollRes, skillId, (handleErr) => { - if (handleErr) { - return callback(handleErr); - } - callback(null, skillId); - }); - }); - } + /** + * To check skill status by keeping submitting the request + * until the resources' status are all SUCCEEDED or heat the max retry time + * @param {Object} smapiClient SMAPI client to make request + * @param {string} skillId The skill id + * @param {callback} callback { error, response } + */ + checkSkillStatus(skillId, callback) { + helper.pollingSkillStatus(this.smapiClient, skillId, (pollErr, pollRes) => { + if (pollErr) { + return callback(pollErr); + } + helper.handleSkillStatus(pollRes, skillId, (handleErr) => { + if (handleErr) { + return callback(handleErr); + } + callback(null, skillId); + }); + }); + } - /** - * To delete an Alexa hosted skill - * @param {string} skillId The skill ID - * @param {callback} callback { error, response } - */ - deleteSkill(skillId, callback) { - this.smapiClient.skill.deleteSkill(skillId, (err) => { - if (err) { - return callback(err); - } - callback(); - }); - } + /** + * To delete an Alexa hosted skill + * @param {string} skillId The skill ID + * @param {callback} callback { error, response } + */ + deleteSkill(skillId, callback) { + this.smapiClient.skill.deleteSkill(skillId, (err) => { + if (err) { + return callback(err); + } + callback(); + }); + } - /** - * To update ASK system-wide scripts and download the pre-push hook to the skill project git folder - * @param {String} folderName the project folder name - * @param {callback} callback { error, response } - */ - downloadAskScripts(folderName, callback) { - const askFolderPath = path.join(os.homedir(), CONSTANTS.FILE_PATH.ASK.HIDDEN_FOLDER); - fs.ensureDirSync(askFolderPath); - this.updateAskSystemScripts((err) => { - if (err) { - return callback(err); - } - this.updateSkillPrePushScript(folderName, (prePushErr) => callback(prePushErr || null)); - }); - } + /** + * To update ASK system-wide scripts and download the pre-push hook to the skill project git folder + * @param {String} folderName the project folder name + * @param {callback} callback { error, response } + */ + downloadAskScripts(folderName, callback) { + const askFolderPath = path.join(os.homedir(), CONSTANTS.FILE_PATH.ASK.HIDDEN_FOLDER); + fs.ensureDirSync(askFolderPath); + this.updateAskSystemScripts((err) => { + if (err) { + return callback(err); + } + this.updateSkillPrePushScript(folderName, (prePushErr) => callback(prePushErr || null)); + }); + } - /** - * To update all ASK system-wide scripts from S3 - * @param {callback} callback { error, response } - */ - updateAskSystemScripts(callback) { - const askFolderPath = path.join(os.homedir(), CONSTANTS.FILE_PATH.ASK.HIDDEN_FOLDER); - fs.ensureDirSync(askFolderPath); - helper.downloadAuthInfoScript((authInfoErr) => { - if (authInfoErr) { - return callback(authInfoErr); - } - helper.downloadAskPrePushScript((prePushErr) => { - if (prePushErr) { - return callback(prePushErr); - } - helper.downloadGitCredentialHelperScript((credentialErr) => callback(credentialErr || null)); - }); - }); - } + /** + * To update all ASK system-wide scripts from S3 + * @param {callback} callback { error, response } + */ + updateAskSystemScripts(callback) { + const askFolderPath = path.join(os.homedir(), CONSTANTS.FILE_PATH.ASK.HIDDEN_FOLDER); + fs.ensureDirSync(askFolderPath); + helper.downloadAuthInfoScript((authInfoErr) => { + if (authInfoErr) { + return callback(authInfoErr); + } + helper.downloadAskPrePushScript((prePushErr) => { + if (prePushErr) { + return callback(prePushErr); + } + helper.downloadGitCredentialHelperScript((credentialErr) => callback(credentialErr || null)); + }); + }); + } - /** - * To update pre-push scripts in the skill project from S3 - * @param {String} folderName the project folder name - * @param {callback} callback { error, response } - */ - updateSkillPrePushScript(folderName, callback) { - const prePushUrl = DynamicConfig.s3Scripts.prePush; - const filePath = path.join(folderName, - CONSTANTS.HOSTED_SKILL.HIDDEN_GIT_FOLDER.NAME, - CONSTANTS.HOSTED_SKILL.HIDDEN_GIT_FOLDER.HOOKS.NAME, - CONSTANTS.HOSTED_SKILL.HIDDEN_GIT_FOLDER.HOOKS.PRE_PUSH); - helper.downloadScriptFromS3(prePushUrl, filePath, (downloadErr) => callback(downloadErr || null)); - } + /** + * To update pre-push scripts in the skill project from S3 + * @param {String} folderName the project folder name + * @param {callback} callback { error, response } + */ + updateSkillPrePushScript(folderName, callback) { + const prePushUrl = DynamicConfig.s3Scripts.prePush; + const filePath = path.join( + folderName, + CONSTANTS.HOSTED_SKILL.HIDDEN_GIT_FOLDER.NAME, + CONSTANTS.HOSTED_SKILL.HIDDEN_GIT_FOLDER.HOOKS.NAME, + CONSTANTS.HOSTED_SKILL.HIDDEN_GIT_FOLDER.HOOKS.PRE_PUSH, + ); + helper.downloadScriptFromS3(prePushUrl, filePath, (downloadErr) => callback(downloadErr || null)); + } }; diff --git a/lib/controllers/skill-code-controller/code-builder.js b/lib/controllers/skill-code-controller/code-builder.js index f86c49cc..b432902d 100644 --- a/lib/controllers/skill-code-controller/code-builder.js +++ b/lib/controllers/skill-code-controller/code-builder.js @@ -1,59 +1,53 @@ -const fs = require('fs-extra'); -const path = require('path'); +const fs = require("fs-extra"); +const path = require("path"); -const CustomBuildFlow = require('@src/builtins/build-flows/custom'); -const JavaMvnBuildFlow = require('@src/builtins/build-flows/java-mvn'); -const NodeJsNpmBuildFlow = require('@src/builtins/build-flows/nodejs-npm'); -const PythonPipBuildFlow = require('@src/builtins/build-flows/python-pip'); -const ZipOnlyBuildFlow = require('@src/builtins/build-flows/zip-only'); +const CustomBuildFlow = require("../../builtins/build-flows/custom"); +const JavaMvnBuildFlow = require("../../builtins/build-flows/java-mvn"); +const NodeJsNpmBuildFlow = require("../../builtins/build-flows/nodejs-npm"); +const PythonPipBuildFlow = require("../../builtins/build-flows/python-pip"); +const ZipOnlyBuildFlow = require("../../builtins/build-flows/zip-only"); // order is important -const BUILD_FLOWS = [ - CustomBuildFlow, - NodeJsNpmBuildFlow, - JavaMvnBuildFlow, - PythonPipBuildFlow, - ZipOnlyBuildFlow -]; +const BUILD_FLOWS = [CustomBuildFlow, NodeJsNpmBuildFlow, JavaMvnBuildFlow, PythonPipBuildFlow, ZipOnlyBuildFlow]; class CodeBuilder { - /** - * Constructor for CodeBuilder - * @param {Object} config { src, build, doDebug }, where build = { folder, file }. - */ - constructor(config) { - const { src, build, doDebug } = config; - this.src = src; - this.build = build; - this.doDebug = doDebug; - this.BuildFlowClass = {}; - this._selectBuildFlowClass(); - } + /** + * Constructor for CodeBuilder + * @param {Object} config { src, build, doDebug }, where build = { folder, file }. + */ + constructor(config) { + const {src, build, doDebug} = config; + this.src = src; + this.build = build; + this.doDebug = doDebug; + this.BuildFlowClass = {}; + this._selectBuildFlowClass(); + } - /** - * Executes build flow - * @param {Function} callback (error) - */ - execute(callback) { - try { - this._setUpBuildFolder(); - } catch (fsErr) { - return process.nextTick(callback(fsErr)); - } - const options = { cwd: this.build.folder, src: this.src, buildFile: this.build.file, doDebug: this.doDebug }; - const builder = new this.BuildFlowClass(options); - builder.execute((error) => callback(error)); + /** + * Executes build flow + * @param {Function} callback (error) + */ + execute(callback) { + try { + this._setUpBuildFolder(); + } catch (fsErr) { + return process.nextTick(callback(fsErr)); } + const options = {cwd: this.build.folder, src: this.src, buildFile: this.build.file, doDebug: this.doDebug}; + const builder = new this.BuildFlowClass(options); + builder.execute((error) => callback(error)); + } - _setUpBuildFolder() { - fs.ensureDirSync(this.build.folder); - fs.emptyDirSync(this.build.folder); - fs.copySync(path.resolve(this.src), this.build.folder, { filter: src => !src.includes(this.build.folder) }); - } + _setUpBuildFolder() { + fs.ensureDirSync(this.build.folder); + fs.emptyDirSync(this.build.folder); + fs.copySync(path.resolve(this.src), this.build.folder, {filter: (src) => !src.includes(this.build.folder)}); + } - _selectBuildFlowClass() { - this.BuildFlowClass = BUILD_FLOWS.find(flow => flow.canHandle({ src: this.src })); - } + _selectBuildFlowClass() { + this.BuildFlowClass = BUILD_FLOWS.find((flow) => flow.canHandle({src: this.src})); + } } module.exports = CodeBuilder; diff --git a/lib/controllers/skill-code-controller/index.js b/lib/controllers/skill-code-controller/index.js index fa54c687..c41015fe 100644 --- a/lib/controllers/skill-code-controller/index.js +++ b/lib/controllers/skill-code-controller/index.js @@ -1,83 +1,87 @@ -const fs = require('fs-extra'); -const async = require('async'); +const fs = require("fs-extra"); +const async = require("async"); -const ResourcesConfig = require('@src/model/resources-config'); -const stringUtils = require('@src/utils/string-utils'); -const CodeBuilder = require('./code-builder'); +const ResourcesConfig = require("../../model/resources-config"); +const stringUtils = require("../../utils/string-utils"); +const CodeBuilder = require("./code-builder"); module.exports = class SkillCodeController { - /** - * Constructor for SkillCodeController - * @param {Object} configuration { profile, doDebug } - */ - constructor(configuration) { - const { profile, doDebug } = configuration; - this.profile = profile; - this.doDebug = doDebug; - } + /** + * Constructor for SkillCodeController + * @param {Object} configuration { profile, doDebug } + */ + constructor(configuration) { + const {profile, doDebug} = configuration; + this.profile = profile; + this.doDebug = doDebug; + } - /** - * Decide the unique codebase to build and execute the building process from CodeBuilder - * @param {Function} callback (error, uniqueCodeList) - * @param {Function} callback.uniqueCodeList [{ src, build{file, folder}}, buildFlow, regionsList }] - */ - buildCode(callback) { - let uniqueCodeList; - try { - uniqueCodeList = this._resolveUniqueCodeList(); - } catch (codeErr) { - return callback(codeErr); - } - // execute build logic based on the regional code settings - async.each(uniqueCodeList, (codeProperty, eachCallback) => { - const codeBuilder = new CodeBuilder({ - src: codeProperty.src, - build: codeProperty.build, - doDebug: this.doDebug - }); - codeProperty.buildFlow = codeBuilder.BuildFlowClass.name; - codeBuilder.execute((execErr) => { - eachCallback(execErr); - }); - }, (err) => { - callback(err, err ? null : uniqueCodeList); - }); + /** + * Decide the unique codebase to build and execute the building process from CodeBuilder + * @param {Function} callback (error, uniqueCodeList) + * @param {Function} callback.uniqueCodeList [{ src, build{file, folder}}, buildFlow, regionsList }] + */ + buildCode(callback) { + let uniqueCodeList; + try { + uniqueCodeList = this._resolveUniqueCodeList(); + } catch (codeErr) { + return callback(codeErr); } + // execute build logic based on the regional code settings + async.each( + uniqueCodeList, + (codeProperty, eachCallback) => { + const codeBuilder = new CodeBuilder({ + src: codeProperty.src, + build: codeProperty.build, + doDebug: this.doDebug, + }); + codeProperty.buildFlow = codeBuilder.BuildFlowClass.name; + codeBuilder.execute((execErr) => { + eachCallback(execErr); + }); + }, + (err) => { + callback(err, err ? null : uniqueCodeList); + }, + ); + } - /** - * Resolve the list of unique codebases from the codeResources from ask-resources config. - * @return {Array} codeList in the structure of [{ src, build, regionsList }] - */ - _resolveUniqueCodeList() { - const codeRegionsList = ResourcesConfig.getInstance().getCodeRegions(this.profile); - // register codeResources as a HashMap with following structure { codeSrc: [regionsList] } - const codeSrcToRegionMap = new Map(); - for (const region of codeRegionsList) { - const codeSrc = ResourcesConfig.getInstance().getCodeSrcByRegion(this.profile, region); - if (!stringUtils.isNonBlankString(codeSrc)) { - throw `Invalid code setting in region ${region}. "src" must be set if you want to deploy skill code with skill package.`; - } - if (!fs.existsSync(codeSrc)) { - throw `Invalid code setting in region ${region}. File doesn't exist for code src: ${codeSrc}.`; - } - // check if HashMap has codeSrc: append the region if codeSrc exists, or register an array with current region to the codeSrc - if (codeSrcToRegionMap.has(codeSrc)) { - const existingRegions = codeSrcToRegionMap.get(codeSrc); - existingRegions.push(region); - codeSrcToRegionMap.set(codeSrc, existingRegions); - } else { - codeSrcToRegionMap.set(codeSrc, [region]); - } - } - // convert the HashMap to a list of unique code properties list - const uniqueCodeList = []; - for (const entry of codeSrcToRegionMap.entries()) { - uniqueCodeList.push({ - src: entry[0], - build: ResourcesConfig.getInstance().getCodeBuildByRegion(this.profile, entry[1][0]), - regionsList: entry[1] - }); - } - return uniqueCodeList; + /** + * Resolve the list of unique codebases from the codeResources from ask-resources config. + * @return {Array} codeList in the structure of [{ src, build, regionsList }] + */ + _resolveUniqueCodeList() { + const codeRegionsList = ResourcesConfig.getInstance().getCodeRegions(this.profile); + // register codeResources as a HashMap with following structure { codeSrc: [regionsList] } + const codeSrcToRegionMap = new Map(); + for (const region of codeRegionsList) { + const codeSrc = ResourcesConfig.getInstance().getCodeSrcByRegion(this.profile, region); + if (!stringUtils.isNonBlankString(codeSrc)) { + throw `Invalid code setting in region ${region}. "src" must be set if you want to deploy skill code with skill package.`; + } + if (!fs.existsSync(codeSrc)) { + throw `Invalid code setting in region ${region}. File doesn't exist for code src: ${codeSrc}.`; + } + // check if HashMap has codeSrc: append the region if codeSrc exists, or register an array with current region to the codeSrc + if (codeSrcToRegionMap.has(codeSrc)) { + const existingRegions = codeSrcToRegionMap.get(codeSrc); + existingRegions.push(region); + codeSrcToRegionMap.set(codeSrc, existingRegions); + } else { + codeSrcToRegionMap.set(codeSrc, [region]); + } + } + // convert the HashMap to a list of unique code properties list + const uniqueCodeList = []; + for (const entry of codeSrcToRegionMap.entries()) { + uniqueCodeList.push({ + src: entry[0], + build: ResourcesConfig.getInstance().getCodeBuildByRegion(this.profile, entry[1][0]), + regionsList: entry[1], + }); } + return uniqueCodeList; + } }; diff --git a/lib/controllers/skill-infrastructure-controller/deploy-delegate.js b/lib/controllers/skill-infrastructure-controller/deploy-delegate.js index e66e1d32..81dc2bed 100644 --- a/lib/controllers/skill-infrastructure-controller/deploy-delegate.js +++ b/lib/controllers/skill-infrastructure-controller/deploy-delegate.js @@ -1,32 +1,32 @@ -const path = require('path'); +const path = require("path"); -const CONSTANTS = require('@src/utils/constants'); +const CONSTANTS = require("../../utils/constants"); const BUILT_IN_DEPLOY_DELEGATES = { - [CONSTANTS.DEPLOYER_TYPE.CFN.NAME]: { - location: 'cfn-deployer', - description: CONSTANTS.DEPLOYER_TYPE.CFN.DESCRIPTION, - templates: { - branch: 'ask-cli-x', - language_map: { - NodeJS: 'https://ask-cli-static-content.s3-us-west-2.amazonaws.com/skill-templates/NodeJS/cfn-deployer-templates.json', - Python: 'https://ask-cli-static-content.s3-us-west-2.amazonaws.com/skill-templates/Python/cfn-deployer-templates.json', - Java: 'https://ask-cli-static-content.s3-us-west-2.amazonaws.com/skill-templates/Java/cfn-deployer-templates.json' - } - } + [CONSTANTS.DEPLOYER_TYPE.CFN.NAME]: { + location: "cfn-deployer", + description: CONSTANTS.DEPLOYER_TYPE.CFN.DESCRIPTION, + templates: { + branch: "ask-cli-x", + language_map: { + NodeJS: "https://ask-cli-static-content.s3-us-west-2.amazonaws.com/skill-templates/NodeJS/cfn-deployer-templates.json", + Python: "https://ask-cli-static-content.s3-us-west-2.amazonaws.com/skill-templates/Python/cfn-deployer-templates.json", + Java: "https://ask-cli-static-content.s3-us-west-2.amazonaws.com/skill-templates/Java/cfn-deployer-templates.json", + }, }, - [CONSTANTS.DEPLOYER_TYPE.LAMBDA.NAME]: { - location: 'lambda-deployer', - description: CONSTANTS.DEPLOYER_TYPE.LAMBDA.DESCRIPTION, - templates: { - branch: 'ask-cli-x', - language_map: { - NodeJS: 'https://ask-cli-static-content.s3-us-west-2.amazonaws.com/skill-templates/NodeJS/lambda-deployer-templates.json', - Python: 'https://ask-cli-static-content.s3-us-west-2.amazonaws.com/skill-templates/Python/lambda-deployer-templates.json', - Java: 'https://ask-cli-static-content.s3-us-west-2.amazonaws.com/skill-templates/Java/lambda-deployer-templates.json' - } - } - } + }, + [CONSTANTS.DEPLOYER_TYPE.LAMBDA.NAME]: { + location: "lambda-deployer", + description: CONSTANTS.DEPLOYER_TYPE.LAMBDA.DESCRIPTION, + templates: { + branch: "ask-cli-x", + language_map: { + NodeJS: "https://ask-cli-static-content.s3-us-west-2.amazonaws.com/skill-templates/NodeJS/lambda-deployer-templates.json", + Python: "https://ask-cli-static-content.s3-us-west-2.amazonaws.com/skill-templates/Python/lambda-deployer-templates.json", + Java: "https://ask-cli-static-content.s3-us-west-2.amazonaws.com/skill-templates/Java/lambda-deployer-templates.json", + }, + }, + }, }; /** @@ -53,83 +53,83 @@ const BUILT_IN_DEPLOY_DELEGATES = { * result.deployState the result of deploy to be tracked in ask-resources config */ class DeployDelegate { - /** - * Constructor for wrapping the deploy delegate instance to enforce its contract with ask-cli. - * @param {String} type the deploy delegate type name - * @param {Object} instance the instance for the deploy delegate - */ - constructor(type, instance) { - this.type = type; - this.instance = instance; - this._validateDeployDelegateMethods(); - } + /** + * Constructor for wrapping the deploy delegate instance to enforce its contract with ask-cli. + * @param {String} type the deploy delegate type name + * @param {Object} instance the instance for the deploy delegate + */ + constructor(type, instance) { + this.type = type; + this.instance = instance; + this._validateDeployDelegateMethods(); + } - /** - * Wrapper of deployDelegate's bootstrap method - * @param {Function} callback - */ - bootstrap(options, callback) { - if (!this.instance) { - return callback('[Fatal]: Please instantiate the DeployDelegate class before using.'); - } - this.instance.bootstrap(options, callback); + /** + * Wrapper of deployDelegate's bootstrap method + * @param {Function} callback + */ + bootstrap(options, callback) { + if (!this.instance) { + return callback("[Fatal]: Please instantiate the DeployDelegate class before using."); } + this.instance.bootstrap(options, callback); + } - /** - * Wrapper of deployDelegate's invoke method - * @param {Object} reporter upstream CLI status reporter - * @param {Object} options Invoke options { profile, alexaRegion, skillId, skillName, code, userConfig, deployState } - * @param {Function} callback - */ - invoke(reporter, options, callback) { - if (!this.instance) { - return callback('[Fatal]: Please instantiate the DeployDelegate class before using.'); - } - this.instance.invoke(reporter, options, callback); + /** + * Wrapper of deployDelegate's invoke method + * @param {Object} reporter upstream CLI status reporter + * @param {Object} options Invoke options { profile, alexaRegion, skillId, skillName, code, userConfig, deployState } + * @param {Function} callback + */ + invoke(reporter, options, callback) { + if (!this.instance) { + return callback("[Fatal]: Please instantiate the DeployDelegate class before using."); } + this.instance.invoke(reporter, options, callback); + } - /** - * Validate if the response from DeployDelegate is following the contract between ask-cli and DeployDelegate. - * @param {Object} deployResult the result from deployDelegate's invoke. - */ - validateDeployDelegateResponse(deployResult) { - if (!deployResult) { - throw new Error('[Error]: Deploy result should not be empty.'); - } - let error = null; - for (const region of Object.keys(deployResult)) { - if (!deployResult[region].endpoint) { - error = '[Error]: Invalid response from deploy delegate. "endpoint" field must exist in the response.'; - break; - } - if (!deployResult[region].endpoint.uri) { - error = '[Error]: Invalid response from deploy delegate. "uri" field must exist in the "endpoint" field in the response.'; - break; - } - if (!deployResult[region].deployState) { - error = '[Error]: Invalid response from deploy delegate. "deployState" field must exist in the response.'; - break; - } - } - if (error) { - throw new Error(error); - } + /** + * Validate if the response from DeployDelegate is following the contract between ask-cli and DeployDelegate. + * @param {Object} deployResult the result from deployDelegate's invoke. + */ + validateDeployDelegateResponse(deployResult) { + if (!deployResult) { + throw new Error("[Error]: Deploy result should not be empty."); + } + let error = null; + for (const region of Object.keys(deployResult)) { + if (!deployResult[region].endpoint) { + error = '[Error]: Invalid response from deploy delegate. "endpoint" field must exist in the response.'; + break; + } + if (!deployResult[region].endpoint.uri) { + error = '[Error]: Invalid response from deploy delegate. "uri" field must exist in the "endpoint" field in the response.'; + break; + } + if (!deployResult[region].deployState) { + error = '[Error]: Invalid response from deploy delegate. "deployState" field must exist in the response.'; + break; + } } + if (error) { + throw new Error(error); + } + } - /** - * Validate if the instance of DeployDelegate has required method. - */ - _validateDeployDelegateMethods() { - if (!this.instance) { - throw new Error('[Error]: Invalid deploy delegate. Failed to load the target module.'); - } - if (!this.instance.bootstrap || typeof this.instance.bootstrap !== 'function') { - throw new Error('[Error]: Invalid deploy delegate. The class of the deploy delegate must contain "bootstrap" method.'); - } - if (!this.instance.invoke || typeof this.instance.invoke !== 'function') { - throw new Error('[Error]: Invalid deploy delegate. The class of the deploy delegate must contain "invoke" method.'); - } + /** + * Validate if the instance of DeployDelegate has required method. + */ + _validateDeployDelegateMethods() { + if (!this.instance) { + throw new Error("[Error]: Invalid deploy delegate. Failed to load the target module."); + } + if (!this.instance.bootstrap || typeof this.instance.bootstrap !== "function") { + throw new Error('[Error]: Invalid deploy delegate. The class of the deploy delegate must contain "bootstrap" method.'); + } + if (!this.instance.invoke || typeof this.instance.invoke !== "function") { + throw new Error('[Error]: Invalid deploy delegate. The class of the deploy delegate must contain "invoke" method.'); } + } } /** @@ -141,25 +141,25 @@ class DeployDelegate { * @param {Function} callback (error, deployDelegateInstance) */ function loadDeployDelegate(type, callback) { - if (typeof type === 'string' && BUILT_IN_DEPLOY_DELEGATES[type]) { - let dd; - const builtinLocation = BUILT_IN_DEPLOY_DELEGATES[type].location; - try { - const modulePath = path.join(__dirname, '..', '..', 'builtins', 'deploy-delegates', builtinLocation); - dd = new DeployDelegate(type, require(modulePath)); // eslint-disable-line global-require - } catch (loadErr) { - return process.nextTick(() => { - callback(`[Error]: Built-in skill infrastructure type "${type}" failed to load.\n${loadErr}`); - }); - } - callback(null, dd); - } else if (type === 'custom') { - // TODO support custom script type deploy delegate - } else { - process.nextTick(() => { - callback(`[Error]: Skill infrastructure type "${type}" is not recognized by ask-cli.`); - }); + if (typeof type === "string" && BUILT_IN_DEPLOY_DELEGATES[type]) { + let dd; + const builtinLocation = BUILT_IN_DEPLOY_DELEGATES[type].location; + try { + const modulePath = path.join(__dirname, "..", "..", "builtins", "deploy-delegates", builtinLocation); + dd = new DeployDelegate(type, require(modulePath)); // eslint-disable-line global-require + } catch (loadErr) { + return process.nextTick(() => { + callback(`[Error]: Built-in skill infrastructure type "${type}" failed to load.\n${loadErr}`); + }); } + callback(null, dd); + } else if (type === "custom") { + // TODO support custom script type deploy delegate + } else { + process.nextTick(() => { + callback(`[Error]: Skill infrastructure type "${type}" is not recognized by ask-cli.`); + }); + } } module.exports = DeployDelegate; diff --git a/lib/controllers/skill-infrastructure-controller/index.js b/lib/controllers/skill-infrastructure-controller/index.js index 900ac1a2..4870eb75 100644 --- a/lib/controllers/skill-infrastructure-controller/index.js +++ b/lib/controllers/skill-infrastructure-controller/index.js @@ -1,325 +1,374 @@ -const R = require('ramda'); -const path = require('path'); +const R = require("ramda"); +const path = require("path"); -const SkillMetadataController = require('@src/controllers/skill-metadata-controller'); -const ResourcesConfig = require('@src/model/resources-config'); -const Manifest = require('@src/model/manifest'); -const MultiTasksView = require('@src/view/multi-tasks-view'); -const Messenger = require('@src/view/messenger'); -const hashUtils = require('@src/utils/hash-utils'); -const stringUtils = require('@src/utils/string-utils'); -const SpinnerView = require('@src/view/spinner-view'); -const profileHelper = require('@src/utils/profile-helper'); - -const DeployDelegate = require('./deploy-delegate'); +const SkillMetadataController = require("../skill-metadata-controller"); +const ResourcesConfig = require("../../model/resources-config"); +const Manifest = require("../../model/manifest"); +const MultiTasksView = require("../../view/multi-tasks-view"); +const Messenger = require("../../view/messenger"); +const hashUtils = require("../../utils/hash-utils"); +const stringUtils = require("../../utils/string-utils"); +const CONSTANTS = require("../../utils/constants"); +const {isAcSkill, syncManifest} = require("../../utils/ac-util"); +const acdl = require("@alexa/acdl"); +const DeployDelegate = require("./deploy-delegate"); const defaultAlexaAwsRegionMap = { - default: 'us-east-1', - NA: 'us-east-1', - EU: 'eu-west-1', - FE: 'us-west-2' + default: "us-east-1", + NA: "us-east-1", + EU: "eu-west-1", + FE: "us-west-2", }; module.exports = class SkillInfrastructureController { - constructor(configuration) { - const { profile, doDebug, ignoreHash } = configuration; - this.profile = profile; - this.doDebug = doDebug; - this.ignoreHash = ignoreHash; + constructor(configuration) { + const {profile, doDebug, ignoreHash} = configuration; + this.profile = profile; + this.doDebug = doDebug; + this.ignoreHash = ignoreHash; + this.skillMetaController = new SkillMetadataController({profile, doDebug}); + } + + /** + * Bootstrap a skill project with deploy delegate's custom logic, to initiate the project to be ready for deployment. + * + * @param {String} workspacePath The path to the new skill's workspace + * @param {Function} callback (error) + */ + bootstrapInfrastructures(workspacePath, callback) { + const infraType = ResourcesConfig.getInstance().getSkillInfraType(this.profile); + if (!stringUtils.isNonBlankString(infraType)) { + return process.nextTick(() => { + callback('[Error]: Please set the "type" field for your skill infrastructures.'); + }); } + // 1.Prepare the loading of deploy delegate + DeployDelegate.load(infraType, (loadErr, deployDelegate) => { + if (loadErr) { + return callback(loadErr); + } + // 2.Call bootstrap method from deploy delegate + const bootstrapOptions = { + profile: this.profile, + userConfig: ResourcesConfig.getInstance().getSkillInfraUserConfig(this.profile), + workspacePath, + }; + deployDelegate.bootstrap(bootstrapOptions, (bootsErr, bootstrapResult) => { + if (bootsErr) { + return callback(bootsErr); + } + const {userConfig} = bootstrapResult; + ResourcesConfig.getInstance().setSkillInfraUserConfig(this.profile, userConfig); + callback(); + }); + }); + } - /** - * Bootstrap a skill project with deploy delegate's custom logic, to initiate the project to be ready for deployment. - * @param {String} workspacePath The path to the new skill's workspace - * @param {Function} callback (error) - */ - bootstrapInfrastructures(workspacePath, callback) { - const infraType = ResourcesConfig.getInstance().getSkillInfraType(this.profile); - if (!stringUtils.isNonBlankString(infraType)) { - return process.nextTick(() => { - callback('[Error]: Please set the "type" field for your skill infrastructures.'); - }); + /** + * Entry method for skill infrastructure deployment based on the deploy delegate type. + * + * @param {Function} callback + */ + deployInfrastructure(callback) { + const infraType = ResourcesConfig.getInstance().getSkillInfraType(this.profile); + // 1.Prepare the loading of deploy delegate + DeployDelegate.load(infraType, (loadErr, deployDelegate) => { + if (loadErr) { + return callback(loadErr); + } + // 2.Trigger regional deployment using deploy delegate + this.deployInfraToAllRegions(deployDelegate, (deployErr, deployResult) => { + if (deployErr) { + return callback(deployErr); } - // 1.Prepare the loading of deploy delegate - DeployDelegate.load(infraType, (loadErr, deployDelegate) => { - if (loadErr) { - return callback(loadErr); - } - // 2.Call bootstrap method from deploy delegate - const bootstrapOptions = { - profile: this.profile, - userConfig: ResourcesConfig.getInstance().getSkillInfraUserConfig(this.profile), - workspacePath - }; - deployDelegate.bootstrap(bootstrapOptions, (bootsErr, bootstrapResult) => { - if (bootsErr) { - return callback(bootsErr); - } - const { userConfig } = bootstrapResult; - ResourcesConfig.getInstance().setSkillInfraUserConfig(this.profile, userConfig); - callback(); - }); + // 3.Post deploy skill manifest update + this.updateSkillManifestWithDeployResult(deployResult, (postUpdateErr) => { + if (postUpdateErr) { + return callback(postUpdateErr); + } + callback(); }); - } + }); + }); + } - /** - * Entry method for skill infrastructure deployment based on the deploy delegate type. - * @param {Function} callback - */ - deployInfrastructure(callback) { - const infraType = ResourcesConfig.getInstance().getSkillInfraType(this.profile); - // 1.Prepare the loading of deploy delegate - DeployDelegate.load(infraType, (loadErr, deployDelegate) => { - if (loadErr) { - return callback(loadErr); - } - // 2.Trigger regional deployment using deploy delegate - this.deployInfraToAllRegions(deployDelegate, (deployErr, deployResult) => { - if (deployErr) { - return callback(deployErr); - } - // 3.Post deploy skill manifest update - this.updateSkillManifestWithDeployResult(deployResult, (postUpdateErr) => { - if (postUpdateErr) { - return callback(postUpdateErr); - } - callback(); - }); - }); - }); + /** + * Deploy skill infrastructure to all the Alexa regions. + * + * @param {Object} dd DeployDelegate instance + * @param {Function} callback (error, invokeResult) + * invokeResult: { $region: { endpoint: { url }, lastDeployHash, deployState } } + */ + deployInfraToAllRegions(dd, callback) { + const skillName = + stringUtils.filterNonAlphanumeric(Manifest.getInstance().getSkillName()) || + stringUtils.filterNonAlphanumeric(path.basename(process.cwd())); + if (!stringUtils.isNonBlankString(skillName)) { + return callback( + "[Error]: Failed to parse the skill name used to decide the CloudFormation stack name. " + + "Please make sure your skill name or skill project folder basename contains alphanumeric characters.", + ); + } + const regionsList = ResourcesConfig.getInstance().getCodeRegions(this.profile); + if (!regionsList || regionsList.length === 0) { + return callback('[Warn]: Skip the infrastructure deployment, as the "code" field has not been set in the resources config file.'); } - /** - * Deploy skill infrastructure to all the Alexa regions. - * @param {Object} dd DeployDelegate instance - * @param {Function} callback (error, invokeResult) - * invokeResult: { $region: { endpoint: { url }, lastDeployHash, deployState } } - */ - deployInfraToAllRegions(dd, callback) { - const skillName = stringUtils.filterNonAlphanumeric(Manifest.getInstance().getSkillName()) - || stringUtils.filterNonAlphanumeric(path.basename(process.cwd())); - if (!stringUtils.isNonBlankString(skillName)) { - return callback('[Error]: Failed to parse the skill name used to decide the CloudFormation stack name. ' - + 'Please make sure your skill name or skill project folder basename contains alphanumeric characters.'); - } - const regionsList = ResourcesConfig.getInstance().getCodeRegions(this.profile); - if (!regionsList || regionsList.length === 0) { - return callback('[Warn]: Skip the infrastructure deployment, as the "code" field has not been set in the resources config file.'); + const userConfig = ResourcesConfig.getInstance().getSkillInfraUserConfig(this.profile); + const deployRegions = this._getAlexaDeployRegions(regionsList, userConfig); + + // 1.instantiate MultiTasksView + const taskConfig = { + concurrent: true, + exitOnError: false, + }; + const multiTasksView = new MultiTasksView(taskConfig); + // 2.register each regional task into MultiTasksView + regionsList.forEach((region) => { + const taskTitle = `Deploy Alexa skill infrastructure for region "${region}"`; + const taskHandle = (reporter, taskCallback) => { + this._deployInfraByRegion(reporter, dd, region, skillName, deployRegions, taskCallback); + }; + multiTasksView.loadTask(taskHandle, taskTitle, region); + }); + // 3.start multi-tasks and validate task response + multiTasksView.start((taskErr, taskResult) => { + const {error, partialResult} = taskErr || {}; + const result = partialResult || taskResult; + // update skipped deployment task with deploy region result + if (result) { + R.keys(result) + .filter((alexaRegion) => result[alexaRegion].isDeploySkipped) + .forEach((alexaRegion) => { + const {deployRegion} = result[alexaRegion]; + result[alexaRegion] = result[deployRegion]; + }); + } + if (error) { + // update partial successful deploy results to resources config + if (result && !R.isEmpty(R.keys(result))) { + this._updateResourcesConfig(regionsList, result); } - const userConfig = ResourcesConfig.getInstance().getSkillInfraUserConfig(this.profile); - const deployRegions = this._getAlexaDeployRegions(regionsList, userConfig); + return callback(error); + } + // 4.validate response and update states based on the results + try { + dd.validateDeployDelegateResponse(result); + } catch (responseInvalidErr) { + return callback(responseInvalidErr); + } + this._updateResourcesConfig(regionsList, result); + callback(null, result); + }); + } - // 1.instantiate MultiTasksView - const taskConfig = { - concurrent: true, - exitOnError: false - }; - const multiTasksView = new MultiTasksView(taskConfig); - // 2.register each regional task into MultiTasksView - regionsList.forEach((region) => { - const taskTitle = `Deploy Alexa skill infrastructure for region "${region}"`; - const taskHandle = (reporter, taskCallback) => { - this._deployInfraByRegion(reporter, dd, region, skillName, deployRegions, taskCallback); - }; - multiTasksView.loadTask(taskHandle, taskTitle, region); - }); - // 3.start multi-tasks and validate task response - multiTasksView.start((taskErr, taskResult) => { - const { error, partialResult } = taskErr || {}; - const result = partialResult || taskResult; - // update skipped deployment task with deploy region result - if (result) { - R.keys(result).filter((alexaRegion) => result[alexaRegion].isDeploySkipped).forEach((alexaRegion) => { - const { deployRegion } = result[alexaRegion]; - result[alexaRegion] = result[deployRegion]; - }); - } - if (error) { - // update partial successful deploy results to resources config - if (result && !R.isEmpty(R.keys(result))) { - this._updateResourcesConfig(regionsList, result); - } - return callback(error); - } - // 4.validate response and update states based on the results - try { - dd.validateDeployDelegateResponse(result); - } catch (responseInvalidErr) { - return callback(responseInvalidErr); - } - this._updateResourcesConfig(regionsList, result); - callback(null, result); - }); + /** + * Update the skill manifest based on the skill infrastructure deployment result. + * + * @param {Object} rawDeployResult deploy result from invoke: { $region: { endpoint: { url }, lastDeployHash, deployState } } + * @param {Function} callback (error) + */ + updateSkillManifestWithDeployResult(rawDeployResult, callback) { + const targetEndpoints = ResourcesConfig.getInstance().getTargetEndpoints(this.profile); + // for backward compatibility, defaulting to api from skill manifest if targetEndpoints is not defined + const domains = targetEndpoints.length ? targetEndpoints : Object.keys(Manifest.getInstance().getApis()); + // 1.update local skill.json file: + // update the "uri" in all target api endpoints for each region + domains.forEach((domain) => { + R.keys(rawDeployResult).forEach((region) => { + Manifest.getInstance().setApisEndpointByDomainRegion(domain, region, rawDeployResult[region].endpoint); + }); + }); + // add skill events if defined in resources config + const events = ResourcesConfig.getInstance().getSkillEvents(this.profile); + if (events) { + R.keys(rawDeployResult).forEach((region) => { + Manifest.getInstance().setEventsEndpointByRegion(region, rawDeployResult[region].endpoint); + }); + if (events.publications) { + const publications = events.publications.map((eventName) => ({eventName})); + Manifest.getInstance().setEventsPublications(publications); + } + if (events.subscriptions) { + const subscriptions = events.subscriptions.map((eventName) => ({eventName})); + Manifest.getInstance().setEventsSubscriptions(subscriptions); + } } - /** - * Update the skill manifest based on the skill infrastructure deployment result. - * @param {Object} rawDeployResult deploy result from invoke: { $region: { endpoint: { url }, lastDeployHash, deployState } } - * @param {Function} callback (error) - */ - updateSkillManifestWithDeployResult(rawDeployResult, callback) { - const targetEndpoints = ResourcesConfig.getInstance().getTargetEndpoints(this.profile); - // for backward compatibility, defaulting to api from skill manifest if targetEndpoints is not defined - const domains = targetEndpoints.length ? targetEndpoints : Object.keys(Manifest.getInstance().getApis()); - // 1.update local skill.json file: - // update the "uri" in all target api endpoints for each region - domains.forEach((domain) => { - R.keys(rawDeployResult).forEach((region) => { - Manifest.getInstance().setApisEndpointByDomainRegion(domain, region, rawDeployResult[region].endpoint); - }); - }); - // add skill events if defined in resources config - const events = ResourcesConfig.getInstance().getSkillEvents(this.profile); - if (events) { - R.keys(rawDeployResult).forEach((region) => { - Manifest.getInstance().setEventsEndpointByRegion(region, rawDeployResult[region].endpoint); - }); - if (events.publications) { - const publications = events.publications.map((eventName) => ({ eventName })); - Manifest.getInstance().setEventsPublications(publications); - } - if (events.subscriptions) { - const subscriptions = events.subscriptions.map((eventName) => ({ eventName })); - Manifest.getInstance().setEventsSubscriptions(subscriptions); - } - } + Manifest.getInstance().write(); - Manifest.getInstance().write(); - // 2.compare with current hash result to decide if skill.json file need to be updated - // (the only possible change in skillMetaSrc during the infra deployment is the skill.json's uri change) - hashUtils.getHash(ResourcesConfig.getInstance().getSkillMetaSrc(this.profile), (hashErr, currentHash) => { - if (hashErr) { - return callback(hashErr); - } - if (currentHash === ResourcesConfig.getInstance().getSkillMetaLastDeployHash(this.profile)) { - return callback(); - } - // 3.re-upload skill package - this._ensureSkillManifestGotUpdated((manifestUpdateErr) => { - if (manifestUpdateErr) { - return callback(manifestUpdateErr); - } - ResourcesConfig.getInstance().setSkillMetaLastDeployHash(this.profile, currentHash); - Messenger.getInstance().info(' The api endpoints of skill.json have been updated from the skill infrastructure deploy results.'); - callback(); - }); - }); - } + let skillMetaSrc = ResourcesConfig.getInstance().getSkillMetaSrc(this.profile); - /** - * Deploy skill infrastructure by calling invoke function from deploy delegate. - * @param {Object} reporter upstream CLI status reporter - * @param {Object} dd injected deploy delegate instance - * @param {String} alexaRegion - * @param {String} skillName - * @param {Object} deployRegions - * @param {Function} callback (error, invokeResult) - * callback.error can be a String or { message, context } Object which passes back the partial deploy result - */ - _deployInfraByRegion(reporter, dd, alexaRegion, skillName, deployRegions, callback) { - const regionConfig = { - profile: this.profile, - doDebug: this.doDebug, - ignoreHash: this.ignoreHash, - alexaRegion, - skillId: ResourcesConfig.getInstance().getSkillId(this.profile), - skillName, - code: { - codeBuild: ResourcesConfig.getInstance().getCodeBuildByRegion(this.profile, alexaRegion).file, - isCodeModified: null - }, - userConfig: ResourcesConfig.getInstance().getSkillInfraUserConfig(this.profile), - deployState: ResourcesConfig.getInstance().getSkillInfraDeployState(this.profile), - deployRegions - }; - // 1.calculate the lastDeployHash for current code folder and compare with the one in record - const lastDeployHash = ResourcesConfig.getInstance().getCodeLastDeployHashByRegion(this.profile, regionConfig.alexaRegion); - hashUtils.getHash(regionConfig.code.codeBuild, (hashErr, currentHash) => { - if (hashErr) { - return callback(hashErr); - } - regionConfig.code.isCodeModified = currentHash !== lastDeployHash; - // 2.trigger the invoke function from deploy delegate - dd.invoke(reporter, regionConfig, (invokeErr, invokeResult) => { - if (invokeErr) { - return callback(invokeErr); - } - const { isAllStepSuccess, isCodeDeployed, isDeploySkipped, resultMessage } = invokeResult; - // track the current hash if isCodeDeployed - if (isCodeDeployed) { - invokeResult.lastDeployHash = currentHash; - } - // skip task if isDeploySkipped - if (isDeploySkipped) { - reporter.skipTask(resultMessage); - } - // pass result message as error message if deploy not success and not skipped - if (!isAllStepSuccess && !isDeploySkipped) { - callback({ message: resultMessage, context: invokeResult }); - } else { - callback(null, invokeResult); - } - }); - }); - } + // If it's a AC skill, update build/skill-package/skill.json as well + const isACSkill = isAcSkill(this.profile); + if (isACSkill) { + const projectConfig = acdl.loadProjectConfigSync(); + const outDirPath = path.join(projectConfig.rootDir, projectConfig.outDir); + const skillPackageSrc = path.join(outDirPath, CONSTANTS.COMPILER.TARGETDIR); + skillMetaSrc = skillPackageSrc; - /** - * Update the the ask resources config and the deploy state. - * @param {Object} regionsList list of configured alexa regions - * @param {Object} rawDeployResult deploy result from invoke: { $region: deploy-delegate's response } - */ - _updateResourcesConfig(regionsList, rawDeployResult) { - const curDeployState = ResourcesConfig.getInstance().getSkillInfraDeployState(this.profile) || {}; - const newDeployState = {}; - regionsList.forEach((alexaRegion) => { - const { deployState, lastDeployHash } = rawDeployResult[alexaRegion] || {}; - newDeployState[alexaRegion] = deployState || curDeployState[alexaRegion]; - if (lastDeployHash) { - ResourcesConfig.getInstance().setCodeLastDeployHashByRegion(this.profile, alexaRegion, lastDeployHash); - } - }); - ResourcesConfig.getInstance().setSkillInfraDeployState(this.profile, newDeployState); - ResourcesConfig.getInstance().write(); + const manifestPath = path.join(skillPackageSrc, CONSTANTS.COMPILER.MANIFEST); + syncManifest(manifestPath); } - /** - * Make sure the skill manifest is updated successfully by deploying the skill package - * @param {Function} callback - */ - _ensureSkillManifestGotUpdated(callback) { - const spinner = new SpinnerView(); - spinner.start('Updating skill package from the skill infrastructure deploy results.'); - let vendorId, skillMetaController; - try { - vendorId = profileHelper.resolveVendorId(this.profile); - skillMetaController = new SkillMetadataController({ profile: this.profile, doDebug: this.doDebug }); - } catch (err) { - spinner.terminate(); - return callback(err); + // 2.compare with current hash result to decide if skill.json file need to be updated + // (the only possible change in skillMetaSrc during the infra deployment is the skill.json's uri change) + + hashUtils.getHash(skillMetaSrc, (hashErr, currentHash) => { + if (hashErr) { + return callback(hashErr); + } + if (currentHash === ResourcesConfig.getInstance().getSkillMetaLastDeployHash(this.profile)) { + return callback(); + } + // 3.re-upload skill package + this._ensureSkillManifestGotUpdated((manifestUpdateErr) => { + if (manifestUpdateErr) { + return callback(manifestUpdateErr); } - skillMetaController.deploySkillPackage(vendorId, this.ignoreHash, (deployErr) => { - spinner.terminate(); - if (deployErr) { - return callback(deployErr); - } - callback(); - }); - } + ResourcesConfig.getInstance().setSkillMetaLastDeployHash(this.profile, currentHash); + Messenger.getInstance().info("\nThe api endpoints of skill.json have been updated from the skill infrastructure deploy results."); + callback(); + }); + }); + } - /** - * Return deploy regions map based on configured alexa code regions - * @param {Array} regionsList list of configured alexa regions - * @param {Object} userConfig - * @return {Object} - */ - _getAlexaDeployRegions(regionsList, userConfig) { - const deployRegions = {}; - regionsList.forEach((alexaRegion) => { - const awsRegion = alexaRegion === 'default' - ? userConfig.awsRegion - : R.path(['regionalOverrides', alexaRegion, 'awsRegion'], userConfig); - deployRegions[alexaRegion] = awsRegion || defaultAlexaAwsRegionMap[alexaRegion]; - }); - return deployRegions; + /** + * Deploy skill infrastructure by calling invoke function from deploy delegate. + * @param {Object} reporter upstream CLI status reporter + * @param {Object} dd injected deploy delegate instance + * @param {String} alexaRegion + * @param {String} skillName + * @param {Object} deployRegions + * @param {Function} callback (error, invokeResult) + * callback.error can be a String or { message, context } Object which passes back the partial deploy result + */ + _deployInfraByRegion(reporter, dd, alexaRegion, skillName, deployRegions, callback) { + const regionConfig = { + profile: this.profile, + doDebug: this.doDebug, + ignoreHash: this.ignoreHash, + alexaRegion, + skillId: ResourcesConfig.getInstance().getSkillId(this.profile), + skillName, + code: { + codeBuild: ResourcesConfig.getInstance().getCodeBuildByRegion(this.profile, alexaRegion).file, + isCodeModified: null, + }, + userConfig: ResourcesConfig.getInstance().getSkillInfraUserConfig(this.profile), + deployState: ResourcesConfig.getInstance().getSkillInfraDeployState(this.profile), + deployRegions, + }; + // 1.calculate the lastDeployHash for current code folder and compare with the one in record + const lastDeployHash = ResourcesConfig.getInstance().getCodeLastDeployHashByRegion(this.profile, regionConfig.alexaRegion); + hashUtils.getHash(regionConfig.code.codeBuild, (hashErr, currentHash) => { + if (hashErr) { + return callback(hashErr); + } + regionConfig.code.isCodeModified = currentHash !== lastDeployHash; + // 2.trigger the invoke function from deploy delegate + dd.invoke(reporter, regionConfig, (invokeErr, invokeResult) => { + if (invokeErr) { + return callback(invokeErr); + } + const {isAllStepSuccess, isCodeDeployed, isDeploySkipped, resultMessage} = invokeResult; + // track the current hash if isCodeDeployed + if (isCodeDeployed) { + invokeResult.lastDeployHash = currentHash; + } + // skip task if isDeploySkipped + if (isDeploySkipped) { + reporter.skipTask(resultMessage); + } + // pass result message as error message if deploy not success and not skipped + if (!isAllStepSuccess && !isDeploySkipped) { + callback({message: resultMessage, context: invokeResult}); + } else { + callback(null, invokeResult); + } + }); + }); + } + + /** + * Update the the ask resources config and the deploy state. + * + * @param {Object} rawDeployResult deploy result from invoke: { $region: deploy-delegate's response } + */ + _updateResourcesConfig(regionsList, rawDeployResult) { + const curDeployState = ResourcesConfig.getInstance().getSkillInfraDeployState(this.profile) || {}; + const newDeployState = {}; + regionsList.forEach((alexaRegion) => { + const {deployState, lastDeployHash} = rawDeployResult[alexaRegion] || {}; + newDeployState[alexaRegion] = deployState || curDeployState[alexaRegion]; + if (lastDeployHash) { + ResourcesConfig.getInstance().setCodeLastDeployHashByRegion(this.profile, alexaRegion, lastDeployHash); + } + }); + ResourcesConfig.getInstance().setSkillInfraDeployState(this.profile, newDeployState); + ResourcesConfig.getInstance().write(); + } + + /** + * Make sure the skill manifest is updated successfully + * @param {Function} callback + */ + _ensureSkillManifestGotUpdated(callback) { + let skillMetaController; + + try { + skillMetaController = new SkillMetadataController({profile: this.profile, doDebug: this.doDebug}); + } catch (err) { + return callback(err); } + + skillMetaController.updateSkillManifest((err) => { + callback(err); + }); + } + + /** + * Poll skill's manifest status until the status is not IN_PROGRESS. + * + * @param {Object} smapiClient + * @param {String} skillId + * @param {Function} callback + */ + _pollSkillStatus(smapiClient, skillId, callback) { + const retryConfig = { + base: 2000, + factor: 1.12, + maxRetry: 50, + }; + const retryCall = (loopCallback) => { + smapiClient.skill.getSkillStatus(skillId, [CONSTANTS.SKILL.RESOURCES.MANIFEST], (statusErr, statusResponse) => { + if (statusErr) { + return loopCallback(statusErr); + } + if (statusResponse.statusCode >= 300) { + return loopCallback(jsonView.toString(statusResponse.body)); + } + loopCallback(null, statusResponse); + }); + }; + const shouldRetryCondition = (retryResponse) => + R.view(R.lensPath(["body", "manifest", "lastUpdateRequest", "status"]), retryResponse) === CONSTANTS.SKILL.SKILL_STATUS.IN_PROGRESS; + retryUtils.retry(retryConfig, retryCall, shouldRetryCondition, (err, res) => callback(err, err ? null : res)); + } + + /** + * Return deploy regions map based on configured alexa code regions + * @param {Array} regionsList list of configured alexa regions + * @param {Object} userConfig + * @return {Object} + */ + _getAlexaDeployRegions(regionsList, userConfig) { + const deployRegions = {}; + regionsList.forEach((alexaRegion) => { + const awsRegion = + alexaRegion === "default" ? userConfig.awsRegion : R.path(["regionalOverrides", alexaRegion, "awsRegion"], userConfig); + deployRegions[alexaRegion] = awsRegion || defaultAlexaAwsRegionMap[alexaRegion]; + }); + return deployRegions; + } }; diff --git a/lib/controllers/skill-metadata-controller/index.js b/lib/controllers/skill-metadata-controller/index.js index 56a63e32..065c0a61 100644 --- a/lib/controllers/skill-metadata-controller/index.js +++ b/lib/controllers/skill-metadata-controller/index.js @@ -1,358 +1,611 @@ -const R = require('ramda'); -const fs = require('fs-extra'); -const path = require('path'); - -const retryUtils = require('@src/utils/retry-utility'); -const ResourcesConfig = require('@src/model/resources-config'); -const SmapiClient = require('@src/clients/smapi-client'); -const httpClient = require('@src/clients/http-client'); -const Manifest = require('@src/model/manifest'); -const Messenger = require('@src/view/messenger'); -const jsonView = require('@src/view/json-view'); -const stringUtils = require('@src/utils/string-utils'); -const zipUtils = require('@src/utils/zip-utils'); -const hashUtils = require('@src/utils/hash-utils'); -const CONSTANTS = require('@src/utils/constants'); -const CLiError = require('@src/exceptions/cli-error'); -const CLiWarn = require('@src/exceptions/cli-warn'); +const R = require("ramda"); +const fs = require("fs-extra"); +const path = require("path"); + +const retryUtils = require("../../utils/retry-utility"); +const ResourcesConfig = require("../../model/resources-config"); +const SmapiClient = require("../../clients/smapi-client").default; +const httpClient = require("../../clients/http-client"); +const Manifest = require("../../model/manifest"); +const {BuildStatusLocalCache} = require("../../model/build-status-local-cache"); +const {ImportStatus} = require("../../model/import-status"); +const {SkillStatus, AC_QUICK_BUILD, AC_FULL_BUILD} = require("../../model/skill-status"); +const Messenger = require("../../view/messenger"); +const jsonView = require("../../view/json-view"); +const stringUtils = require("../../utils/string-utils"); +const zipUtils = require("../../utils/zip-utils"); +const hashUtils = require("../../utils/hash-utils"); +const CONSTANTS = require("../../utils/constants"); +const CLiError = require("../../exceptions/cli-error"); +const CLiWarn = require("../../exceptions/cli-warn"); +const acUtil = require("../../utils/ac-util"); +const acdl = require("@alexa/acdl"); +const { + IMPORT_STATUS_AC_BUILD_SUCCESS_EVENT, + IMPORT_STATUS_AC_BUILD_FAILED_EVENT, + IMPORT_STATUS_BUILDING_AC_FULL_EVENT, + IMPORT_STATUS_BUILDING_AC_LIGHT_EVENT, + IMPORT_STATUS_IM_BUILD_SUCCESS_EVENT, + IMPORT_STATUS_IM_BUILD_FAILED_EVENT, +} = require("../../view/import-status/import-status-view-events"); +const {ImportStatusView} = require("../../view/import-status/import-status-view"); module.exports = class SkillMetadataController { - /** - * Constructor for SkillMetadataController - * @param {Object} configuration { profile, doDebug } - */ - constructor(configuration) { - const { profile, doDebug } = configuration; - this.smapiClient = new SmapiClient({ profile, doDebug }); - this.profile = profile; - this.doDebug = doDebug; + /** + * Constructor for SkillMetadataController + * @param {Object} configuration { profile, doDebug } + */ + constructor(configuration) { + const {profile, doDebug} = configuration; + this.smapiClient = new SmapiClient({profile, doDebug}); + this.profile = profile; + this.doDebug = doDebug; + this.importStatusPollView = undefined; + this.isACSkill = undefined; + } + + /** + * Entry method for all the skill package deployment logic + * @param {String} vendorId + * @param {Function} callback (error) + */ + deploySkillPackage(vendorId, ignoreHash, callback) { + // 1.get valid skillMetadata src path + let skillPackageSrc = ResourcesConfig.getInstance().getSkillMetaSrc(this.profile); + if (!stringUtils.isNonBlankString(skillPackageSrc)) { + return callback("Skill package src is not found in ask-resources.json."); + } + if (!fs.existsSync(skillPackageSrc)) { + return callback(`File ${skillPackageSrc} does not exist.`); } - /** - * Entry method for all the skill package deployment logic - * @param {String} vendorId - * @param {Function} callback (error) - */ - deploySkillPackage(vendorId, ignoreHash, callback) { - // 1.get valid skillMetada src path - const skillPackageSrc = ResourcesConfig.getInstance().getSkillMetaSrc(this.profile); - if (!stringUtils.isNonBlankString(skillPackageSrc)) { - return callback('Skill package src is not found in ask-resources.json.'); - } - if (!fs.existsSync(skillPackageSrc)) { - return callback(`File ${skillPackageSrc} does not exist.`); - } + // if it's AC skill, use the build/skill-package + if (this.getIsAcSkill() === true) { + const projectConfig = acdl.loadProjectConfigSync(); + const outDirPath = path.join(projectConfig.rootDir, projectConfig.outDir); + skillPackageSrc = path.join(outDirPath, CONSTANTS.COMPILER.TARGETDIR); + } - // 2.compare hashcode between current and previous status to decide if necessary to upload - hashUtils.getHash(skillPackageSrc, (hashErr, currentHash) => { - if (hashErr) { - return callback(hashErr); - } - const lastDeployHash = ResourcesConfig.getInstance().getSkillMetaLastDeployHash(this.profile); - if (!ignoreHash && stringUtils.isNonBlankString(lastDeployHash) && lastDeployHash === currentHash) { - return callback('The hash of current skill package folder does not change compared to the last deploy hash result, ' - + 'CLI will skip the deploy of skill package.'); - } + // 2.compare hashcode between current and previous status to decide if necessary to upload + hashUtils.getHash(skillPackageSrc, (hashErr, currentHash) => { + if (hashErr) { + return callback(hashErr); + } + const lastDeployHash = ResourcesConfig.getInstance().getSkillMetaLastDeployHash(this.profile); + if (!ignoreHash && stringUtils.isNonBlankString(lastDeployHash) && lastDeployHash === currentHash) { + return callback( + "The hash of current skill package folder does not change compared to the last deploy hash result, " + + "CLI will skip the deploy of skill package.", + ); + } + + // 3.call smapiClient to create/upload skillPackage + const skillId = ResourcesConfig.getInstance().getSkillId(this.profile); - // 3.call smapiClient to create/upload skillPackage - const skillId = ResourcesConfig.getInstance().getSkillId(this.profile); - this.putSkillPackage(skillId, skillId ? null : vendorId, (putErr, currentSkillId) => { - if (putErr) { - return callback(putErr); - } - ResourcesConfig.getInstance().setSkillId(this.profile, currentSkillId); - ResourcesConfig.getInstance().setSkillMetaLastDeployHash(this.profile, currentHash); - callback(); - }); + // print skill Id if this is the first time we see it + this.getImportStatusPollView(); + if (skillId) { + // need to encapsulate this with nextTick since we want to make sure the observable listeners are setup + process.nextTick(() => { + this.getImportStatusPollView().displaySkillId(skillId, true); }); - } + } - /** - * Validates domain info - */ - validateDomain() { - const domainInfo = Manifest.getInstance().getApis(); - if (!domainInfo || R.isEmpty(domainInfo)) { - throw new CLiError('Skill information is not valid. Please make sure "apis" field in the skill.json is not empty.'); - } + this.putSkillPackage(skillPackageSrc, skillId, skillId ? null : vendorId, (putErr, currentSkillId) => { + this.getImportStatusPollView().stop(); + this.getImportStatusPollView() + .waitForCompletion() + .then(() => { + if (putErr) { + return callback(putErr); + } + ResourcesConfig.getInstance().setSkillId(this.profile, currentSkillId); + ResourcesConfig.getInstance().setSkillMetaLastDeployHash(this.profile, currentHash); + callback(); + }); + }); + }); + } - const domainList = R.keys(domainInfo); - if (domainList.length !== 1) { - throw new CLiWarn('Skill with multiple api domains cannot be enabled. Skip the enable process.'); - } - if (CONSTANTS.SKILL.DOMAIN.CAN_ENABLE_DOMAIN_LIST.indexOf(domainList[0]) === -1) { - throw new CLiWarn(`Skill api domain "${domainList[0]}" cannot be enabled. Skip the enable process.`); - } + /** + * Validates domain info + */ + validateDomain() { + const domainInfo = Manifest.getInstance().getApis(); + if (!domainInfo || R.isEmpty(domainInfo)) { + throw new CLiError('Skill information is not valid. Please make sure "apis" field in the skill.json is not empty.'); + } + + const domainList = R.keys(domainInfo); + if (domainList.length !== 1) { + throw new CLiWarn("Skill with multiple api domains cannot be enabled. Skipping the enable process.\n"); + } + if (CONSTANTS.SKILL.DOMAIN.CAN_ENABLE_DOMAIN_LIST.indexOf(domainList[0]) === -1) { + throw new CLiWarn(`Skill api domain "${domainList[0]}" cannot be enabled. Skipping the enable process.\n`); } + } - /** - * Function used to enable skill. It calls smapi getSkillEnablement function first to check if skill is already enabled, - * if not, it will enable the skill by calling smapi enableSkill function. - * @param {Function} callback (err, null) - */ - enableSkill(callback) { - const skillId = ResourcesConfig.getInstance().getSkillId(this.profile); - if (!stringUtils.isNonBlankString(skillId)) { - return callback(`[Fatal]: Failed to find the skillId for profile [${this.profile}], + /** + * Function used to enable skill. It calls smapi getSkillEnablement function first to check if skill is already enabled, + * if not, it will enable the skill by calling smapi enableSkill function. + * @param {Function} callback (err, null) + */ + enableSkill(callback) { + const skillId = ResourcesConfig.getInstance().getSkillId(this.profile); + if (!stringUtils.isNonBlankString(skillId)) { + return callback(`[Fatal]: Failed to find the skillId for profile [${this.profile}], please make sure the skill metadata deployment has succeeded with result of a valid skillId.`); + } + + this.smapiClient.skill.getSkillEnablement(skillId, CONSTANTS.SKILL.STAGE.DEVELOPMENT, (err, response) => { + if (err) { + return callback(err); + } + if (response.statusCode === CONSTANTS.HTTP_REQUEST.STATUS_CODE.NOT_FOUND) { + this.smapiClient.skill.enableSkill(skillId, CONSTANTS.SKILL.STAGE.DEVELOPMENT, (enableErr, enableResponse) => { + if (enableErr) { + return callback(enableErr); + } + if (enableResponse.statusCode >= 300) { + return callback(jsonView.toString(enableResponse.body)); + } + Messenger.getInstance().info("Skill is enabled successfully.\n"); + + callback(); + }); + } else if (response.statusCode >= 300) { + callback(jsonView.toString(response.body)); + } else { + Messenger.getInstance().info("Skill is already enabled, skipping the enable process.\n"); + callback(); + } + }); + } + + /** + * Put skill package based on the input of skillId and vendorId: + * when vendorId is set but skillId is not, create skill package; + * when skillId is set but vendorId is not, update skill package. + * + * @param {String} skillId + * @param {String} vendorId + * @param {Function} callback (error, skillId) + */ + putSkillPackage(skillPackageSrc, skillId, vendorId, callback) { + // 1.zip and upload skill package + this.uploadSkillPackage(skillPackageSrc, (uploadErr, uploadResult) => { + if (uploadErr) { + return callback(uploadErr); + } + // 2.import skill package with upload URL + this._importPackage(skillId, vendorId, uploadResult.uploadUrl, (importErr, importResponse) => { + if (importErr) { + return callback(importErr); } + const importId = path.basename(importResponse.headers.location); + if (importId) { + this.getImportStatusPollView().displayImportId(importId); + } + // 3.poll for the skill package import status + this._pollImportStatus(importId, (pollErr, pollResponse) => { + if (pollErr) { + return callback(pollErr); + } - this.smapiClient.skill.getSkillEnablement(skillId, CONSTANTS.SKILL.STAGE.DEVELOPMENT, (err, response) => { - if (err) { - return callback(err); + if (pollResponse.body.status !== CONSTANTS.SKILL.PACKAGE_STATUS.SUCCEEDED) { + if (this.getIsAcSkill() === false) { + this.getImportStatusPollView().publishEvent("Interaction Model", IMPORT_STATUS_IM_BUILD_FAILED_EVENT); } - if (response.statusCode === CONSTANTS.HTTP_REQUEST.STATUS_CODE.NOT_FOUND) { - this.smapiClient.skill.enableSkill(skillId, CONSTANTS.SKILL.STAGE.DEVELOPMENT, (enableErr, enableResponse) => { - if (enableErr) { - return callback(enableErr); - } - if (enableResponse.statusCode >= 300) { - return callback(jsonView.toString(enableResponse.body)); - } - Messenger.getInstance().info('Skill is enabled successfully.'); - - callback(); - }); - } else if (response.statusCode >= 300) { - callback(jsonView.toString(response.body)); - } else { - Messenger.getInstance().info('Skill is already enabled, skip the enable process.'); - callback(); + callback(jsonView.toString(pollResponse.body)); + } else { + if (this.getIsAcSkill() === false) { + this.getImportStatusPollView().publishEvent("Interaction Model", IMPORT_STATUS_IM_BUILD_SUCCESS_EVENT); } + callback(null, pollResponse.body.skill.skillId); + } }); - } + }); + }); + } - /** - * Put skill package based on the input of skillId and vendorId: - * when vendorId is set but skillId is not, create skill package; - * when skillId is set but vendorId is not, update skill package. - * - * @param {String} skillId - * @param {String} vendorId - * @param {Function} callback (error, skillId) - */ - putSkillPackage(skillId, vendorId, callback) { - // 1.zip and upload skill package - const skillPackageSrc = ResourcesConfig.getInstance().getSkillMetaSrc(this.profile); - this.uploadSkillPackage(skillPackageSrc, (uploadErr, uploadResult) => { - if (uploadErr) { - return callback(uploadErr); - } - // 2.import skill package with upload URL - this._importPackage(skillId, vendorId, uploadResult.uploadUrl, (importErr, importResponse) => { - if (importErr) { - return callback(importErr); - } - const importId = path.basename(importResponse.headers.location); - // 3.poll for the skill package import status - this._pollImportStatus(importId, (pollErr, pollResponse) => { - if (pollErr) { - return callback(pollErr); - } - if (pollResponse.body.status !== CONSTANTS.SKILL.PACKAGE_STATUS.SUCCEEDED) { - callback(jsonView.toString(pollResponse.body)); - } else { - callback(null, pollResponse.body.skill.skillId); - } - }); - }); - }); - } + /** + * Download the skill package by exporting the skill package and then download it into the skill project + * @param {String} rootFolder Folder path for the skill project root + * @param {String} skillId + * @param {String stage + * @param {Function} callback + */ + getSkillPackage(rootFolder, skillId, stage, callback) { + // 1.request to export skill package + this._exportPackage(skillId, stage, (exportErr, exportResponse) => { + if (exportErr) { + return callback(exportErr); + } + const exportId = path.basename(R.view(R.lensPath(["headers", "location"]), exportResponse)); - /** - * Download the skill package by exporting the skill package and then download it into the skill project - * @param {String} rootFolder Folder path for the skill project root - * @param {String} skillId - * @param {String stage - * @param {Function} callback - */ - getSkillPackage(rootFolder, skillId, stage, callback) { - // 1.request to export skill package - this._exportPackage(skillId, stage, (exportErr, exportResponse) => { - if (exportErr) { - return callback(exportErr); - } - const exportId = path.basename(R.view(R.lensPath(['headers', 'location']), exportResponse)); - - // 2.poll for the skill package export status - this._pollExportStatus(exportId, (pollErr, pollResponse) => { - if (pollErr) { - return callback(pollErr); - } - // TODO: check the error when statusCode is not 200 or check the body strucutre when status is not SUCCEEDED or check non skill case - - // 3.download skill package into local file system - const skillPackageLocation = R.view(R.lensPath(['body', 'skill', 'location']), pollResponse); - const targetPath = path.join(rootFolder, 'skill-package'); - zipUtils.unzipRemoteZipFile(skillPackageLocation, targetPath, false, (unzipErr) => { - callback(unzipErr); - }); - }); - }); - } + // 2.poll for the skill package export status + this._pollExportStatus(exportId, (pollErr, pollResponse) => { + if (pollErr) { + return callback(pollErr); + } + // TODO: check the error when statusCode is not 200 or check the body structure when status is not SUCCEEDED or check non skill case - /** - * Upload skill package by zipping, creating upload URL, and then upload - * @param {String} skillPackageSrc - * @param {Function} callback (err, { uploadUrl, expiresAt }) - */ - uploadSkillPackage(skillPackageSrc, callback) { - // 1.create upload URL for CLI to upload - this._createUploadUrl((createUploadErr, createUploadResult) => { - if (createUploadErr) { - return callback(createUploadErr); - } - // 2.zip skill package - const outputDir = path.join(process.cwd(), '.ask'); - zipUtils.createTempZip(skillPackageSrc, outputDir, (zipErr, zipFilePath) => { - if (zipErr) { - return callback(zipErr); - } - // 3.upload zip file - const uploadPayload = fs.readFileSync(zipFilePath); - const operation = 'upload-skill-package'; - httpClient.putByUrl(createUploadResult.uploadUrl, uploadPayload, operation, this.doDebug, (uploadErr, uploadResponse) => { - fs.removeSync(zipFilePath); - if (uploadErr) { - return callback(uploadErr); - } - if (uploadResponse.statusCode >= 300) { - return callback('[Error]: Upload of skill package failed. Please try again with --debug to see more details.'); - } - callback(null, createUploadResult); - }); - }); + // 3.download skill package into local file system + const skillPackageLocation = R.view(R.lensPath(["body", "skill", "location"]), pollResponse); + const targetPath = path.join(rootFolder, "skill-package"); + zipUtils.unzipRemoteZipFile(skillPackageLocation, targetPath, false, (unzipErr) => { + callback(unzipErr); }); - } + }); + }); + } - /** - * Read from the {skillPackage}/interactionModel/custom directory, check what locales the current project - * is currently deploying to. - * When we have the Model for entire skill-package, this method is better sitting there. - * - * @returns { [languageName]: iModelPath } where languageName is in the format of xx-YY - */ - getInteractionModelLocales() { - const skillPackagePath = path.join(process.cwd(), ResourcesConfig.getInstance().getSkillMetaSrc(this.profile)); - const iModelFolderPath = path.join(skillPackagePath, CONSTANTS.FILE_PATH.SKILL_PACKAGE.INTERACTION_MODEL, 'custom'); - const supportedLocaleFiles = fs.readdirSync(iModelFolderPath).filter((file) => { - const fileExt = path.extname(file); - const fileNameNoExt = path.basename(file, fileExt); - return fileExt === '.json' && R.includes(fileNameNoExt, R.keys(CONSTANTS.ALEXA.LANGUAGES)); - }); - const result = {}; - supportedLocaleFiles.forEach((file) => { - const fileNameNoExt = path.basename(file, path.extname(file)); - result[fileNameNoExt] = path.join(iModelFolderPath, file); + /** + * Upload skill package by zipping, creating upload URL, and then upload + * @param {String} skillPackageSrc + * @param {Function} callback (err, { uploadUrl, expiresAt }) + */ + uploadSkillPackage(skillPackageSrc, callback) { + // 1.create upload URL for CLI to upload + this._createUploadUrl((createUploadErr, createUploadResult) => { + if (createUploadErr) { + return callback(createUploadErr); + } + // 2.zip skill package + const outputDir = path.join(process.cwd(), ".ask"); + zipUtils.createTempZip(skillPackageSrc, (zipErr, zipFilePath) => { + if (zipErr) { + return callback(zipErr); + } + // 3.upload zip file + const uploadPayload = fs.readFileSync(zipFilePath); + const operation = "upload-skill-package"; + httpClient.putByUrl(createUploadResult.uploadUrl, uploadPayload, operation, this.doDebug, (uploadErr, uploadResponse) => { + fs.removeSync(zipFilePath); + if (uploadErr) { + return callback(uploadErr); + } + if (uploadResponse.statusCode >= 300) { + return callback("[Error]: Upload of skill package failed. Please try again with --debug to see more details."); + } + callback(null, createUploadResult); }); - return result; - } + }); + }); + } - /** - * Wrapper for smapi createUpload function - * @param {Function} callback (err, { uploadUrl, expiresAt }) - */ - _createUploadUrl(callback) { - this.smapiClient.skillPackage.createUpload((createErr, createResponse) => { - if (createErr) { - return callback(createErr); - } - if (createResponse.statusCode >= 300) { - return callback(jsonView.toString(createResponse.body)); - } - callback(null, { - uploadUrl: createResponse.body.uploadUrl, - expiresAt: createResponse.body.expiresAt - }); - }); - } + /** + * Updates the skill manifest using the skill-id from ask-states, and polls + * the skill manifest status until it's finished updating. + * + * @param {error} callback + */ + updateSkillManifest(callback) { + const smapiClient = new SmapiClient({profile: this.profile, doDebug: this.doDebug}); + const skillId = ResourcesConfig.getInstance().getSkillId(this.profile); + const content = Manifest.getInstance().content; + const stage = CONSTANTS.SKILL.STAGE.DEVELOPMENT; - /** - * Wrapper for smapi importPackage function. The response contains importId in its headers' location url. - * @param {String} skillId - * @param {String} vendorId - * @param {String} location - * @param {Function} callback (err, importResponse) - */ - _importPackage(skillId, vendorId, location, callback) { - this.smapiClient.skillPackage.importPackage(skillId, vendorId, location, (importErr, importResponse) => { - if (importErr) { - return callback(importErr); - } - if (importResponse.statusCode >= 300) { - return callback(jsonView.toString(importResponse.body)); + smapiClient.skill.manifest.updateManifest(skillId, stage, content, null, (updateErr, updateResponse) => { + if (updateErr) { + return callback(updateErr); + } + if (updateResponse.statusCode >= 300) { + return callback(jsonView.toString(updateResponse.body)); + } + + // poll manifest status until finish + this._pollSkillManifestStatus(smapiClient, skillId, (pollErr, pollResponse) => { + if (pollErr) { + return callback(pollErr); + } + const manifestStatus = R.view(R.lensPath(["body", "manifest", "lastUpdateRequest", "status"]), pollResponse); + if (!manifestStatus) { + return callback(`[Error]: Failed to extract the manifest result from SMAPI's response.\n${pollResponse}`); + } + if (manifestStatus !== CONSTANTS.SKILL.SKILL_STATUS.SUCCEEDED) { + return callback(`[Error]: Updating skill manifest but received non-success message from SMAPI: ${manifestStatus}`); + } + callback(); + }); + }); + } + + /** + * Poll skill's manifest status until the status is not IN_PROGRESS. + * + * @param {Object} smapiClient + * @param {String} skillId + * @param {Function} callback + */ + _pollSkillManifestStatus(smapiClient, skillId, callback) { + const retryConfig = { + base: 2000, + factor: 1.12, + maxRetry: 50, + }; + + const retryCall = (loopCallback) => { + smapiClient.skill.getSkillStatus(skillId, [CONSTANTS.SKILL.RESOURCES.MANIFEST], (statusErr, statusResponse) => { + if (statusErr) { + return loopCallback(statusErr); + } + if (statusResponse.statusCode >= 300) { + return loopCallback(jsonView.toString(statusResponse.body)); + } + loopCallback(null, statusResponse); + }); + }; + + const shouldRetryCondition = (retryResponse) => + R.view(R.lensPath(["body", "manifest", "lastUpdateRequest", "status"]), retryResponse) === CONSTANTS.SKILL.SKILL_STATUS.IN_PROGRESS; + + retryUtils.retry(retryConfig, retryCall, shouldRetryCondition, (err, res) => callback(err, err ? null : res)); + } + + /** + * Read from the {skillPackage}/interactionModel/custom directory, check what locales the current project + * is currently deploying to. + * When we have the Model for entire skill-package, this method is better sitting there. + * + * @returns { [languageName]: iModelPath } where languageName is in the format of xx-YY + */ + getInteractionModelLocales() { + const skillPackagePath = path.join(process.cwd(), ResourcesConfig.getInstance().getSkillMetaSrc(this.profile)); + const iModelFolderPath = path.join(skillPackagePath, CONSTANTS.FILE_PATH.SKILL_PACKAGE.INTERACTION_MODEL, "custom"); + const supportedLocaleFiles = fs.readdirSync(iModelFolderPath).filter((file) => { + const fileExt = path.extname(file); + const fileNameNoExt = path.basename(file, fileExt); + return fileExt === ".json" && R.includes(fileNameNoExt, R.keys(CONSTANTS.ALEXA.LANGUAGES)); + }); + const result = {}; + supportedLocaleFiles.forEach((file) => { + const fileNameNoExt = path.basename(file, path.extname(file)); + result[fileNameNoExt] = path.join(iModelFolderPath, file); + }); + return result; + } + + /** + * Wrapper for smapi createUpload function + * @param {Function} callback (err, { uploadUrl, expiresAt }) + */ + _createUploadUrl(callback) { + this.smapiClient.skillPackage.createUpload((createErr, createResponse) => { + if (createErr) { + return callback(createErr); + } + if (createResponse.statusCode >= 300) { + return callback(jsonView.toString(createResponse.body)); + } + callback(null, { + uploadUrl: createResponse.body.uploadUrl, + expiresAt: createResponse.body.expiresAt, + }); + }); + } + + /** + * Wrapper for smapi importPackage function. The response contains importId in its headers' location url. + * @param {String} skillId + * @param {String} vendorId + * @param {String} location + * @param {Function} callback (err, importResponse) + */ + _importPackage(skillId, vendorId, location, callback) { + this.smapiClient.skillPackage.importPackage(skillId, vendorId, location, (importErr, importResponse) => { + if (importErr) { + return callback(importErr); + } + if (importResponse.statusCode >= 300) { + return callback(jsonView.toString(importResponse.body)); + } + callback(null, importResponse); + }); + } + + /** + * Wrapper for smapi exportPackage function + * @param {String} skillId + * @param {String} stage + * @param {Function} callback + */ + _exportPackage(skillId, stage, callback) { + this.smapiClient.skillPackage.exportPackage(skillId, stage, (exportErr, exportResponse) => { + if (exportErr) { + return callback(exportErr); + } + if (exportResponse.statusCode >= 300) { + return callback(jsonView.toString(exportResponse.body)); + } + callback(null, exportResponse); + }); + } + + /** + * Wrapper for polling smapi skill package import status. + * @param {String} importId + * @param {Function} callback (err, lastImportStatus) + */ + _pollImportStatus(importId, callback) { + const retryConfig = + this.getIsAcSkill() === true + ? { + base: CONSTANTS.CONFIGURATION.RETRY.GET_PACKAGE_IMPORT_STATUS_FOR_AC.MIN_TIME_OUT, + factor: CONSTANTS.CONFIGURATION.RETRY.GET_PACKAGE_IMPORT_STATUS_FOR_AC.FACTOR, + maxRetry: CONSTANTS.CONFIGURATION.RETRY.GET_PACKAGE_IMPORT_STATUS_FOR_AC.MAX_RETRY, + } + : { + base: CONSTANTS.CONFIGURATION.RETRY.GET_PACKAGE_IMPORT_STATUS.MIN_TIME_OUT, + factor: CONSTANTS.CONFIGURATION.RETRY.GET_PACKAGE_IMPORT_STATUS.FACTOR, + maxRetry: CONSTANTS.CONFIGURATION.RETRY.GET_PACKAGE_IMPORT_STATUS.MAX_RETRY, + }; + const buildStatusLocalCache = new BuildStatusLocalCache(); + let shouldPrintWarning = true; + + const retryCall = (loopCallback) => { + this.smapiClient.skillPackage.getImportStatus(importId, (pollErr, pollResponse) => { + if (pollErr) { + return loopCallback(pollErr); + } + + // print skill Id if needed + const skillId = R.view(R.lensPath(["body", "skill", "skillId"]), pollResponse); + if (skillId) { + this.getImportStatusPollView().displaySkillId(skillId, false); + } + + if (pollResponse.statusCode >= 300) { + return loopCallback(jsonView.toString(pollResponse.body)); + } + const importStatusResponse = new ImportStatus(pollResponse); + + if (shouldPrintWarning && importStatusResponse.warnings.length > 0) { + importStatusResponse.warnings.forEach((warning) => { + Messenger.getInstance().warn(warning); + }); + shouldPrintWarning = false; + } + + const resources = importStatusResponse.resources ? importStatusResponse.resources : []; + resources + .filter((resource) => resource.locale !== "Manifest") + .forEach((resource) => { + const buildStatusLocalCacheEntry = buildStatusLocalCache.get(resource.locale) || {}; + if (Object.keys(buildStatusLocalCacheEntry).length == 0) { + if (resource.status && this.getIsAcSkill() === true) { + // If this is the first time seeing a import build status for AC Skills + // print a message indicating the build is now In Progress for this locale + this.getImportStatusPollView().publishEvent(resource.locale, IMPORT_STATUS_BUILDING_AC_LIGHT_EVENT); + } } - callback(null, importResponse); - }); - } + // update the local cache Import Build Status + buildStatusLocalCache.set(resource.locale, resource.status); + }); + + if (this.getIsAcSkill() === true && stringUtils.isNonBlankString(importStatusResponse.skillId)) { + this.smapiClient.skill.getSkillStatus( + importStatusResponse.skillId, + [CONSTANTS.SKILL.RESOURCES.INTERACTION_MODEL], + (skillStatusErr, skillStatusResponse) => { + if (skillStatusErr) { + return loopCallback(skillStatusErr); + } + this.notifyUserOnACBuildsCompletion(skillStatusResponse, buildStatusLocalCache); + loopCallback(null, pollResponse); + }, + ); + } else { + loopCallback(null, pollResponse); + } + }); + }; + const shouldRetryCondition = (retryResponse) => retryResponse.body.status === CONSTANTS.SKILL.PACKAGE_STATUS.IN_PROGRESS; + retryUtils.retry(retryConfig, retryCall, shouldRetryCondition, (err, res) => callback(err, err ? null : res)); + } - /** - * Wrapper for smapi exportPackage function - * @param {String} skillId - * @param {String} stage - * @param {Function} callback - */ - _exportPackage(skillId, stage, callback) { - this.smapiClient.skillPackage.exportPackage(skillId, stage, (exportErr, exportResponse) => { - if (exportErr) { - return callback(exportErr); + /** + * Synchronous helper function to extract the Alexa Conversation build status from skill status response + * and send a notification on the CLI as the Alexa Conversation builds complete. + * @param {Object} skillStatusResponse SMAPI response from getSkillStatus call + * @param {BuildStatusLocalCache} buildStatusLocalCache current build status context local cache + */ + notifyUserOnACBuildsCompletion(skillStatusResponse, buildStatusLocalCache) { + const skillStatus = new SkillStatus(skillStatusResponse); + const lastUpdateRequests = skillStatus.interactionModel.lastUpdateRequests ? skillStatus.interactionModel.lastUpdateRequests : []; + + lastUpdateRequests.forEach((lastUpdateRequest) => { + const lastUpdatedLocale = lastUpdateRequest.locale; + const buildStatusLocalCacheEntry = buildStatusLocalCache.get(lastUpdatedLocale); + + Object.keys(lastUpdateRequest.buildDetailSteps).forEach((buildTypeName) => { + const smapiBuildDetailStep = lastUpdateRequest.getBuildDetailStep(buildTypeName); + + // only process the skill status if the import status is showing the build has started see https://issues.labcollab.net/browse/ASKIT-36460 + if (buildStatusLocalCacheEntry?.hasBuildStarted() && smapiBuildDetailStep?.isACBuildType) { + const buildType = smapiBuildDetailStep.buildType; + const buildStatus = smapiBuildDetailStep.buildStatus; + const localBuildDetailStep = buildStatusLocalCacheEntry.getBuildDetailStep(buildType) || {}; + + if (localBuildDetailStep.buildStatus !== buildStatus) { + // build status has changed report quick build as In Progress + if (buildType === AC_QUICK_BUILD && buildStatus === CONSTANTS.SKILL.SKILL_STATUS.IN_PROGRESS) { + this.getImportStatusPollView().publishEvent(lastUpdatedLocale, IMPORT_STATUS_BUILDING_AC_LIGHT_EVENT); } - if (exportResponse.statusCode >= 300) { - return callback(jsonView.toString(exportResponse.body)); + // build status has changed report on completed states + if (buildStatus === CONSTANTS.SKILL.SKILL_STATUS.SUCCEEDED) { + // send the build status successfull event + if (buildType === AC_QUICK_BUILD) { + this.getImportStatusPollView().publishEvent(lastUpdatedLocale, IMPORT_STATUS_BUILDING_AC_FULL_EVENT); + } else if (buildType === AC_FULL_BUILD) { + this.getImportStatusPollView().publishEvent(lastUpdatedLocale, IMPORT_STATUS_AC_BUILD_SUCCESS_EVENT); + } + } else if (buildStatus === CONSTANTS.SKILL.SKILL_STATUS.FAILED) { + // send the build status failed event + this.getImportStatusPollView().publishEvent( + lastUpdatedLocale, + IMPORT_STATUS_AC_BUILD_FAILED_EVENT, + `${this.getBuildNameFromType(buildType)} failed for locale: ${lastUpdatedLocale}.`, + ); } - callback(null, exportResponse); - }); - } + } + // Update the local cache entry + buildStatusLocalCacheEntry.setBuildDetailStep(smapiBuildDetailStep); + } + }); + }); + } - /** - * Wrapper for polling smapi skill package import status. - * @param {String} importId - * @param {Function} callback (err, lastImportStatus) - */ - _pollImportStatus(importId, callback) { - const retryConfig = { - base: CONSTANTS.CONFIGURATION.RETRY.GET_PACKAGE_IMPORT_STATUS.MIN_TIME_OUT, - factor: CONSTANTS.CONFIGURATION.RETRY.GET_PACKAGE_IMPORT_STATUS.FACTOR, - maxRetry: CONSTANTS.CONFIGURATION.RETRY.GET_PACKAGE_IMPORT_STATUS.MAX_RETRY - }; - const retryCall = (loopCallback) => { - this.smapiClient.skillPackage.getImportStatus(importId, (pollErr, pollResponse) => { - if (pollErr) { - return loopCallback(pollErr); - } - if (pollResponse.statusCode >= 300) { - return loopCallback(jsonView.toString(pollResponse.body)); - } - loopCallback(null, pollResponse); - }); - }; - const shouldRetryCondition = retryResponse => retryResponse.body.status === CONSTANTS.SKILL.PACKAGE_STATUS.IN_PROGRESS; - retryUtils.retry(retryConfig, retryCall, shouldRetryCondition, (err, res) => callback(err, err ? null : res)); + getBuildNameFromType(buildType) { + let buildName = buildType; + if (buildType === AC_QUICK_BUILD) { + buildName = "Alexa Conversations Light Build"; + } else if (buildType === AC_FULL_BUILD) { + buildName = "Alexa Conversations Full Build"; } - /** - * Wrapper for polling smapi skill package export status. - * @param {String} exportId - * @param {Function} callback (err, lastExportStatus) - */ - _pollExportStatus(exportId, callback) { - const retryConfig = { - base: CONSTANTS.CONFIGURATION.RETRY.GET_PACKAGE_EXPORT_STATUS.MIN_TIME_OUT, - factor: CONSTANTS.CONFIGURATION.RETRY.GET_PACKAGE_EXPORT_STATUS.FACTOR, - maxRetry: CONSTANTS.CONFIGURATION.RETRY.GET_PACKAGE_EXPORT_STATUS.MAX_RETRY - }; - const retryCall = (loopCallback) => { - this.smapiClient.skillPackage.getExportStatus(exportId, (pollErr, pollResponse) => { - if (pollErr) { - return loopCallback(pollErr); - } - if (pollResponse.statusCode >= 300) { - return loopCallback(jsonView.toString(pollResponse.body)); - } - loopCallback(null, pollResponse); - }); - }; - const shouldRetryCondition = retryResponse => retryResponse.body.status === CONSTANTS.SKILL.PACKAGE_STATUS.IN_PROGRESS; - retryUtils.retry(retryConfig, retryCall, shouldRetryCondition, (err, res) => callback(err, err ? null : res)); + return buildName; + } + + /** + * Wrapper for polling smapi skill package export status. + * @param {String} exportId + * @param {Function} callback (err, lastExportStatus) + */ + _pollExportStatus(exportId, callback) { + const retryConfig = { + base: CONSTANTS.CONFIGURATION.RETRY.GET_PACKAGE_EXPORT_STATUS.MIN_TIME_OUT, + factor: CONSTANTS.CONFIGURATION.RETRY.GET_PACKAGE_EXPORT_STATUS.FACTOR, + maxRetry: CONSTANTS.CONFIGURATION.RETRY.GET_PACKAGE_EXPORT_STATUS.MAX_RETRY, + }; + const retryCall = (loopCallback) => { + this.smapiClient.skillPackage.getExportStatus(exportId, (pollErr, pollResponse) => { + if (pollErr) { + return loopCallback(pollErr); + } + if (pollResponse.statusCode >= 300) { + return loopCallback(jsonView.toString(pollResponse.body)); + } + loopCallback(null, pollResponse); + }); + }; + const shouldRetryCondition = (retryResponse) => retryResponse.body.status === CONSTANTS.SKILL.PACKAGE_STATUS.IN_PROGRESS; + retryUtils.retry(retryConfig, retryCall, shouldRetryCondition, (err, res) => callback(err, err ? null : res)); + } + + getImportStatusPollView() { + if (!this.importStatusPollView) { + this.importStatusPollView = + this.getIsAcSkill() === true + ? new ImportStatusView(Object.keys(Manifest.getInstance().getPublishingLocales())) + : new ImportStatusView(["Interaction Model"]); } + + return this.importStatusPollView; + } + + getIsAcSkill() { + this.isACSkill = this.isAcSkill || acUtil.isAcSkill(this.profile); + return this.isACSkill; + } }; diff --git a/lib/controllers/skill-simulation-controller/index.js b/lib/controllers/skill-simulation-controller/index.js deleted file mode 100644 index 9334b481..00000000 --- a/lib/controllers/skill-simulation-controller/index.js +++ /dev/null @@ -1,87 +0,0 @@ -const R = require('ramda'); -const DialogSaveSkillIoFile = require('@src/model/dialog-save-skill-io-file'); -const SmapiClient = require('@src/clients/smapi-client'); -const jsonView = require('@src/view/json-view'); -const CONSTANTS = require('@src/utils/constants'); -const Retry = require('@src/utils/retry-utility'); - -module.exports = class SkillSimulationController { - /** - * Constructor for SkillSimulationController - * @param {Object} configuration { profile, doDebug } - * @throws {Error} if configuration is invalid for dialog. - */ - constructor(configuration) { - if (configuration === undefined) { - throw 'Cannot have an undefined configuration.'; - } - const { skillId, locale, stage, profile, saveSkillIo, debug, smapiClient, simulationType } = configuration; - this.profile = profile; - this.doDebug = debug; - this.smapiClient = smapiClient || new SmapiClient({ profile: this.profile, doDebug: this.doDebug }); - this.skillId = skillId; - this.locale = locale; - this.stage = stage; - this.simulationtype = simulationType; - this.skillIOInstance = new DialogSaveSkillIoFile(saveSkillIo); - } - - /** - * Start skill simulation by calling SMAPI POST skill simulation - * @param {String} utterance text utterance to simulate against. - * @param {Boolean} newSession Boolean to specify to FORCE_NEW_SESSION - * @param {Function} callback callback to execute upon a response. - */ - startSkillSimulation(utterance, newSession, callback) { - this.skillIOInstance.startInvocation({ utterance, newSession }); - this.smapiClient.skill.test.simulateSkill(this.skillId, this.stage, utterance, newSession, this.locale, this.simulationtype, (err, res) => { - if (err) { - return callback(err); - } - if (res.statusCode >= 300) { - return callback(jsonView.toString(res.body)); - } - callback(err, res); - }); - } - - /** - * Poll for skill simulation results. - * @todo Implement timeout. - * @param {String} simulationId simulation ID associated to the current simulation. - * @param {Function} callback function to execute upon a response. - */ - getSkillSimulationResult(simulationId, callback) { - const retryConfig = { - factor: CONSTANTS.CONFIGURATION.RETRY.GET_SIMULATE_STATUS.FACTOR, - maxRetry: CONSTANTS.CONFIGURATION.RETRY.GET_SIMULATE_STATUS.MAX_RETRY, - base: CONSTANTS.CONFIGURATION.RETRY.GET_SIMULATE_STATUS.MIN_TIME_OUT - }; - const retryCall = (loopCallback) => { - this.smapiClient.skill.test.getSimulation(this.skillId, simulationId, this.stage, (pollErr, pollResponse) => { - if (pollErr) { - return loopCallback(pollErr); - } - if (pollResponse.statusCode >= 300) { - return loopCallback(jsonView.toString(pollResponse.body)); - } - loopCallback(null, pollResponse); - }); - }; - const shouldRetryCondition = (retryResponse) => { - const status = R.view(R.lensPath(['body', 'status']), retryResponse); - return !status || status === CONSTANTS.SKILL.SIMULATION_STATUS.IN_PROGRESS; - }; - Retry.retry(retryConfig, retryCall, shouldRetryCondition, (err, res) => { - if (err) { - return callback(err); - } - this.skillIOInstance.endInvocation({ body: res.body }); - if (!res.body.status) { - return callback(`Failed to get status for simulation id: ${simulationId}.` - + 'Please run again using --debug for more details.'); - } - return callback(null, res); - }); - } -}; diff --git a/lib/controllers/skill-simulation-controller/index.ts b/lib/controllers/skill-simulation-controller/index.ts new file mode 100644 index 00000000..5e33910b --- /dev/null +++ b/lib/controllers/skill-simulation-controller/index.ts @@ -0,0 +1,120 @@ +import DialogSaveSkillIoFile from "../../model/dialog-save-skill-io-file"; +import SmapiClient, {ISmapiClient, isSmapiError} from "../../clients/smapi-client"; +import {RetriableServiceError} from "../../exceptions/cli-retriable-error"; +import CliError from "../../exceptions/cli-error"; +import {toString} from "../../view/json-view"; +import * as CONSTANTS from "../../utils/constants"; + +export interface SkillSimulationControllerProps { + skillId: string; + locale: string; + stage: string; + profile: string; + saveSkillIo: string; + debug: boolean; + smapiClient?: ISmapiClient; +} + +export class SkillSimulationController { + protected readonly profile: string; + protected readonly doDebug: boolean; + public readonly skillId: string; + public readonly locale: string; + public readonly stage: string; + smapiClient: ISmapiClient; + skillIOInstance; + + /** + * Constructor for SkillSimulationController + * @param {Object} configuration { profile, doDebug } + * @throws {Error} if configuration is invalid for dialog. + */ + constructor(configuration: SkillSimulationControllerProps) { + if (configuration === undefined) { + throw "Cannot have an undefined configuration."; + } + const {skillId, locale, stage, profile, saveSkillIo, debug, smapiClient} = configuration; + this.profile = profile; + this.doDebug = debug; + this.smapiClient = + smapiClient || + new SmapiClient({ + profile: this.profile, + doDebug: this.doDebug, + }); + this.skillId = skillId; + this.locale = locale; + this.stage = stage; + this.skillIOInstance = new DialogSaveSkillIoFile(saveSkillIo); + } + + /** + * Start skill simulation by calling SMAPI POST skill simulation + * @param {String} utterance text utterance to simulate against. + * @param {Boolean} newSession Boolean to specify to FORCE_NEW_SESSION + */ + async startSkillSimulation(utterance: string, newSession: boolean) { + this.skillIOInstance.startInvocation({ + utterance, + newSession, + }); + try { + const res = await this.smapiClient.skill.test.simulateSkill(this.skillId, this.stage, utterance, newSession, this.locale); + if (isSmapiError(res)) { + throw new RetriableServiceError(toString(res.body), res.body); + } + return res; + } catch (err) { + if (err instanceof RetriableServiceError) { + throw err; + } + throw new RetriableServiceError(err as string); + } + } + + /** + * Poll for skill simulation results. + * @todo Implement timeout. + * @param {String} simulationId simulation ID associated to the current simulation. + * @param {Function} callback function to execute upon a response. + */ + async getSkillSimulationResult(simulationId: string, pollCount?: number): Promise { + const retryConfig = { + factor: CONSTANTS.CONFIGURATION.RETRY.GET_SIMULATE_STATUS.FACTOR, + maxRetry: CONSTANTS.CONFIGURATION.RETRY.GET_SIMULATE_STATUS.MAX_RETRY, + base: CONSTANTS.CONFIGURATION.RETRY.GET_SIMULATE_STATUS.MIN_TIME_OUT, + }; + try { + const res = await this.smapiClient.skill.test.getSimulation(this.skillId, simulationId, this.stage); + if (isSmapiError(res)) { + throw new RetriableServiceError(toString(res.body), res.body); + } + this.skillIOInstance.endInvocation({ + body: res.body, + }); + const status = res.body.status; + if (status === CONSTANTS.SKILL.SIMULATION_STATUS.SUCCESS) { + return res; + } else if (status === CONSTANTS.SKILL.SIMULATION_STATUS.FAILURE) { + throw new RetriableServiceError(`Failed to simulate skill. Error: ${res.body.result.error.message}`, res.body); + } else { + if (pollCount && pollCount > retryConfig.maxRetry) { + throw new CliError( + !status + ? `Failed to get status for simulation id: ${simulationId}.` + "Please run again using --debug for more details." + : "Retry attempt exceeded.", + ); + } else { + const retryInterval = retryConfig.base * Math.pow(retryConfig.factor, pollCount ? pollCount : 0); + await new Promise((resolve) => setTimeout(resolve, retryInterval)); + return this.getSkillSimulationResult(simulationId, (pollCount ? pollCount : 0) + 1); + } + } + } catch (err) { + if (err instanceof RetriableServiceError) { + throw err; + } + throw new RetriableServiceError(err as string); + } + } +} diff --git a/lib/exceptions/cli-cfn-deployer-error.js b/lib/exceptions/cli-cfn-deployer-error.js index 39a994cf..347902c7 100644 --- a/lib/exceptions/cli-cfn-deployer-error.js +++ b/lib/exceptions/cli-cfn-deployer-error.js @@ -1,8 +1,8 @@ -const CliError = require('./cli-error'); +const CliError = require("./cli-error"); module.exports = class CliCFNDeployerError extends CliError { - constructor(message) { - super(message); - this.name = 'CliCFNDeployerError'; - } + constructor(message) { + super(message); + this.name = "CliCFNDeployerError"; + } }; diff --git a/lib/exceptions/cli-data-format-error.ts b/lib/exceptions/cli-data-format-error.ts new file mode 100644 index 00000000..85de3e98 --- /dev/null +++ b/lib/exceptions/cli-data-format-error.ts @@ -0,0 +1,12 @@ +import CliError from "./cli-error"; + +export class CliDataFormatError extends CliError { + constructor(message: string) { + super(message); + this.name = "CliDataFormatError"; + + if (Object.setPrototypeOf) { + Object.setPrototypeOf(this, new.target.prototype); + } + } +} diff --git a/lib/exceptions/cli-error.js b/lib/exceptions/cli-error.js index 9179e77f..a3f9a468 100644 --- a/lib/exceptions/cli-error.js +++ b/lib/exceptions/cli-error.js @@ -1,6 +1,6 @@ module.exports = class CliError extends Error { - constructor(message) { - super(message); - this.name = 'CliError'; - } + constructor(message) { + super(message); + this.name = "CliError"; + } }; diff --git a/lib/exceptions/cli-file-not-found-error.js b/lib/exceptions/cli-file-not-found-error.js index 30d34eef..804c933b 100644 --- a/lib/exceptions/cli-file-not-found-error.js +++ b/lib/exceptions/cli-file-not-found-error.js @@ -1,8 +1,8 @@ -const CliError = require('./cli-error'); +const CliError = require("./cli-error"); module.exports = class CliFileNotFoundError extends CliError { - constructor(message) { - super(message); - this.name = 'CliFileNotFoundError'; - } + constructor(message) { + super(message); + this.name = "CliFileNotFoundError"; + } }; diff --git a/lib/exceptions/cli-retriable-error.ts b/lib/exceptions/cli-retriable-error.ts new file mode 100644 index 00000000..78b30106 --- /dev/null +++ b/lib/exceptions/cli-retriable-error.ts @@ -0,0 +1,26 @@ +import CliError from "./cli-error"; + +export class CliRetriableError extends CliError { + constructor(message: string) { + super(message); + this.name = "CliRetriableError"; + + if (Object.setPrototypeOf) { + Object.setPrototypeOf(this, new.target.prototype); + } + } +} + +export class RetriableServiceError extends CliRetriableError { + protected readonly payload: any; + + constructor(message: string, body?: any) { + super(message); + this.name = "RetriableServiceError"; + this.payload = body; + + if (Object.setPrototypeOf) { + Object.setPrototypeOf(this, new.target.prototype); + } + } +} diff --git a/lib/exceptions/cli-warn.js b/lib/exceptions/cli-warn.js index dfb4209e..609edf24 100644 --- a/lib/exceptions/cli-warn.js +++ b/lib/exceptions/cli-warn.js @@ -1,8 +1,8 @@ -const CliError = require('./cli-error'); +const CliError = require("./cli-error"); module.exports = class CliWarn extends CliError { - constructor(message) { - super(message); - this.name = 'CliWarn'; - } + constructor(message) { + super(message); + this.name = "CliWarn"; + } }; diff --git a/lib/model/abstract-config-file.js b/lib/model/abstract-config-file.js index bb5bf56a..281d028c 100644 --- a/lib/model/abstract-config-file.js +++ b/lib/model/abstract-config-file.js @@ -1,133 +1,133 @@ -const R = require('ramda'); -const fs = require('fs-extra'); -const path = require('path'); +const R = require("ramda"); +const fs = require("fs-extra"); +const path = require("path"); -const CliFileNotFoundError = require('@src/exceptions/cli-file-not-found-error'); -const jsonView = require('@src/view/json-view'); +const CliFileNotFoundError = require("../exceptions/cli-file-not-found-error"); +const jsonView = require("../view/json-view"); -const yaml = require('./yaml-parser'); +const yaml = require("./yaml-parser"); -const FILE_EXTNAME_JSON = '.json'; -const FILE_EXTNAME_YAML = '.yaml'; -const FILE_EXTNAME_YML = '.yml'; -const FILE_TYPE_JSON = 'JSON'; -const FILE_TYPE_YAML = 'YAML'; +const FILE_EXTNAME_JSON = ".json"; +const FILE_EXTNAME_YAML = ".yaml"; +const FILE_EXTNAME_YML = ".yml"; +const FILE_TYPE_JSON = "JSON"; +const FILE_TYPE_YAML = "YAML"; const READ_METHOD_BY_FILE_TYPE = { - JSON: (filePath) => { - try { - return JSON.parse(fs.readFileSync(filePath, 'utf-8')); - } catch (error) { - throw new Error(`Failed to parse JSON file ${filePath}.\n${error}`); - } - }, - YAML: (filePath) => { - try { - return yaml.load(filePath); - } catch (error) { - throw new Error(`Failed to parse YAML file ${filePath}.\n${error}`); - } + JSON: (filePath) => { + try { + return JSON.parse(fs.readFileSync(filePath, "utf-8")); + } catch (error) { + throw new Error(`Failed to parse JSON file ${filePath}.\n${error}`); } + }, + YAML: (filePath) => { + try { + return yaml.load(filePath); + } catch (error) { + throw new Error(`Failed to parse YAML file ${filePath}.\n${error}`); + } + }, }; const WRITE_METHOD_BY_FILE_TYPE = { - JSON: (filePath, content) => { - fs.writeFileSync(filePath, jsonView.toString(content), 'utf-8'); - }, - YAML: (filePath, content) => { - yaml.dump(filePath, content); - } + JSON: (filePath, content) => { + fs.writeFileSync(filePath, jsonView.toString(content), "utf-8"); + }, + YAML: (filePath, content) => { + yaml.dump(filePath, content); + }, }; module.exports = class ConfigFile { - /** - * Constructor function for ConfigFile. Current support JSON and YAML. - * @param {string} filePath - * @throws {Error} - */ - constructor(filePath) { - this.path = filePath; - this.content = null; - this.fileType = null; - this.fileNotFoundHintMessage = ''; - } + /** + * Constructor function for ConfigFile. Current support JSON and YAML. + * @param {string} filePath + * @throws {Error} + */ + constructor(filePath) { + this.path = filePath; + this.content = null; + this.fileType = null; + this.fileNotFoundHintMessage = ""; + } - /** - * Write content to file path using ConfigFile's WRITE_METHODs - * @param {String} filePath - * @param {Object} content - */ - static withContent(filePath, content) { - // ensure file exits with content - if (fs.existsSync(filePath)) { - throw new Error(`Failed to create file ${filePath} as it already exists.`); - } - fs.ensureDirSync(path.dirname(filePath)); - const fileType = _resolveFileType(filePath); - WRITE_METHOD_BY_FILE_TYPE[fileType](filePath, content); + /** + * Write content to file path using ConfigFile's WRITE_METHODs + * @param {String} filePath + * @param {Object} content + */ + static withContent(filePath, content) { + // ensure file exits with content + if (fs.existsSync(filePath)) { + throw new Error(`Failed to create file ${filePath} as it already exists.`); } + fs.ensureDirSync(path.dirname(filePath)); + const fileType = _resolveFileType(filePath); + WRITE_METHOD_BY_FILE_TYPE[fileType](filePath, content); + } - /** - * Get property based on the property array. - * Return undefined if not found. - * @param {string} pathArray e.g. ['path', 'to', 'the', '3rd', 'object', 2, 'done'] - */ - getProperty(pathArray) { - return R.view(R.lensPath(pathArray), this.content); - } + /** + * Get property based on the property array. + * Return undefined if not found. + * @param {string} pathArray e.g. ['path', 'to', 'the', '3rd', 'object', 2, 'done'] + */ + getProperty(pathArray) { + return R.view(R.lensPath(pathArray), this.content); + } - /** - * Set property to the runtime object based on the property array. - * Create field if path does not exist. - * @param {string} pathArray - * @param {string} newValue - */ - setProperty(pathArray, newValue) { - this.content = R.set(R.lensPath(pathArray), newValue, this.content); - } + /** + * Set property to the runtime object based on the property array. + * Create field if path does not exist. + * @param {string} pathArray + * @param {string} newValue + */ + setProperty(pathArray, newValue) { + this.content = R.set(R.lensPath(pathArray), newValue, this.content); + } - /** - * Write file according to the file path and serialize it based on file extname - */ - write() { - WRITE_METHOD_BY_FILE_TYPE[this.fileType](this.path, this.content); - } + /** + * Write file according to the file path and serialize it based on file extname + */ + write() { + WRITE_METHOD_BY_FILE_TYPE[this.fileType](this.path, this.content); + } - /** - * Read from file path and deserialize it based on file extname - */ - read() { - this._validateFilePath(); - this.fileType = _resolveFileType(this.path); - this.content = READ_METHOD_BY_FILE_TYPE[this.fileType](this.path); - } + /** + * Read from file path and deserialize it based on file extname + */ + read() { + this._validateFilePath(); + this.fileType = _resolveFileType(this.path); + this.content = READ_METHOD_BY_FILE_TYPE[this.fileType](this.path); + } - _validateFilePath() { - // check existence - if (!fs.existsSync(this.path)) { - throw new CliFileNotFoundError(`File ${this.path} not exists.${this.fileNotFoundHintMessage}`); - } - // check access permission - try { - fs.accessSync(this.path, fs.constants.R_OK | fs.constants.W_OK); - } catch (error) { - throw new Error(`No access to read/write file ${this.path}.`); - } + _validateFilePath() { + // check existence + if (!fs.existsSync(this.path)) { + throw new CliFileNotFoundError(`File ${this.path} not exists.${this.fileNotFoundHintMessage}`); + } + // check access permission + try { + fs.accessSync(this.path, fs.constants.R_OK | fs.constants.W_OK); + } catch (error) { + throw new Error(`No access to read/write file ${this.path}.`); } + } }; function _resolveFileType(filePath) { - if (path.basename(filePath) === 'cli_config') { - return FILE_TYPE_JSON; - } - // check file extension - const fileExtension = path.extname(filePath).toLowerCase(); - if (fileExtension === FILE_EXTNAME_JSON) { - return FILE_TYPE_JSON; - } - if (fileExtension === FILE_EXTNAME_YAML || fileExtension === FILE_EXTNAME_YML) { - return FILE_TYPE_YAML; - } + if (path.basename(filePath) === "cli_config") { + return FILE_TYPE_JSON; + } + // check file extension + const fileExtension = path.extname(filePath).toLowerCase(); + if (fileExtension === FILE_EXTNAME_JSON) { + return FILE_TYPE_JSON; + } + if (fileExtension === FILE_EXTNAME_YAML || fileExtension === FILE_EXTNAME_YML) { + return FILE_TYPE_YAML; + } - throw new Error(`File type for ${filePath} is not supported. Only JSON and YAML files are supported.`); + throw new Error(`File type for ${filePath} is not supported. Only JSON and YAML files are supported.`); } diff --git a/lib/model/app-config.js b/lib/model/app-config.js index 3db43493..2e20aaf3 100644 --- a/lib/model/app-config.js +++ b/lib/model/app-config.js @@ -1,106 +1,106 @@ -const fs = require('fs-extra'); -const os = require('os'); -const path = require('path'); +const fs = require("fs-extra"); +const os = require("os"); +const path = require("path"); -const CONSTANTS = require('@src/utils/constants'); -const profileHelper = require('@src/utils/profile-helper'); -const ConfigFile = require('./abstract-config-file'); +const CONSTANTS = require("../utils/constants"); +const profileHelper = require("../utils/profile-helper"); +const ConfigFile = require("./abstract-config-file"); const defaultFilePath = path.join(os.homedir(), CONSTANTS.FILE_PATH.ASK.HIDDEN_FOLDER, CONSTANTS.FILE_PATH.ASK.PROFILE_FILE); // instance which stores the singleton let instance = null; module.exports = class AppConfig extends ConfigFile { - /** - * Constructor for GlobalConfig class - * @param {string} filePath - * @throws {Error} - */ - constructor(filePath = defaultFilePath) { - if (instance && instance.path === filePath) { - return instance; - } - // init by calling super() if instance not exists - super(filePath); - this.isEnvProfile = profileHelper.isEnvProfile(); - if (!this.isEnvProfile) { - this.read(); - } - instance = this; + /** + * Constructor for GlobalConfig class + * @param {string} filePath + * @throws {Error} + */ + constructor(filePath = defaultFilePath) { + if (instance && instance.path === filePath) { + return instance; } - - static getInstance() { - return instance; - } - - static dispose() { - instance = null; - } - - static configFileExists() { - return fs.existsSync(defaultFilePath); - } - - // getter and setter - - getAwsProfile(profile) { - return this.getProperty(['profiles', profile, 'aws_profile']); - } - - setAwsProfile(profile, awsProfile) { - this.setProperty(['profiles', profile, 'aws_profile'], awsProfile); + // init by calling super() if instance not exists + super(filePath); + this.isEnvProfile = profileHelper.isEnvProfile(); + if (!this.isEnvProfile) { + this.read(); } + instance = this; + } - getToken(profile) { - if (this.isEnvProfile) { - return { - access_token: process.env.ASK_ACCESS_TOKEN, - refresh_token: process.env.ASK_REFRESH_TOKEN - }; - } - return this.getProperty(['profiles', profile, 'token']); - } + static getInstance() { + return instance; + } - setToken(profile, tokenObject) { - this.setProperty(['profiles', profile, 'token'], tokenObject); - } + static dispose() { + instance = null; + } - getVendorId(profile) { - return this.isEnvProfile ? process.env.ASK_VENDOR_ID : this.getProperty(['profiles', profile, 'vendor_id']); - } + static configFileExists() { + return fs.existsSync(defaultFilePath); + } - setVendorId(profile, vendorId) { - this.setProperty(['profiles', profile, 'vendor_id'], vendorId); - } + // getter and setter - setMachineId(machineId) { - this.setProperty(['machine_id'], machineId); - } - - getMachineId() { - return this.getProperty(['machine_id']); - } + getAwsProfile(profile) { + return this.getProperty(["profiles", profile, "aws_profile"]); + } - getShareUsage() { - const shareUsage = this.getProperty(['share_usage']); - if (shareUsage !== undefined) return shareUsage; + setAwsProfile(profile, awsProfile) { + this.setProperty(["profiles", profile, "aws_profile"], awsProfile); + } - return true; + getToken(profile) { + if (this.isEnvProfile) { + return { + access_token: process.env.ASK_ACCESS_TOKEN, + refresh_token: process.env.ASK_REFRESH_TOKEN, + }; } - - /** - * Returns all profile names and their associated aws profile names (if any) as list of objects. - * return profilesList. Eg: [{ askProfile: 'askProfile1', awsProfile: 'awsProfile1'}, { askProfile: 'askProfile2', awsProfile: 'awsProfile2'}]. - */ - getProfilesList() { - const profilesList = []; - const profilesObj = this.getProperty(['profiles']); - for (const profile of Object.getOwnPropertyNames(profilesObj)) { - profilesList.push({ - askProfile: profile, - awsProfile: profilesObj[profile].aws_profile - }); - } - return profilesList; + return this.getProperty(["profiles", profile, "token"]); + } + + setToken(profile, tokenObject) { + this.setProperty(["profiles", profile, "token"], tokenObject); + } + + getVendorId(profile) { + return this.isEnvProfile ? process.env.ASK_VENDOR_ID : this.getProperty(["profiles", profile, "vendor_id"]); + } + + setVendorId(profile, vendorId) { + this.setProperty(["profiles", profile, "vendor_id"], vendorId); + } + + setMachineId(machineId) { + this.setProperty(["machine_id"], machineId); + } + + getMachineId() { + return this.getProperty(["machine_id"]); + } + + getShareUsage() { + const shareUsage = this.getProperty(["share_usage"]); + if (shareUsage !== undefined) return shareUsage; + + return true; + } + + /** + * Returns all profile names and their associated aws profile names (if any) as list of objects. + * return profilesList. Eg: [{ askProfile: 'askProfile1', awsProfile: 'awsProfile1'}, { askProfile: 'askProfile2', awsProfile: 'awsProfile2'}]. + */ + getProfilesList() { + const profilesList = []; + const profilesObj = this.getProperty(["profiles"]); + for (const profile of Object.getOwnPropertyNames(profilesObj)) { + profilesList.push({ + askProfile: profile, + awsProfile: profilesObj[profile].aws_profile, + }); } + return profilesList; + } }; diff --git a/lib/model/build-status-local-cache.ts b/lib/model/build-status-local-cache.ts new file mode 100644 index 00000000..0d154674 --- /dev/null +++ b/lib/model/build-status-local-cache.ts @@ -0,0 +1,91 @@ +import {BuildDetailStep, BuildType} from "./skill-status"; +import {ImportBuildStatus} from "./import-status"; + +/** + * Local cache entry representing the BuildStatus for a specific locale + */ +export class BuildStatusLocalCacheEntry { + private buildDetailSteps: {[key: string]: BuildDetailStep}; + private importBuildStatus: ImportBuildStatus; + + /** + * Constructor function to instantiate a BuildStatusLocalCacheEntry object + * @param {ImportBuildStatus} importStatus The import package status in the given locale + */ + constructor(importBuildStatus: ImportBuildStatus) { + this.buildDetailSteps = {}; + this.importBuildStatus = importBuildStatus; + } + + /** + * function to retrieve the BuildDetailStep for a given build type + * @param buildType the build type + * @returns {BuildDetailStep} the BuildDetailStep for a given build type + */ + getBuildDetailStep(buildType: BuildType): BuildDetailStep { + return this.buildDetailSteps[buildType]; + } + + /** + * setter for the a given build detail step + * @param buildDetailStep the BuildDetailStep object to set + */ + setBuildDetailStep(buildDetailStep: BuildDetailStep) { + this.buildDetailSteps[buildDetailStep.buildType] = buildDetailStep; + } + + /** + * getter for the import build status for the current locale + * @returns {ImportBuildStatus} + */ + getImportStatus(): ImportBuildStatus { + return this.importBuildStatus; + } + + /** + * function to update the import build status for the current locale + * @param importStatus the new import build status + */ + setImportStatus(importStatus: ImportBuildStatus) { + this.importBuildStatus = importStatus; + } + + /** + * function to check if the import build status for the current locale has started + * @returns {boolean} true if the import build status for the current locale has started + */ + hasBuildStarted(): boolean { + return this.importBuildStatus !== undefined; + } +} + +/** + * Class to abstract a local cache for storing the latest BuildStatus + */ +export class BuildStatusLocalCache { + statuses: {[key: string]: BuildStatusLocalCacheEntry}; + + constructor() { + this.statuses = {}; + } + + /** + * Function to fetch the BuildStatusLocalCacheEntry from the local cache + * @param {string} locale The build locale for this specific local cache entry + * @param {BuildType} buildType The Build Type for this specific local cache entry + * @returns {BuildStatusLocalCacheEntry} BuildStatusLocalCacheEntry containing the BuildStatus for the provided locale + */ + get(locale: string): BuildStatusLocalCacheEntry { + return this.statuses[locale]; + } + + /** + * Function to insert/update the BuildStatusLocalCacheEntry in the Local cache for the provided locale + * @param {string} locale The build locale to insert into the local cache entry + * @param {ImportBuildStatus} importBuildStatus The import build status for the given locale + */ + set(locale: string, importBuildStatus: ImportBuildStatus) { + this.statuses[locale] = this.statuses[locale] || new BuildStatusLocalCacheEntry(importBuildStatus); + this.statuses[locale].setImportStatus(importBuildStatus); + } +} diff --git a/lib/model/callback.ts b/lib/model/callback.ts new file mode 100644 index 00000000..80adcf52 --- /dev/null +++ b/lib/model/callback.ts @@ -0,0 +1,2 @@ +export type callbackError = Error | null; +export type uiCallback = (err: callbackError, result?: any) => void; diff --git a/lib/model/dialog-replay-file.js b/lib/model/dialog-replay-file.js index abfa2868..1da3c3ca 100644 --- a/lib/model/dialog-replay-file.js +++ b/lib/model/dialog-replay-file.js @@ -1,114 +1,114 @@ -const fs = require('fs-extra'); -const R = require('ramda'); +const fs = require("fs-extra"); +const R = require("ramda"); -const CliFileNotFoundError = require('@src/exceptions/cli-file-not-found-error'); -const jsonView = require('@src/view/json-view'); +const CliFileNotFoundError = require("../exceptions/cli-file-not-found-error"); +const jsonView = require("../view/json-view"); module.exports = class DialogReplayFile { - /** - * Constructor for GlobalConfig class - * @param {string} filePath - * @throws {Error} - */ - constructor(filePath) { - this.filePath = filePath; - this.content = this.readFileContent(this.filePath); + /** + * Constructor for GlobalConfig class + * @param {string} filePath + * @throws {Error} + */ + constructor(filePath) { + this.filePath = filePath; + this.content = this.readFileContent(this.filePath); + } + + // Getters and Setters + + getSkillId() { + return this.getProperty(["skillId"]); + } + + setSkillId(skillId) { + return this.setProperty(["skillId"], skillId); + } + + getLocale() { + return this.getProperty(["locale"]); + } + + setLocale(locale) { + return this.setProperty(["locale"], locale); + } + + getType() { + return this.getProperty(["type"]); + } + + setType(type) { + return this.setProperty(["type"], type); + } + + getUserInput() { + return this.getProperty(["userInput"]); + } + + setUserInput(userInput) { + return this.setProperty(["userInput"], userInput); + } + + // TODO: move these operations to a model interface since replay file doesn't support yaml files currently. + + /** + * Reads contents of a given file. Currently supports files of the following types: .json, .yaml and .yml + * Throws error if filePath is invalid, file does not have read permissions or is of unsupported file type. + * @param {String} filePath path to the given file. + */ + readFileContent(filePath) { + try { + this.doesFileExist(filePath); + fs.accessSync(filePath, fs.constants.R_OK); + return fs.readJsonSync(filePath); + } catch (error) { + throw `Failed to parse file: ${filePath}.\n${error.message}`; } - - // Getters and Setters - - getSkillId() { - return this.getProperty(['skillId']); - } - - setSkillId(skillId) { - return this.setProperty(['skillId'], skillId); + } + + /** + * Writes contents to a given file. Currently supports files of the following types: .json, .yaml and .yml + * Throws error if filePath is invalid, file does not have write permissions or is of unsupported file type. + * @param {Object} content data to ve written to the file + * @param {String} filePath path to the given file. + */ + writeContentToFile(content, filePath) { + try { + this.doesFileExist(filePath); + fs.accessSync(filePath, fs.constants.W_OK); + fs.writeFileSync(filePath, jsonView.toString(content), "utf-8"); + } catch (error) { + throw `Failed to write to file ${filePath}.\n${error.message}`; } - - getLocale() { - return this.getProperty(['locale']); - } - - setLocale(locale) { - return this.setProperty(['locale'], locale); - } - - getType() { - return this.getProperty(['type']); - } - - setType(type) { - return this.setProperty(['type'], type); - } - - getUserInput() { - return this.getProperty(['userInput']); - } - - setUserInput(userInput) { - return this.setProperty(['userInput'], userInput); - } - - // TODO: move these operations to a model interface since replay file doesn't support yaml files currently. - - /** - * Reads contents of a given file. Currently supports files of the following types: .json, .yaml and .yml - * Throws error if filePath is invalid, file does not have read permissions or is of unsupported file type. - * @param {String} filePath path to the given file. - */ - readFileContent(filePath) { - try { - this.doesFileExist(filePath); - fs.accessSync(filePath, fs.constants.R_OK); - return fs.readJsonSync(filePath); - } catch (error) { - throw `Failed to parse file: ${filePath}.\n${error.message}`; - } - } - - /** - * Writes contents to a given file. Currently supports files of the following types: .json, .yaml and .yml - * Throws error if filePath is invalid, file does not have write permissions or is of unsupported file type. - * @param {Object} content data to ve written to the file - * @param {String} filePath path to the given file. - */ - writeContentToFile(content, filePath) { - try { - this.doesFileExist(filePath); - fs.accessSync(filePath, fs.constants.W_OK); - fs.writeFileSync(filePath, jsonView.toString(content), 'utf-8'); - } catch (error) { - throw `Failed to write to file ${filePath}.\n${error.message}`; - } - } - - /** - * Check if the file exists on the given path. Throws error if it doesn't exist. - * @param {String} filePath path to the given file. - */ - doesFileExist(filePath) { - if (!fs.existsSync(filePath)) { - throw new CliFileNotFoundError(`File ${filePath} not exists.`); - } - } - - // TODO: these two methods can be in jsonView since we are reading/modifying JSON content - /** - * Get property based on the property array. - * Return undefined if not found. - * @param {string} pathArray e.g. ['path', 'to', 'the', '3rd', 'object', 2, 'done'] - */ - getProperty(pathArray) { - return R.view(R.lensPath(pathArray), this.content); - } - - /** - * Set property to the runtime object based on the property array. - * Create field if path does not exist. - * @param {string} pathArray - * @param {string} newValue - */ - setProperty(pathArray, newValue) { - this.content = R.set(R.lensPath(pathArray), newValue, this.content); + } + + /** + * Check if the file exists on the given path. Throws error if it doesn't exist. + * @param {String} filePath path to the given file. + */ + doesFileExist(filePath) { + if (!fs.existsSync(filePath)) { + throw new CliFileNotFoundError(`File ${filePath} not exists.`); } + } + + // TODO: these two methods can be in jsonView since we are reading/modifying JSON content + /** + * Get property based on the property array. + * Return undefined if not found. + * @param {string} pathArray e.g. ['path', 'to', 'the', '3rd', 'object', 2, 'done'] + */ + getProperty(pathArray) { + return R.view(R.lensPath(pathArray), this.content); + } + + /** + * Set property to the runtime object based on the property array. + * Create field if path does not exist. + * @param {string} pathArray + * @param {string} newValue + */ + setProperty(pathArray, newValue) { + this.content = R.set(R.lensPath(pathArray), newValue, this.content); + } }; diff --git a/lib/model/dialog-save-skill-io-file.js b/lib/model/dialog-save-skill-io-file.js index d77ff384..b892a046 100644 --- a/lib/model/dialog-save-skill-io-file.js +++ b/lib/model/dialog-save-skill-io-file.js @@ -1,46 +1,46 @@ -const fs = require('fs-extra'); -const jsonView = require('@src/view/json-view'); -const R = require('ramda'); +const fs = require("fs-extra"); +const jsonView = require("../view/json-view"); +const R = require("ramda"); class DialogSaveSkillIoFile { - /** - * Constructor for DialogSaveSkillIoFile class - * @param {string} filePath - */ - constructor(filePath) { - this.filePath = filePath; - this.content = { invocations: [] }; - } + /** + * Constructor for DialogSaveSkillIoFile class + * @param {string} filePath + */ + constructor(filePath) { + this.filePath = filePath; + this.content = {invocations: []}; + } - /** - * Adds invocation start request to in memory invocation list - * @param {*} request invocation request - */ - startInvocation(request) { - this.currentInvocation = { request: {}, response: {} }; - this.currentInvocation.request = request; - } + /** + * Adds invocation start request to in memory invocation list + * @param {*} request invocation request + */ + startInvocation(request) { + this.currentInvocation = {request: {}, response: {}}; + this.currentInvocation.request = request; + } - /** - * Adds invocation end response to in memory invocation list - * @param {*} response invocation response - */ - endInvocation(response) { - if (!this.currentInvocation) { - this.currentInvocation = { response: {} }; - } - this.currentInvocation.response = response; - this.content.invocations.push(R.clone(this.currentInvocation)); + /** + * Adds invocation end response to in memory invocation list + * @param {*} response invocation response + */ + endInvocation(response) { + if (!this.currentInvocation) { + this.currentInvocation = {response: {}}; } + this.currentInvocation.response = response; + this.content.invocations.push(R.clone(this.currentInvocation)); + } - /** - * Saves invocation list to a file - */ - save() { - if (this.filePath) { - fs.writeFileSync(this.filePath, jsonView.toString(this.content), 'utf-8'); - } + /** + * Saves invocation list to a file + */ + save() { + if (this.filePath) { + fs.writeFileSync(this.filePath, jsonView.toString(this.content), "utf-8"); } + } } module.exports = DialogSaveSkillIoFile; diff --git a/lib/model/dialog/inputs.ts b/lib/model/dialog/inputs.ts new file mode 100644 index 00000000..61f186e2 --- /dev/null +++ b/lib/model/dialog/inputs.ts @@ -0,0 +1,107 @@ +export const inputToCommand = (input: string): SpecialCommand => { + const [enm] = Object.entries(SpecialCommand).find(([, value]) => value === input.toLowerCase()) || [undefined]; + return enm ? (SpecialCommand)[enm] : SpecialCommand.UNKNOWN; +}; + +export const isCommand = (input: any): input is SpecialCommandInput => { + return "command" in input; +}; + +export interface EndTurn extends SpecialCommandInput { + command: SpecialCommand.END_TURN; +} + +export type TerminalCommand = SpecialCommand.QUIT; + +export interface Quit extends SpecialCommandInput { + command: TerminalCommand; +} + +export const isQuitCommandInput = (cmd: any): cmd is Quit => { + return isCommand(cmd) && isQuitCommand(cmd.command); +}; + +export const isQuitCommand = (cmd: SpecialCommand): cmd is SpecialCommand.QUIT => { + return isCommandOfType(cmd, [SpecialCommand.QUIT]); +}; + +export const isCommandOfType = (cmd: SpecialCommand, types: T[]): cmd is T => { + return types.includes(cmd as T); +}; + +export type UserInput = SpecialCommandInput | UtteranceInput | CorrectionInput | Corrections; +export type UtteranceInput = {utterance: string}; +export type SpecialCommandInput = {command: SpecialCommand}; +/** + * Command values should be lower cased. + * Command evaluation will be case agnostic. + */ +export enum SpecialCommand { + QUIT = ".quit", + SAVE = ".save", + VARS = ".vars", + END_TURN = ".endturn", + UNKNOWN = "UNKNOWN", +} + +export interface CorrectionInput { + correction: string; +} + +export interface CorrectionsInput { + type?: CorrectionInput; + content: CorrectionInput | SpecialCommandInput; +} + +export interface Corrections { + type?: CorrectionInput; + content: CorrectionInput; +} + +export interface ACDLLineInfo { + responses: ACDLLineInfoCell[]; + beforeResponse: ACDLLineInfoCell[]; +} + +export interface ACDLLineInfoCell { + acdl: string; + explanation: string; +} + +export interface ResponseAndAcdlGroup { + responseLine?: string; + acdlLines?: ACDLLineInfoCell[]; +} + +export interface ResponseAndAcdlGroups { + before: ACDLLineInfoCell[]; + groups: ResponseAndAcdlGroup[]; +} + +export const partitionAcdlResponses = (acdlLines: ACDLLineInfo, responses: string[]): ResponseAndAcdlGroups => { + // Partition the ACDL lines with each partition ending with response() + const partitionedAcdlLines = acdlLines.responses + .reduce((acc, resp) => { + const [head = [], ...rest] = acc; + + // Add a new partition to the start when the response ends with response() + return [ + ...(resp.acdl.match(/.*response\(.+\).*/g) ? [[]] : []), + // Add the current response to the first partition + [...head, resp], + ...rest, + ]; + }, [] as ACDLLineInfoCell[][]) + // New partitions are at the end of the list, reverse to get the right order + .reverse(); + + return { + // Match a response with the partitioned acdlLines. + // Its possible for the acdlLine partitions or the responses to be longer. + groups: [...Array(Math.max(partitionedAcdlLines.length, responses.length)).keys()].map((i) => ({ + responseLine: responses.length > i ? responses[i] : undefined, + acdlLines: partitionedAcdlLines.length > i ? partitionedAcdlLines[i] : undefined, + })), + before: acdlLines.beforeResponse, + }; +}; diff --git a/lib/model/import-status.ts b/lib/model/import-status.ts new file mode 100644 index 00000000..8cb222c7 --- /dev/null +++ b/lib/model/import-status.ts @@ -0,0 +1,69 @@ +import {view, lensPath} from "ramda"; + +/** + * type representing the getImportStatus SMAPI response resource's build statuses + */ +export type ImportBuildStatus = "IN_PROGRESS" | "SUCCEEDED" | "FAILED" | "ROLLBACK_IN_PROGRESS" | "ROLLBACK_SUCCEEDED" | "ROLLBACK_FAILED"; + +/** + * Class to abstract a single resource object from the GetImportStatus SMAPI API response JSON + * { + * name:, + * status: + * } + */ +class ImportStatusResource { + locale: string; + status: ImportBuildStatus; + constructor(locale: string, status: ImportBuildStatus) { + this.locale = locale; + this.status = status; + } +} + +/** + * A warning object that is returned in from the SMAPI getSkillStatus API response. + */ +interface ImportStatusWarning { + message: string; +} + +/** + * Class to abstract the skillId and resources from the SMAPI getSkillStatus API response JSON + * { + * body: { + * skill: { + * skillId: , + * resources: [ + * { + * action: , + * name:, + * status: + * }, + * ... + * ] + * } + * } + * } + */ +export class ImportStatus { + resources: ImportStatusResource[]; + skillId: string; + warnings: ImportStatusWarning[]; + + constructor(pollImportStatusResponse: object) { + this.skillId = view(lensPath(["body", "skill", "skillId"]), pollImportStatusResponse); + this.warnings = view(lensPath(["body", "warnings"]), pollImportStatusResponse) || []; + this.resources = new Array(); + const resources = view(lensPath(["body", "skill", "resources"]), pollImportStatusResponse) || []; + resources.forEach((res: object) => { + const name: string = view(lensPath(["name"]), res); + const status: ImportBuildStatus = view(lensPath(["status"]), res); + this.resources.push(new ImportStatusResource(this._getLocaleFromInteractionModel(name), status)); + }); + } + + private _getLocaleFromInteractionModel(interactionModelName: string): string { + return interactionModelName ? interactionModelName.replace("InteractionModel.", "") : ""; + } +} diff --git a/lib/model/manifest.js b/lib/model/manifest.js index d6808062..8a2f28eb 100644 --- a/lib/model/manifest.js +++ b/lib/model/manifest.js @@ -1,131 +1,131 @@ -const ConfigFile = require('./abstract-config-file'); +const ConfigFile = require("./abstract-config-file"); // instance which stores the singleton let instance = null; module.exports = class Manifest extends ConfigFile { - /** - * Constructor for Manifest class - * @param {string} filePath - * @throws {Error} - */ - constructor(filePath) { - if (instance && instance.path === filePath) { - return instance; - } - // init by calling super() if instance not exists - super(filePath); - this.read(); - instance = this; - } - - static getInstance() { - return instance; - } - - static dispose() { - instance = null; - } - - static get endpointTypes() { - return { - EVENTS: 'events', - APIS: 'apis' - }; - } - - /** - * Skill name is decided by en-US locale's name or the first locale's name if en-US doesn't exist - */ - getSkillName() { - const publishingLocales = this.getPublishingLocales(); - const finalLocale = publishingLocales['en-US'] ? 'en-US' : Object.keys(publishingLocales)[0]; - return this.getProperty(['manifest', 'publishingInformation', 'locales', finalLocale, 'name']); - } - - setSkillName(skillName) { - const publishingLocales = this.getPublishingLocales(); - const finalLocale = publishingLocales['en-US'] ? 'en-US' : Object.keys(publishingLocales)[0]; - this.setProperty(['manifest', 'publishingInformation', 'locales', finalLocale, 'name'], skillName); - } - - // getter and setter - - getPublishingLocales() { - return this.getProperty(['manifest', 'publishingInformation', 'locales']); - } - - setPublishingLocales(localesObject) { - this.setProperty(['manifest', 'publishingInformation', 'locales'], localesObject); - } - - getPublishingLocale(locale) { - return this.getProperty(['manifest', 'publishingInformation', 'locales', locale]); - } - - setPublishingLocale(locale, localeObject) { - this.setProperty(['manifest', 'publishingInformation', 'locales', locale], localeObject); - } - - getApis() { - return this.getProperty(['manifest', Manifest.endpointTypes.APIS]); - } - - setApis(apisObject) { - this.setProperty(['manifest', Manifest.endpointTypes.APIS], apisObject); - } - - getApisDomain(domain) { - return this.getProperty(['manifest', Manifest.endpointTypes.APIS, domain]); - } - - setApisDomain(domain, domainObject) { - this.setProperty(['manifest', Manifest.endpointTypes.APIS, domain], domainObject); - } - - getEventsEndpointByRegion(region) { - if (region === 'default') { - return this.getProperty(['manifest', Manifest.endpointTypes.EVENTS, 'endpoint']); - } - return this.getProperty(['manifest', Manifest.endpointTypes.EVENTS, 'regions', region, 'endpoint']); - } - - setEventsEndpointByRegion(region, endpointObj) { - if (region === 'default') { - this.setProperty(['manifest', Manifest.endpointTypes.EVENTS, 'endpoint'], endpointObj); - } else { - this.setProperty(['manifest', Manifest.endpointTypes.EVENTS, 'regions', region, 'endpoint'], endpointObj); - } - } - - getApisEndpointByDomainRegion(domain, region) { - if (region === 'default') { - return this.getProperty(['manifest', Manifest.endpointTypes.APIS, domain, 'endpoint']); - } - return this.getProperty(['manifest', Manifest.endpointTypes.APIS, domain, 'regions', region, 'endpoint']); - } - - setApisEndpointByDomainRegion(domain, region, endpointObj) { - if (region === 'default') { - this.setProperty(['manifest', Manifest.endpointTypes.APIS, domain, 'endpoint'], endpointObj); - } else { - this.setProperty(['manifest', Manifest.endpointTypes.APIS, domain, 'regions', region, 'endpoint'], endpointObj); - } - } - - getEventsPublications() { - return this.getProperty(['manifest', Manifest.endpointTypes.EVENTS, 'publications']); - } - - setEventsPublications(publications) { - this.setProperty(['manifest', Manifest.endpointTypes.EVENTS, 'publications'], publications); - } - - getEventsSubscriptions() { - return this.getProperty(['manifest', Manifest.endpointTypes.EVENTS, 'subscriptions']); - } - - setEventsSubscriptions(subscriptions) { - this.setProperty(['manifest', Manifest.endpointTypes.EVENTS, 'subscriptions'], subscriptions); - } + /** + * Constructor for Manifest class + * @param {string} filePath + * @throws {Error} + */ + constructor(filePath) { + if (instance && instance.path === filePath) { + return instance; + } + // init by calling super() if instance not exists + super(filePath); + this.read(); + instance = this; + } + + static getInstance() { + return instance; + } + + static dispose() { + instance = null; + } + + static get endpointTypes() { + return { + EVENTS: "events", + APIS: "apis", + }; + } + + /** + * Skill name is decided by en-US locale's name or the first locale's name if en-US doesn't exist + */ + getSkillName() { + const publishingLocales = this.getPublishingLocales(); + const finalLocale = publishingLocales["en-US"] ? "en-US" : Object.keys(publishingLocales)[0]; + return this.getProperty(["manifest", "publishingInformation", "locales", finalLocale, "name"]); + } + + setSkillName(skillName) { + const publishingLocales = this.getPublishingLocales(); + const finalLocale = publishingLocales["en-US"] ? "en-US" : Object.keys(publishingLocales)[0]; + this.setProperty(["manifest", "publishingInformation", "locales", finalLocale, "name"], skillName); + } + + // getter and setter + + getPublishingLocales() { + return this.getProperty(["manifest", "publishingInformation", "locales"]); + } + + setPublishingLocales(localesObject) { + this.setProperty(["manifest", "publishingInformation", "locales"], localesObject); + } + + getPublishingLocale(locale) { + return this.getProperty(["manifest", "publishingInformation", "locales", locale]); + } + + setPublishingLocale(locale, localeObject) { + this.setProperty(["manifest", "publishingInformation", "locales", locale], localeObject); + } + + getApis() { + return this.getProperty(["manifest", Manifest.endpointTypes.APIS]); + } + + setApis(apisObject) { + this.setProperty(["manifest", Manifest.endpointTypes.APIS], apisObject); + } + + getApisDomain(domain) { + return this.getProperty(["manifest", Manifest.endpointTypes.APIS, domain]); + } + + setApisDomain(domain, domainObject) { + this.setProperty(["manifest", Manifest.endpointTypes.APIS, domain], domainObject); + } + + getEventsEndpointByRegion(region) { + if (region === "default") { + return this.getProperty(["manifest", Manifest.endpointTypes.EVENTS, "endpoint"]); + } + return this.getProperty(["manifest", Manifest.endpointTypes.EVENTS, "regions", region, "endpoint"]); + } + + setEventsEndpointByRegion(region, endpointObj) { + if (region === "default") { + this.setProperty(["manifest", Manifest.endpointTypes.EVENTS, "endpoint"], endpointObj); + } else { + this.setProperty(["manifest", Manifest.endpointTypes.EVENTS, "regions", region, "endpoint"], endpointObj); + } + } + + getApisEndpointByDomainRegion(domain, region) { + if (region === "default") { + return this.getProperty(["manifest", Manifest.endpointTypes.APIS, domain, "endpoint"]); + } + return this.getProperty(["manifest", Manifest.endpointTypes.APIS, domain, "regions", region, "endpoint"]); + } + + setApisEndpointByDomainRegion(domain, region, endpointObj) { + if (region === "default") { + this.setProperty(["manifest", Manifest.endpointTypes.APIS, domain, "endpoint"], endpointObj); + } else { + this.setProperty(["manifest", Manifest.endpointTypes.APIS, domain, "regions", region, "endpoint"], endpointObj); + } + } + + getEventsPublications() { + return this.getProperty(["manifest", Manifest.endpointTypes.EVENTS, "publications"]); + } + + setEventsPublications(publications) { + this.setProperty(["manifest", Manifest.endpointTypes.EVENTS, "publications"], publications); + } + + getEventsSubscriptions() { + return this.getProperty(["manifest", Manifest.endpointTypes.EVENTS, "subscriptions"]); + } + + setEventsSubscriptions(subscriptions) { + this.setProperty(["manifest", Manifest.endpointTypes.EVENTS, "subscriptions"], subscriptions); + } }; diff --git a/lib/model/regional-stack-file.js b/lib/model/regional-stack-file.js index 05c8f2b2..810b379b 100644 --- a/lib/model/regional-stack-file.js +++ b/lib/model/regional-stack-file.js @@ -1,65 +1,65 @@ -const ConfigFile = require('./abstract-config-file'); +const ConfigFile = require("./abstract-config-file"); // instance which stores the singleton let instance = null; -const TYPE_AWS_LAMBDA_FUNCTION = 'AWS::Lambda::Function'; -const ERROR_MSG_RESOURCES_FIELD_EMPTY = '[Error]: Resources field must not be empty in regional template file'; +const TYPE_AWS_LAMBDA_FUNCTION = "AWS::Lambda::Function"; +const ERROR_MSG_RESOURCES_FIELD_EMPTY = "[Error]: Resources field must not be empty in regional template file"; module.exports = class RegionalStackFile extends ConfigFile { - /** - * Constructor for RegionalStackFile class - * @param {string} filePath - * @throws {Error} - */ - constructor(filePath) { - if (instance && instance.path === filePath) { - return instance; - } - // init by calling super() if instance not exists - super(filePath); - this.read(); - instance = this; + /** + * Constructor for RegionalStackFile class + * @param {string} filePath + * @throws {Error} + */ + constructor(filePath) { + if (instance && instance.path === filePath) { + return instance; } + // init by calling super() if instance not exists + super(filePath); + this.read(); + instance = this; + } - static getInstance() { - return instance; - } + static getInstance() { + return instance; + } - static dispose() { - instance = null; - } + static dispose() { + instance = null; + } - getResources() { - return this.getProperty(['Resources']); - } + getResources() { + return this.getProperty(["Resources"]); + } - getLambdaFunction() { - const resources = this.getResources(); - if (!resources) { - return null; - } + getLambdaFunction() { + const resources = this.getResources(); + if (!resources) { + return null; + } - for (const logicalId of Object.keys(resources)) { - if (resources[logicalId] && resources[logicalId].Type === TYPE_AWS_LAMBDA_FUNCTION) { - return this.getProperty(['Resources', logicalId]); - } - } - return null; + for (const logicalId of Object.keys(resources)) { + if (resources[logicalId] && resources[logicalId].Type === TYPE_AWS_LAMBDA_FUNCTION) { + return this.getProperty(["Resources", logicalId]); + } } + return null; + } - setLambdaFunctionCode(bucket, key, version) { - const resources = this.getResources(); - if (!resources) { - throw new Error(ERROR_MSG_RESOURCES_FIELD_EMPTY); - } - for (const logicalId of Object.keys(resources)) { - if (resources[logicalId] && resources[logicalId].Type === TYPE_AWS_LAMBDA_FUNCTION) { - this.setProperty(['Resources', logicalId, 'Properties', 'Code', 'S3Bucket'], bucket); - this.setProperty(['Resources', logicalId, 'Properties', 'Code', 'S3Key'], key); - this.setProperty(['Resources', logicalId, 'Properties', 'Code', 'S3ObjectVersion'], version); - break; - } - } + setLambdaFunctionCode(bucket, key, version) { + const resources = this.getResources(); + if (!resources) { + throw new Error(ERROR_MSG_RESOURCES_FIELD_EMPTY); + } + for (const logicalId of Object.keys(resources)) { + if (resources[logicalId] && resources[logicalId].Type === TYPE_AWS_LAMBDA_FUNCTION) { + this.setProperty(["Resources", logicalId, "Properties", "Code", "S3Bucket"], bucket); + this.setProperty(["Resources", logicalId, "Properties", "Code", "S3Key"], key); + this.setProperty(["Resources", logicalId, "Properties", "Code", "S3ObjectVersion"], version); + break; + } } + } }; diff --git a/lib/model/resources-config/ask-resources.js b/lib/model/resources-config/ask-resources.js index 9d57675a..f2969369 100644 --- a/lib/model/resources-config/ask-resources.js +++ b/lib/model/resources-config/ask-resources.js @@ -1,102 +1,102 @@ -const ConfigFile = require('../abstract-config-file'); +const ConfigFile = require("../abstract-config-file"); // instance which stores the singleton let instance = null; const BASE = { - askcliResourcesVersion: '2020-03-31', - profiles: {} + askcliResourcesVersion: "2020-03-31", + profiles: {}, }; -const FILE_NOT_FOUND_HINT_MESSAGE = ' If this is a skill project managed by v1 ask-cli, ' -+ 'please run \'ask util upgrade-project\' then try the command again.'; +const FILE_NOT_FOUND_HINT_MESSAGE = + " If this is a skill project managed by v1 ask-cli, " + "please run 'ask util upgrade-project' then try the command again."; module.exports = class AskResources extends ConfigFile { - /** - * Constructor for AskResources class - * @param {string} filePath - * @throws {Error} - */ - constructor(filePath) { - if (instance && instance.path === filePath) { - return instance; - } - // init by calling super() if instance not exists - super(filePath); - this.fileNotFoundHintMessage = FILE_NOT_FOUND_HINT_MESSAGE; - this.read(); - instance = this; - } - - static withContent(filePath, content = BASE) { - super.withContent(filePath, content); - new AskResources(filePath); - } - - static getInstance() { - return instance; - } - - static dispose() { - instance = null; - } - - // getter and setter - - getProfile(profile) { - return this.getProperty(['profiles', profile]); - } - - setProfile(profile, profileObj) { - this.setProperty(['profiles', profile], profileObj); - } - - // Group for the "skillMetadata" - getSkillMetaSrc(profile) { - return this.getProperty(['profiles', profile, 'skillMetadata', 'src']); - } - - setSkillMetaSrc(profile, skillMetaSrc) { - this.setProperty(['profiles', profile, 'skillMetadata', 'src'], skillMetaSrc); - } - - // Group for the "code" - getCodeRegions(profile) { - return Object.keys(this.getProperty(['profiles', profile, 'code']) || []); - } - - getCodeSrcByRegion(profile, region) { - return this.getProperty(['profiles', profile, 'code', region, 'src']); - } - - setCodeSrcByRegion(profile, region, src) { - this.setProperty(['profiles', profile, 'code', region, 'src'], src); - } - - // Group for the "skillInfrastructure" - getSkillInfraType(profile) { - return this.getProperty(['profiles', profile, 'skillInfrastructure', 'type']); - } - - setSkillInfraType(profile, type) { - this.setProperty(['profiles', profile, 'skillInfrastructure', 'type'], type); - } - - getSkillInfraUserConfig(profile) { - return this.getProperty(['profiles', profile, 'skillInfrastructure', 'userConfig']); - } - - setSkillInfraUserConfig(profile, userConfig) { - this.setProperty(['profiles', profile, 'skillInfrastructure', 'userConfig'], userConfig); - } - - getTargetEndpoint(profile) { - return this.getProperty(['profiles', profile, 'skillInfrastructure', 'userConfig', 'targetEndpoint']) || []; - } - - getSkillEvents(profile) { - return this.getProperty(['profiles', profile, 'skillInfrastructure', 'userConfig', 'skillEvents']); - } + /** + * Constructor for AskResources class + * @param {string} filePath + * @throws {Error} + */ + constructor(filePath) { + if (instance && instance.path === filePath) { + return instance; + } + // init by calling super() if instance not exists + super(filePath); + this.fileNotFoundHintMessage = FILE_NOT_FOUND_HINT_MESSAGE; + this.read(); + instance = this; + } + + static withContent(filePath, content = BASE) { + super.withContent(filePath, content); + new AskResources(filePath); + } + + static getInstance() { + return instance; + } + + static dispose() { + instance = null; + } + + // getter and setter + + getProfile(profile) { + return this.getProperty(["profiles", profile]); + } + + setProfile(profile, profileObj) { + this.setProperty(["profiles", profile], profileObj); + } + + // Group for the "skillMetadata" + getSkillMetaSrc(profile) { + return this.getProperty(["profiles", profile, "skillMetadata", "src"]); + } + + setSkillMetaSrc(profile, skillMetaSrc) { + this.setProperty(["profiles", profile, "skillMetadata", "src"], skillMetaSrc); + } + + // Group for the "code" + getCodeRegions(profile) { + return Object.keys(this.getProperty(["profiles", profile, "code"]) || []); + } + + getCodeSrcByRegion(profile, region) { + return this.getProperty(["profiles", profile, "code", region, "src"]); + } + + setCodeSrcByRegion(profile, region, src) { + this.setProperty(["profiles", profile, "code", region, "src"], src); + } + + // Group for the "skillInfrastructure" + getSkillInfraType(profile) { + return this.getProperty(["profiles", profile, "skillInfrastructure", "type"]); + } + + setSkillInfraType(profile, type) { + this.setProperty(["profiles", profile, "skillInfrastructure", "type"], type); + } + + getSkillInfraUserConfig(profile) { + return this.getProperty(["profiles", profile, "skillInfrastructure", "userConfig"]); + } + + setSkillInfraUserConfig(profile, userConfig) { + this.setProperty(["profiles", profile, "skillInfrastructure", "userConfig"], userConfig); + } + + getTargetEndpoint(profile) { + return this.getProperty(["profiles", profile, "skillInfrastructure", "userConfig", "targetEndpoint"]) || []; + } + + getSkillEvents(profile) { + return this.getProperty(["profiles", profile, "skillInfrastructure", "userConfig", "skillEvents"]); + } }; module.exports.BASE = BASE; diff --git a/lib/model/resources-config/ask-states.js b/lib/model/resources-config/ask-states.js index bee7097e..aa0d99ed 100644 --- a/lib/model/resources-config/ask-states.js +++ b/lib/model/resources-config/ask-states.js @@ -1,102 +1,122 @@ -const fs = require('fs-extra'); -const path = require('path'); +const fs = require("fs-extra"); +const path = require("path"); -const CONSTANTS = require('@src/utils/constants'); +const CONSTANTS = require("../../utils/constants"); -const ConfigFile = require('../abstract-config-file'); +const ConfigFile = require("../abstract-config-file"); // instance which stores the singleton let instance = null; const BASE = { - askcliStatesVersion: '2020-03-31', - profiles: {} + askcliStatesVersion: "2020-03-31", + profiles: {}, }; module.exports = class AskStates extends ConfigFile { - /** - * Constructor for AskStates class - * @param {string} filePath - * @throws {Error} - */ - constructor(filePath) { - if (instance && instance.path === filePath) { - return instance; - } - // init by calling super() if instance not exists - super(filePath); - this.read(); - instance = this; - } - - static withContent(filePath, content = BASE) { - super.withContent(filePath, content); - new AskStates(filePath); - } - - static getInstance() { - return instance; - } - - static dispose() { - instance = null; - } - - // getter and setter - - getSkillId(profile) { - return this.getProperty(['profiles', profile, 'skillId']); - } - - setSkillId(profile, skillId) { - this.setProperty(['profiles', profile, 'skillId'], skillId); - } - - // Group for the "skillMetadata" - getSkillMetaLastDeployHash(profile) { - return this.getProperty(['profiles', profile, 'skillMetadata', 'lastDeployHash']); - } - - setSkillMetaLastDeployHash(profile, lastDeployHash) { - this.setProperty(['profiles', profile, 'skillMetadata', 'lastDeployHash'], lastDeployHash); - } - - // Group for the "code" - getCodeLastDeployHashByRegion(profile, region) { - return this.getProperty(['profiles', profile, 'code', region, 'lastDeployHash']); - } - - setCodeLastDeployHashByRegion(profile, region, hash) { - this.setProperty(['profiles', profile, 'code', region, 'lastDeployHash'], hash); + /** + * Constructor for AskStates class + * @param {string} filePath + * @throws {Error} + */ + constructor(filePath) { + if (instance && instance.path === filePath) { + return instance; } - - getCodeBuildByRegion(projRoot, codeSrc) { - if (!codeSrc) { - return null; - } - /** - * Resolve the base path for build folder: - * if src is a folder, direct add build folder inside of it; - * if src is a file, use the path to the folder it's located as base folder. - */ - const base = path.resolve( - fs.statSync(codeSrc).isDirectory() ? codeSrc : codeSrc.replace(path.basename(codeSrc), '') - ); - const mirrorPath = path.relative(projRoot, base); - return { - folder: path.join(projRoot, CONSTANTS.FILE_PATH.HIDDEN_ASK_FOLDER, mirrorPath), - file: path.join(projRoot, CONSTANTS.FILE_PATH.HIDDEN_ASK_FOLDER, mirrorPath, 'build.zip') - }; - } - - // Group for the "skillInfrastructure" - getSkillInfraDeployState(profile, infraType) { - return this.getProperty(['profiles', profile, 'skillInfrastructure', infraType, 'deployState']); - } - - setSkillInfraDeployState(profile, infraType, deployState) { - this.setProperty(['profiles', profile, 'skillInfrastructure', infraType, 'deployState'], deployState); + // init by calling super() if instance not exists + super(filePath); + this.read(); + instance = this; + } + + static withContent(filePath, content = BASE) { + super.withContent(filePath, content); + new AskStates(filePath); + } + + static getInstance() { + return instance; + } + + static dispose() { + instance = null; + } + + // getter and setter + + getSkillId(profile) { + return this.getProperty(["profiles", profile, "skillId"]); + } + + setSkillId(profile, skillId) { + this.setProperty(["profiles", profile, "skillId"], skillId); + } + + // Group for the "skillMetadata" + getSkillMetaLastDeployHash(profile) { + return this.getProperty(["profiles", profile, "skillMetadata", "lastDeployHash"]); + } + + setSkillMetaLastDeployHash(profile, lastDeployHash) { + this.setProperty(["profiles", profile, "skillMetadata", "lastDeployHash"], lastDeployHash); + } + + /** + * Gets the last skill deployment type or undefined if there hasn't been a + * deployment yet. + * + * @param {String} profile + * @returns "alexa-conversations" | "interaction-model" | undefined + */ + getSkillMetaLastDeployType(profile) { + return this.getProperty(["profiles", profile, "skillMetadata", "lastDeployType"]); + } + + /** + * Sets the last deploy type property in ask-states to the current + * skill type being deployed. + * + * @param {String} profile - user profile name + * @param {String} type - "alexa-conversations" | "interaction-model" + */ + setSkillMetaLastDeployType(profile, type) { + this.setProperty(["profiles", profile, "skillMetadata", "lastDeployType"], type); + } + + // Group for the "code" + getCodeLastDeployHashByRegion(profile, region) { + return this.getProperty(["profiles", profile, "code", region, "lastDeployHash"]); + } + + setCodeLastDeployHashByRegion(profile, region, hash) { + this.setProperty(["profiles", profile, "code", region, "lastDeployHash"], hash); + } + + getCodeBuildByRegion(projRoot, codeSrc) { + if (!codeSrc) { + return null; } + /** + * Resolve the base path for build folder: + * if src is a folder, direct add build folder inside of it; + * if src is a file, use the path to the folder it's located as base folder. + */ + const base = path.resolve(fs.statSync(codeSrc).isDirectory() ? codeSrc : codeSrc.replace(path.basename(codeSrc), "")); + const mirrorPath = path.relative(projRoot, base); + return { + folder: path.join(projRoot, CONSTANTS.FILE_PATH.HIDDEN_ASK_FOLDER, mirrorPath), + file: path.join(projRoot, CONSTANTS.FILE_PATH.HIDDEN_ASK_FOLDER, mirrorPath, "build.zip"), + }; + } + + // Group for the "skillInfrastructure" + getSkillInfraDeployState(profile, infraType) { + return this.getProperty(["profiles", profile, "skillInfrastructure", infraType, "deployState"]); + } + + setSkillInfraDeployState(profile, infraType, deployState) { + this.setProperty(["profiles", profile, "skillInfrastructure", infraType, "deployState"], deployState); + } }; module.exports.BASE = BASE; diff --git a/lib/model/resources-config/index.js b/lib/model/resources-config/index.js index aa5ccb2b..9849c630 100644 --- a/lib/model/resources-config/index.js +++ b/lib/model/resources-config/index.js @@ -1,155 +1,174 @@ -const fs = require('fs-extra'); -const path = require('path'); +const fs = require("fs-extra"); +const path = require("path"); -const CONSTANTS = require('@src/utils/constants'); +const CONSTANTS = require("../../utils/constants"); -const AskResources = require('./ask-resources'); -const AskStates = require('./ask-states'); +const AskResources = require("./ask-resources"); +const AskStates = require("./ask-states"); // instance which stores the singleton let instance = null; module.exports = class ResourcesConfig { - constructor(askResourcesPath) { - if (instance && instance.askResourcesPath === askResourcesPath) { - return instance; - } - this.askResourcesPath = askResourcesPath; - this.projectRootPath = path.dirname(askResourcesPath); - this.askStatesPath = path.join( - this.projectRootPath, CONSTANTS.FILE_PATH.HIDDEN_ASK_FOLDER, CONSTANTS.FILE_PATH.ASK_STATES_JSON_CONFIG - ); - this._loadModel(); - instance = this; - } - - /** - * When instantiating ResourcesConfig, AskResources must exist, AskStates will automatically be created. - */ - _loadModel() { - // instantiate ask-resources first to make sure the file does exist - new AskResources(this.askResourcesPath); - // ensure ask-states will exist - if (!fs.existsSync(this.askStatesPath)) { - AskStates.withContent(this.askStatesPath); - } else { - new AskStates(this.askStatesPath); - } - } - - static getInstance() { - return instance; - } - - static dispose() { - AskResources.dispose(); - AskStates.dispose(); - instance = null; - } - - write() { - AskResources.getInstance().write(); - AskStates.getInstance().write(); - } - - // getter and setter - - getProfile(profile) { - return AskResources.getInstance().getProfile(profile); - } - - setProfile(profile, profileObj) { - AskResources.getInstance().setProfile(profile, profileObj); - } - - getSkillId(profile) { - return AskStates.getInstance().getSkillId(profile); - } - - setSkillId(profile, skillId) { - AskStates.getInstance().setSkillId(profile, skillId); - } - - // Group for the "skillMetadata" - getSkillMetaSrc(profile) { - return AskResources.getInstance().getSkillMetaSrc(profile); - } - - setSkillMetaSrc(profile, skillMetaSrc) { - AskResources.getInstance().setSkillMetaSrc(profile, skillMetaSrc); - } - - getSkillMetaLastDeployHash(profile) { - return AskStates.getInstance().getSkillMetaLastDeployHash(profile); - } - - setSkillMetaLastDeployHash(profile, lastDeployHash) { - AskStates.getInstance().setSkillMetaLastDeployHash(profile, lastDeployHash); - } - - // Group for the "code" - getCodeSrcByRegion(profile, region) { - return AskResources.getInstance().getCodeSrcByRegion(profile, region); - } - - setCodeSrcByRegion(profile, region, src) { - AskResources.getInstance().setCodeSrcByRegion(profile, region, src); - } - - getCodeLastDeployHashByRegion(profile, region) { - return AskStates.getInstance().getCodeLastDeployHashByRegion(profile, region); - } - - setCodeLastDeployHashByRegion(profile, region, hash) { - AskStates.getInstance().setCodeLastDeployHashByRegion(profile, region, hash); - } - - getCodeRegions(profile) { - return AskResources.getInstance().getCodeRegions(profile); - } - - getCodeBuildByRegion(profile, region) { - const codeSrc = this.getCodeSrcByRegion(profile, region); - return AskStates.getInstance().getCodeBuildByRegion(this.projectRootPath, codeSrc); - } - - getTargetEndpoints(profile) { - return AskResources.getInstance().getTargetEndpoint(profile); - } - - getSkillEvents(profile) { - return AskResources.getInstance().getSkillEvents(profile); - } - - // Group for the "skillInfrastructure" - getSkillInfraType(profile) { - return AskResources.getInstance().getSkillInfraType(profile); - } - - setSkillInfraType(profile, type) { - AskResources.getInstance().setSkillInfraType(profile, type); - } - - getSkillInfraUserConfig(profile) { - return AskResources.getInstance().getSkillInfraUserConfig(profile); - } - - setSkillInfraUserConfig(profile, userConfig) { - AskResources.getInstance().setSkillInfraUserConfig(profile, userConfig); - } - - getSkillInfraDeployState(profile) { - const infraType = this.getSkillInfraType(profile); - return AskStates.getInstance().getSkillInfraDeployState(profile, infraType); - } - - setSkillInfraDeployState(profile, deployState) { - const infraType = this.getSkillInfraType(profile); - AskStates.getInstance().setSkillInfraDeployState(profile, infraType, deployState); - } + constructor(askResourcesPath) { + if (instance && instance.askResourcesPath === askResourcesPath) { + return instance; + } + this.askResourcesPath = askResourcesPath; + this.projectRootPath = path.dirname(askResourcesPath); + this.askStatesPath = path.join(this.projectRootPath, CONSTANTS.FILE_PATH.HIDDEN_ASK_FOLDER, CONSTANTS.FILE_PATH.ASK_STATES_JSON_CONFIG); + this._loadModel(); + instance = this; + } + + /** + * When instantiating ResourcesConfig, AskResources must exist, AskStates will automatically be created. + */ + _loadModel() { + // instantiate ask-resources first to make sure the file does exist + new AskResources(this.askResourcesPath); + // ensure ask-states will exist + if (!fs.existsSync(this.askStatesPath)) { + AskStates.withContent(this.askStatesPath); + } else { + new AskStates(this.askStatesPath); + } + } + + static getInstance() { + return instance; + } + + static dispose() { + AskResources.dispose(); + AskStates.dispose(); + instance = null; + } + + write() { + AskResources.getInstance().write(); + AskStates.getInstance().write(); + } + + // getter and setter + + getProfile(profile) { + return AskResources.getInstance().getProfile(profile); + } + + setProfile(profile, profileObj) { + AskResources.getInstance().setProfile(profile, profileObj); + } + + getSkillId(profile) { + return AskStates.getInstance().getSkillId(profile); + } + + setSkillId(profile, skillId) { + AskStates.getInstance().setSkillId(profile, skillId); + } + + // Group for the "skillMetadata" + getSkillMetaSrc(profile) { + return AskResources.getInstance().getSkillMetaSrc(profile); + } + + setSkillMetaSrc(profile, skillMetaSrc) { + AskResources.getInstance().setSkillMetaSrc(profile, skillMetaSrc); + } + + getSkillMetaLastDeployHash(profile) { + return AskStates.getInstance().getSkillMetaLastDeployHash(profile); + } + + setSkillMetaLastDeployHash(profile, lastDeployHash) { + AskStates.getInstance().setSkillMetaLastDeployHash(profile, lastDeployHash); + } + + /** + * Gets the last skill deployment type or undefined if there hasn't been a + * deployment yet. + * + * @param {String} profile + * @returns "alexa-conversations" | "interaction-model" | undefined + */ + getSkillMetaLastDeployType(profile) { + return AskStates.getInstance().getSkillMetaLastDeployType(profile); + } + + /** + * Sets the lastDeployType property in ask-states to the current skill-type being deployed. + * + * @param {String} profile - user profile name + * @param {String} type - "alexa-conversations" | "interaction-model" + */ + setSkillMetaLastDeployType(profile, type) { + AskStates.getInstance().setSkillMetaLastDeployType(profile, type); + } + + // Group for the "code" + getCodeSrcByRegion(profile, region) { + return AskResources.getInstance().getCodeSrcByRegion(profile, region); + } + + setCodeSrcByRegion(profile, region, src) { + AskResources.getInstance().setCodeSrcByRegion(profile, region, src); + } + + getCodeLastDeployHashByRegion(profile, region) { + return AskStates.getInstance().getCodeLastDeployHashByRegion(profile, region); + } + + setCodeLastDeployHashByRegion(profile, region, hash) { + AskStates.getInstance().setCodeLastDeployHashByRegion(profile, region, hash); + } + + getCodeRegions(profile) { + return AskResources.getInstance().getCodeRegions(profile); + } + + getCodeBuildByRegion(profile, region) { + const codeSrc = this.getCodeSrcByRegion(profile, region); + return AskStates.getInstance().getCodeBuildByRegion(this.projectRootPath, codeSrc); + } + + getTargetEndpoints(profile) { + return AskResources.getInstance().getTargetEndpoint(profile); + } + + getSkillEvents(profile) { + return AskResources.getInstance().getSkillEvents(profile); + } + + // Group for the "skillInfrastructure" + getSkillInfraType(profile) { + return AskResources.getInstance().getSkillInfraType(profile); + } + + setSkillInfraType(profile, type) { + AskResources.getInstance().setSkillInfraType(profile, type); + } + + getSkillInfraUserConfig(profile) { + return AskResources.getInstance().getSkillInfraUserConfig(profile); + } + + setSkillInfraUserConfig(profile, userConfig) { + AskResources.getInstance().setSkillInfraUserConfig(profile, userConfig); + } + + getSkillInfraDeployState(profile) { + const infraType = this.getSkillInfraType(profile); + return AskStates.getInstance().getSkillInfraDeployState(profile, infraType); + } + + setSkillInfraDeployState(profile, deployState) { + const infraType = this.getSkillInfraType(profile); + AskStates.getInstance().setSkillInfraDeployState(profile, infraType, deployState); + } }; module.exports.BASE = { - askcliResourcesVersion: '2020-03-31', - profiles: {} + askcliResourcesVersion: "2020-03-31", + profiles: {}, }; diff --git a/lib/model/sample-template.ts b/lib/model/sample-template.ts new file mode 100644 index 00000000..b5b85348 --- /dev/null +++ b/lib/model/sample-template.ts @@ -0,0 +1,77 @@ +type IM = "im"; +type AC = "ac"; +type ALEXA_HOSTED = "hosted"; +type CLOUDFORMATION = "cfn"; +type LAMBDA = "lambda"; +type SELF_HOSTED = "self"; +type NODE = "node"; +type PYTHON = "python"; +type JAVA = "java"; +export type SampleTemplateFilterValues = IM | AC | ALEXA_HOSTED | CLOUDFORMATION | LAMBDA | SELF_HOSTED | NODE | PYTHON | JAVA; + +/** + * + * Interface representation of a specific skill sample template blob. + * + * example: + * { + * "stack": "ac", + * "deploy": "lambda", + * "lang": "node", + * "name": "Hello world", + * "url": "https://github.com/alexa/skill-sample-nodejs-hello-world.git", + * "desc": "Alexa's hello world skill to send the greetings to the world!" + * } + */ +export interface SampleTemplate { + stack: IM | AC; + deploy: ALEXA_HOSTED | CLOUDFORMATION | LAMBDA | SELF_HOSTED; + lang: NODE | PYTHON | JAVA; + name: string; + url: string; + desc: string; + branch?: string; +} + +/** + * + * Interface representation of a flat list of skill sample templates. + * + */ +export interface SampleTemplates { + templates: SampleTemplate[]; +} + +/** + * + * Class representing a generic array of skill sample templates, which allows filtering of samples based on user input + * + * { "templates": [] } + * + */ +export class SampleTemplatesFilter implements SampleTemplates { + templates: SampleTemplate[]; + + constructor(samples: SampleTemplate[]) { + this.templates = samples; + } + + /** + * Filters unneeded sample templates from the sampleTemplates list + * + * @param key SampleTemplate key to filter + * @param value value of the key to filter. Must be one of types SampleTemplateFilterValues + */ + filter(key: K, value: SampleTemplateFilterValues): void { + this.templates = this.templates.filter((sample) => sample[key] === value); + } + + /** + * The remaining SampleTemplates + * + * @returns Array of SampleTemplate that have not been filtered + */ + getSampleTemplates(): SampleTemplate[] { + return this.templates; + } +} diff --git a/lib/model/skill-status.ts b/lib/model/skill-status.ts new file mode 100644 index 00000000..da671959 --- /dev/null +++ b/lib/model/skill-status.ts @@ -0,0 +1,143 @@ +import {SKILL} from "../../lib/utils/constants"; +import {view, lensPath} from "ramda"; + +export type BuildStatus = "SUCCEEDED" | "FAILED" | "IN_PROGRESS" | ""; + +export type BuildType = + | "LANGUAGE_MODEL_QUICK_BUILD" + | "LANGUAGE_MODEL_FULL_BUILD" + | "ALEXA_CONVERSATIONS_QUICK_BUILD" + | "ALEXA_CONVERSATIONS_FULL_BUILD"; + +export const IM_QUICK_BUILD: BuildType = "LANGUAGE_MODEL_QUICK_BUILD"; +export const IM_FULL_BUILD: BuildType = "LANGUAGE_MODEL_FULL_BUILD"; +export const AC_QUICK_BUILD: BuildType = "ALEXA_CONVERSATIONS_QUICK_BUILD"; +export const AC_FULL_BUILD: BuildType = "ALEXA_CONVERSATIONS_FULL_BUILD"; + +export enum BuildLocale { + "ar-SA" = "ar-SA", + "de-DE" = "de-DE", + "en-AU" = "en-AU", + "en-CA" = "en-CA", + "en-GB" = "en-GB", + "en-IN" = "en-IN", + "en-US" = "en-US", + "es-ES" = "es-ES", + "es-MX" = "es-MX", + "es-US" = "es-US", + "fr-CA" = "fr-CA", + "fr-FR" = "fr-FR", + "hi-IN" = "hi-IN", + "it-IT" = "it-IT", + "ja-JP" = "ja-JP", + "pt-BR" = "pt-BR", +} + +/** + * Class to abstract Build Details for a specific Step from the SMAPI getSkillStatus API response JSON + * + */ +export class BuildDetailStep { + buildType: BuildType; + buildStatus: BuildStatus; + isACBuildType: boolean; + + /** + * Constructs a BuildDetailStep object which holds the BuildDetails Step's BuildType and BuildStatus + * @param {BuildType} buildType The specific BuildType for this BuildDetails Step + * @param {BuildStatus} buildStatus The BuildStatus for this BuildDetails Step + */ + constructor(buildType: BuildType, buildStatus: BuildStatus) { + this.buildType = buildType; + this.buildStatus = buildStatus; + this.isACBuildType = buildType === AC_QUICK_BUILD || buildType === AC_FULL_BUILD; + } +} + +/** + * Class to abstract the LastUpdateRequest from the SMAPI getSkillStatus API response JSON + * lastUpdateRequest: { + * status: 'SUCCEEDED|FAILED|IN_PROGRESS', + * buildDetails: { + * steps: [ + * { + * name: , + * status: + * } + * ... + * ] + * } + * } + */ +export class LastUpdateRequest { + locale: BuildLocale; + overallBuildStatus: BuildStatus; + buildDetailSteps: {[key: string]: BuildDetailStep}; + /** + * Constructor for building a LastUpdateRequest Object + * @param {BuildLocale} locale The InteractionModel Locale for this LastUpdateRequest object + * @param lastUpdateRequest the InteractionModel Locale JSON node of the SMAPI getSkillStatus API response + */ + constructor(locale: BuildLocale, lastUpdateRequest: object) { + this.locale = locale; + const currentBuildStatus = view(lensPath(["lastUpdateRequest", "status"]), lastUpdateRequest) || ""; + this.overallBuildStatus = currentBuildStatus; + const steps = view(lensPath(["lastUpdateRequest", "buildDetails", "steps"]), lastUpdateRequest) || []; + this.buildDetailSteps = {}; + steps.forEach((step: object) => { + const name = view(lensPath(["name"]), step) || ""; + const status = view(lensPath(["status"]), step) || ""; + this.buildDetailSteps[name] = new BuildDetailStep(name, status); + }); + } + + /** + * Retrieves BuildDetailStep using the Build Type Name + * @param {string} buildTypeName build type name + * @returns {BuildDetailStep} + */ + getBuildDetailStep(buildTypeName: string): BuildDetailStep { + return this.buildDetailSteps[buildTypeName]; + } +} + +/** + * Class to abstract the InteractionModel from the SMAPI getSkillStatus API response JSON + * body: { + * interactionModel: { + * 'en-US': { + * + * } + * <...all other skill locales> + * } + * } + */ +export class InteractionModel { + lastUpdateRequests: LastUpdateRequest[]; + /** + * Constructor function to instantiate an InteractionModel object + * @param skillStatusResponse the SMAPI getSkillStatus API response JSON which has the top level "body" field + */ + constructor(skillStatusResponse: object) { + const interactionModel = view(lensPath(["body", SKILL.RESOURCES.INTERACTION_MODEL]), skillStatusResponse) || {}; + this.lastUpdateRequests = new Array(); + Object.keys(interactionModel).forEach((key: string) => { + const locale: BuildLocale = key as BuildLocale; + this.lastUpdateRequests.push(new LastUpdateRequest(locale, interactionModel[key])); + }); + } +} + +/** + * Top Level Skill Status object representing a SMAPI getSkillStatus API response + */ +export class SkillStatus { + interactionModel: InteractionModel; + /** + * Constructor function to instantiate a SkillStatus object + * @param skillStatusResponse the SMAPI getSkillStatus API response JSON which has the "body" field + */ + constructor(skillStatusResponse: object) { + this.interactionModel = new InteractionModel(skillStatusResponse); + } +} diff --git a/lib/model/yaml-parser.js b/lib/model/yaml-parser.js index afe98518..4783e708 100644 --- a/lib/model/yaml-parser.js +++ b/lib/model/yaml-parser.js @@ -1,36 +1,37 @@ /** * YAML load and dump from/to JSON object. - * Support the loading of AWS Cloudformation intrinsinc function: + * Support the loading of AWS Cloudformation Intrinsic function: * https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference.html */ -const fs = require('fs'); -const yaml = require('js-yaml'); +const fs = require("fs"); +const yaml = require("js-yaml"); // Custom type for "!Ref" -const refYamlType = new yaml.Type('!Ref', { - kind: 'scalar', - resolve: data => !!data && typeof data === 'string' && data.trim(), - construct: data => `!Ref ${data}` +const refYamlType = new yaml.Type("!Ref", { + kind: "scalar", + resolve: (data) => !!data && typeof data === "string" && data.trim(), + construct: (data) => `!Ref ${data}`, }); // Custom type for "!GetAtt" -const getattYamlType = new yaml.Type('!GetAtt', { - kind: 'scalar', - resolve: data => !!data && typeof data === 'string' && data.trim(), - construct: data => `!GetAtt ${data}` +const getattYamlType = new yaml.Type("!GetAtt", { + kind: "scalar", + resolve: (data) => !!data && typeof data === "string" && data.trim(), + construct: (data) => `!GetAtt ${data}`, }); // Create AWS schema for YAML parser -const awsSchema = yaml.Schema.create(yaml.JSON_SCHEMA, [refYamlType, getattYamlType]); +// https://github.com/nodeca/js-yaml/blob/master/migrate_v3_to_v4.md +const awsSchema = yaml.JSON_SCHEMA.extend([refYamlType, getattYamlType]); /** * Load the yaml file with aws's schema * @param {String} filePath File path for the yaml file */ function load(filePath) { - const fileData = fs.readFileSync(filePath, 'utf-8'); - return yaml.safeLoad(fileData, { schema: awsSchema }); + const fileData = fs.readFileSync(filePath, "utf-8"); + return yaml.load(fileData, {schema: awsSchema}); } /** @@ -39,10 +40,10 @@ function load(filePath) { * @param {Object} content Content to be written into filePath */ function dump(filePath, content) { - fs.writeFileSync(filePath, yaml.dump(content).replace(/: *'(.+)'/g, ': $1')); // remove the single quotes for the value + fs.writeFileSync(filePath, yaml.dump(content).replace(/: *'(.+)'/g, ": $1")); // remove the single quotes for the value } module.exports = { - load, - dump + load, + dump, }; diff --git a/postinstall.js b/lib/postinstall.js similarity index 100% rename from postinstall.js rename to lib/postinstall.js diff --git a/lib/utils/ac-util.js b/lib/utils/ac-util.js new file mode 100644 index 00000000..56a20ce3 --- /dev/null +++ b/lib/utils/ac-util.js @@ -0,0 +1,33 @@ +const fs = require("fs"); +const path = require("path"); +const {COMPILER} = require("./constants"); +const ResourcesConfig = require("../model/resources-config"); +const Manifest = require("../model/manifest"); +const jsonView = require("../view/json-view"); + +module.exports = { + isAcSkill, + syncManifest, +}; + +/** + * determine whether the skill is AC skill by check if skill-package/conversations exist + * @param {String} skillPackagePath the path of skill-package + * @returns boolean + */ +function isAcSkill(profile) { + const skillPackageSrc = ResourcesConfig.getInstance().getSkillMetaSrc(profile); + const conversationPath = path.join(skillPackageSrc, COMPILER.ACDL_PATH); + if (fs.existsSync(conversationPath)) { + return true; + } + return false; +} + +/** + * update build/skill-package/skill.json based on skill.json in src + */ +function syncManifest(manifestPath) { + const {content} = Manifest.getInstance(); + fs.writeFileSync(manifestPath, jsonView.toString(content), "utf-8"); +} diff --git a/lib/utils/constants.js b/lib/utils/constants.js index 2d613745..aaf7d7ed 100644 --- a/lib/utils/constants.js +++ b/lib/utils/constants.js @@ -1,511 +1,548 @@ -const path = require('path'); +const path = require("path"); -module.exports.APPLICATION_NAME = 'ask-cli'; -module.exports.NPM_REGISTRY_URL_BASE = 'https://registry.npmjs.org'; +module.exports.APPLICATION_NAME = "ask-cli"; +module.exports.NPM_REGISTRY_URL_BASE = "http://registry.npmjs.org"; module.exports.METRICS = { - ENDPOINT: 'https://client-telemetry.amazonalexa.com' + ENDPOINT: "https://client-telemetry.amazonalexa.com", + STOREABLE_KEYS: ["skill_id", "locale", "template_url", "stage"], }; module.exports.DEPLOYER_TYPE = { - HOSTED: { - OPTION_NAME: 'Alexa-hosted skills', - NAME: '@ask-cli/hosted-skill-deployer', - DESCRIPTION: 'Host your skill code by Alexa (free).' - }, - CFN: { - OPTION_NAME: 'AWS with CloudFormation', - NAME: '@ask-cli/cfn-deployer', - DESCRIPTION: 'Host your skill code with AWS services and provision with AWS CloudFormation (requires AWS account)' - }, - LAMBDA: { - OPTION_NAME: 'AWS Lambda', - NAME: '@ask-cli/lambda-deployer', - DESCRIPTION: 'Host your skill code on AWS Lambda (requires AWS account).' - } + HOSTED: { + OPTION_NAME: "Alexa-hosted skills", + NAME: "@ask-cli/hosted-skill-deployer", + DESCRIPTION: "Host your skill code by Alexa (free).", + }, + CFN: { + OPTION_NAME: "AWS with CloudFormation", + NAME: "@ask-cli/cfn-deployer", + DESCRIPTION: "Host your skill code with AWS services and provision with AWS CloudFormation (requires AWS account)", + }, + LAMBDA: { + OPTION_NAME: "AWS Lambda", + NAME: "@ask-cli/lambda-deployer", + DESCRIPTION: "Host your skill code on AWS Lambda (requires AWS account).", + }, + SELF_HOSTED: { + OPTION_NAME: "Self-hosted", + NAME: "self-hosted-skill-deployer", + DESCRIPTION: "Manage your own hosting", + }, }; module.exports.DEPLOY_TARGET = { - SKILL_METADATA: 'skill-metadata', - SKILL_INFRASTRUCTURE: 'skill-infrastructure', + SKILL_METADATA: "skill-metadata", + SKILL_INFRASTRUCTURE: "skill-infrastructure", }; module.exports.HOSTED_SKILL = { - DEFAULT_SKILL_NAME: 'Hello World Skill', - LOCALES: ['de-DE', 'en-AU', 'en-CA', 'en-GB', 'en-IN', 'en-US', 'es-ES', 'es-MX', - 'es-US', 'fr-CA', 'fr-FR', 'hi-IN', 'it-IT', 'ja-JP', 'pt-BR'], - REGIONS: { - 'us-east-1': 'US_EAST_1', - 'us-west-2': 'US_WEST_2', - 'eu-west-1': 'EU_WEST_1' - }, - DEFAULT_RUNTIME: { - NodeJS: 'NODE_16_X', - Python: 'PYTHON_3_7', - }, - SIGNIN_PATH: '/ap/signin', - PERMISSION_ENUM: { - NEW_SKILL: 'newSkill' - }, - RESOURCES: { - MANIFEST: 'manifest', - INTERACTION_MODEL: 'interactionModel', - PROVISIONING: 'hostedSkillProvisioning', - DEPLOYMENT: 'hostedSkillDeployment' - }, - MANIFEST: { - publishingInformation: { - locales: { - } - }, - apis: { - custom: { - } - } - }, - PERMISSION_CHECK_RESULT: { - NEW_USER_REGISTRATION_REQUIRED: 'NEW_USER_REGISTRATION_REQUIRED', - RATE_EXCEEDED: 'RATE_EXCEEDED', - ALLOWED: 'ALLOWED' - }, - MANIFEST_STATUS: { - SUCCESS: 'SUCCEEDED', - FAILURE: 'FAILED', - IN_PROGRESS: 'IN_PROGRESS' - }, - PROVISIONING_STATUS: { - SUCCESS: 'SUCCEEDED', - FAILURE: 'FAILED', - IN_PROGRESS: 'IN_PROGRESS' - }, - INTERACTION_MODEL_STATUS: { - SUCCESS: 'SUCCEEDED', - FAILURE: 'FAILED', - IN_PROGRESS: 'IN_PROGRESS' - }, - HIDDEN_GIT_FOLDER: { - NAME: '.git', - HOOKS: { - NAME: 'hooks', - PRE_PUSH: 'pre-push' - } - }, - RUN: { - INVOCATION_INFO: { - node: { skillCodeFolderName: 'lambda', - handlerName: 'handler', - skillFileName: 'index' }, - python: { - skillCodeFolderName: 'lambda', - handlerName: 'lambda_handler', - skillFileName: 'lambda_function' - } - } - } + DEFAULT_SKILL_NAME: "Hello World Skill", + DEFAULT_LOCALE: "en-US", + LOCALES: [ + "de-DE", + "en-AU", + "en-CA", + "en-GB", + "en-IN", + "en-US", + "es-ES", + "es-MX", + "es-US", + "fr-CA", + "fr-FR", + "hi-IN", + "it-IT", + "ja-JP", + "pt-BR", + ], + REGIONS: { + "us-east-1": "US_EAST_1", + "us-west-2": "US_WEST_2", + "eu-west-1": "EU_WEST_1", + }, + DEFAULT_RUNTIME: { + NodeJS: "NODE_16_X", + Python: "PYTHON_3_7", + }, + SIGNIN_PATH: "/ap/signin", + PERMISSION_ENUM: { + NEW_SKILL: "newSkill", + }, + RESOURCES: { + MANIFEST: "manifest", + INTERACTION_MODEL: "interactionModel", + PROVISIONING: "hostedSkillProvisioning", + DEPLOYMENT: "hostedSkillDeployment", + }, + MANIFEST: { + publishingInformation: { + locales: {}, + }, + apis: { + custom: {}, + }, + }, + PERMISSION_CHECK_RESULT: { + NEW_USER_REGISTRATION_REQUIRED: "NEW_USER_REGISTRATION_REQUIRED", + RATE_EXCEEDED: "RATE_EXCEEDED", + ALLOWED: "ALLOWED", + RESOURCE_LIMIT_EXCEEDED: "RESOURCE_LIMIT_EXCEEDED", + }, + MANIFEST_STATUS: { + SUCCESS: "SUCCEEDED", + FAILURE: "FAILED", + IN_PROGRESS: "IN_PROGRESS", + }, + PROVISIONING_STATUS: { + SUCCESS: "SUCCEEDED", + FAILURE: "FAILED", + IN_PROGRESS: "IN_PROGRESS", + }, + INTERACTION_MODEL_STATUS: { + SUCCESS: "SUCCEEDED", + FAILURE: "FAILED", + IN_PROGRESS: "IN_PROGRESS", + }, + HIDDEN_GIT_FOLDER: { + NAME: ".git", + HOOKS: { + NAME: "hooks", + PRE_PUSH: "pre-push", + }, + }, + RUN: { + INVOCATION_INFO: { + node: {skillCodeFolderName: "lambda", handlerName: "handler", skillFileName: "index"}, + python: { + skillCodeFolderName: "lambda", + handlerName: "lambda_handler", + skillFileName: "lambda_function", + }, + }, + }, }; module.exports.SKILL = { - RESOURCES: { - MANIFEST: 'manifest', - INTERACTION_MODEL: 'interactionModel', - }, - STAGE: { - DEVELOPMENT: 'development', - LIVE: 'live', - CERTIFICATION: 'certification' - }, - SKILL_STATUS: { - SUCCEEDED: 'SUCCEEDED', - FAILED: 'FAILED', - IN_PROGRESS: 'IN_PROGRESS', - }, - PACKAGE_STATUS: { - SUCCEEDED: 'SUCCEEDED', - FAILED: 'FAILED', - IN_PROGRESS: 'IN_PROGRESS', - ROLLBACK_SUCCEEDED: 'ROLLBACK_SUCCEEDED', - ROLLBACK_FAILED: 'ROLLBACK_FAILED', - ROLLBACK_IN_PROGRESS: 'ROLLBACK_IN_PROGRESS' - }, - VALIDATION_STATUS: { - SUCCESS: 'SUCCESSFUL', - FAILURE: 'FAILED', - IN_PROGRESS: 'IN_PROGRESS' - }, - SIMULATION_STATUS: { - SUCCESS: 'SUCCESSFUL', - FAILURE: 'FAILED', - IN_PROGRESS: 'IN_PROGRESS' - }, - DOMAIN: { - CAN_ENABLE_DOMAIN_LIST: ['custom', 'music'] - } + RESOURCES: { + MANIFEST: "manifest", + INTERACTION_MODEL: "interactionModel", + }, + STAGE: { + DEVELOPMENT: "development", + LIVE: "live", + CERTIFICATION: "certification", + }, + SKILL_STATUS: { + SUCCEEDED: "SUCCEEDED", + FAILED: "FAILED", + IN_PROGRESS: "IN_PROGRESS", + }, + PACKAGE_STATUS: { + SUCCEEDED: "SUCCEEDED", + FAILED: "FAILED", + IN_PROGRESS: "IN_PROGRESS", + ROLLBACK_SUCCEEDED: "ROLLBACK_SUCCEEDED", + ROLLBACK_FAILED: "ROLLBACK_FAILED", + ROLLBACK_IN_PROGRESS: "ROLLBACK_IN_PROGRESS", + }, + VALIDATION_STATUS: { + SUCCESS: "SUCCESSFUL", + FAILURE: "FAILED", + IN_PROGRESS: "IN_PROGRESS", + }, + SIMULATION_STATUS: { + SUCCESS: "SUCCESSFUL", + FAILURE: "FAILED", + IN_PROGRESS: "IN_PROGRESS", + }, + DOMAIN: { + CAN_ENABLE_DOMAIN_LIST: ["custom", "music"], + }, }; module.exports.CONFIGURATION = { - JSON_DISPLAY_INDENT: 2, - OPEN_BROWSER_DELAY: 1000, - RETRY: { - GET_PACKAGE_IMPORT_STATUS: { - MAX_RETRY: 50, - MIN_TIME_OUT: 2000, - FACTOR: 1.1 - }, - GET_PACKAGE_EXPORT_STATUS: { - MAX_RETRY: 30, - MIN_TIME_OUT: 2000, - FACTOR: 1.1 - }, - GET_SIMULATE_STATUS: { - MAX_RETRY: 20, - MIN_TIME_OUT: 2000, - FACTOR: 1.2 - }, - VALIDATE_SKILL_STATUS: { - MAX_RETRY: 30, - MIN_TIME_OUT: 1000, - FACTOR: 1.2 - }, - CREATE_LAMBDA_FUNCTION: { - BASE: 5000, - FACTOR: 1.5, - MAXRETRY: 3 - }, - WAIT_LAMBDA_FUNCTION: { - BASE: 1000, - FACTOR: 1.2, - MAXRETRY: 10 - } - }, - S3: { - MULTIPART_UPLOAD: { - DEFAULT_PART_SIZE: 8 * 1024 * 1024, - MAX_PART_COUNT: 1000, - MIN_PART_SIZE: 5 * 1024 * 1024, - MIN_PART_SIZE_DISPLAY: '5MB', - CONCURRENCY: 10 - }, - VERSIONING: { - NOT_FOUND_RETRY_DELAY_MS: 1000 - } - } + JSON_DISPLAY_INDENT: 2, + OPEN_BROWSER_DELAY: 1000, + RETRY: { + GET_PACKAGE_IMPORT_STATUS: { + MAX_RETRY: 50, + MIN_TIME_OUT: 2000, + FACTOR: 1.1, + }, + GET_PACKAGE_IMPORT_STATUS_FOR_AC: { + MAX_RETRY: 75, + MIN_TIME_OUT: 2000, + FACTOR: 1.12, + }, + GET_PACKAGE_EXPORT_STATUS: { + MAX_RETRY: 30, + MIN_TIME_OUT: 2000, + FACTOR: 1.1, + }, + GET_SIMULATE_STATUS: { + MAX_RETRY: 20, + MIN_TIME_OUT: 2000, + FACTOR: 1.2, + }, + VALIDATE_SKILL_STATUS: { + MAX_RETRY: 30, + MIN_TIME_OUT: 1000, + FACTOR: 1.2, + }, + CREATE_LAMBDA_FUNCTION: { + BASE: 5000, + FACTOR: 1.5, + MAXRETRY: 3, + }, + WAIT_LAMBDA_FUNCTION: { + BASE: 1000, + FACTOR: 1.2, + MAXRETRY: 10, + }, + MAX_RETRY_INTERVAL: 300000, + }, + S3: { + MULTIPART_UPLOAD: { + DEFAULT_PART_SIZE: 8 * 1024 * 1024, + MAX_PART_COUNT: 1000, + MIN_PART_SIZE: 5 * 1024 * 1024, + MIN_PART_SIZE_DISPLAY: "5MB", + CONCURRENCY: 10, + }, + VERSIONING: { + NOT_FOUND_RETRY_DELAY_MS: 1000, + }, + }, }; module.exports.FILE_PATH = { - HIDDEN_ASK_FOLDER: '.ask', - ASK_STATES_JSON_CONFIG: 'ask-states.json', - ASK_RESOURCES_JSON_CONFIG: 'ask-resources.json', - SKILL_PACKAGE: { - PACKAGE: 'skill-package', - MANIFEST: 'skill.json', - INTERACTION_MODEL: 'interactionModels' - }, - SKILL_CODE: { - CODE: 'code', // TODO ; replaced with LAMBDA - LAMBDA: 'lambda' - }, - SKILL_INFRASTRUCTURE: { - INFRASTRUCTURE: 'infrastructure' - }, - LEGACY_PATH: '.legacy', - AWS: { - HIDDEN_FOLDER: '.aws', - CREDENTIAL_FILE: 'credentials' - }, - ASK: { - HIDDEN_FOLDER: '.ask', - PROFILE_FILE: 'cli_config', - METRIC_FILE: 'cli_metric', - AUTH_INFO: 'auth_info', - SCRIPTS_FOLDER: { - NAME: 'scripts', - ASK_PRE_PUSH: 'ask-pre-push', - GIT_CREDENTIAL_HELPER: 'git-credential-helper' - } - } + HIDDEN_ASK_FOLDER: ".ask", + ASK_STATES_JSON_CONFIG: "ask-states.json", + ASK_RESOURCES_JSON_CONFIG: "ask-resources.json", + SKILL_PACKAGE: { + PACKAGE: "skill-package", + MANIFEST: "skill.json", + INTERACTION_MODEL: "interactionModels", + }, + SKILL_CODE: { + CODE: "code", // TODO ; replaced with LAMBDA + LAMBDA: "lambda", + }, + SKILL_INFRASTRUCTURE: { + INFRASTRUCTURE: "infrastructure", + }, + LEGACY_PATH: ".legacy", + AWS: { + HIDDEN_FOLDER: ".aws", + CREDENTIAL_FILE: "credentials", + }, + ASK: { + HIDDEN_FOLDER: ".ask", + PROFILE_FILE: "cli_config", + METRIC_FILE: "cli_metric", + AUTH_INFO: "auth_info", + SCRIPTS_FOLDER: { + NAME: "scripts", + ASK_PRE_PUSH: "ask-pre-push", + GIT_CREDENTIAL_HELPER: "git-credential-helper", + }, + }, }; module.exports.TEMPLATES = { - TEMPLATE_BRANCH_NAME: 'ask-cli-x', - PROJECT_BY_CODE_LANGUAGE: { - NodeJS: { - TEMPLATE_INDEX: 'https://ask-cli-static-content.s3-us-west-2.amazonaws.com/skill-templates/nodejs-templates.json' - }, - Python: { - TEMPLATE_INDEX: 'https://ask-cli-static-content.s3-us-west-2.amazonaws.com/skill-templates/python-templates.json' - }, - Java: { - TEMPLATE_INDEX: 'https://ask-cli-static-content.s3-us-west-2.amazonaws.com/skill-templates/java-templates.json' - } - }, - INTERACTION_MODEL_MAP: 'https://ask-cli-static-content.s3-us-west-2.amazonaws.com/interaction-model-templates/interaction-model-templates.json' + TEMPLATE_S3_SOURCE_URL: "https://ask-cli-static-content.s3.us-west-2.amazonaws.com/skill-templates/templates.json", + TEMPLATE_DEFAULT_BRANCH_NAME: "ask-cli-x", + INTERACTION_MODEL_MAP: + "https://ask-cli-static-content.s3-us-west-2.amazonaws.com/interaction-model-templates/interaction-model-templates.json", }; -module.exports.AWS_SKILL_INFRASTRUCTURE_DEFAULT_REGION = 'us-east-1'; +module.exports.AWS_SKILL_INFRASTRUCTURE_DEFAULT_REGION = "us-east-1"; module.exports.ALEXA = { - REGION: { - DEFAULT: 'default', - NA: 'NA', - EU: 'EU', - FE: 'FE' - }, - LANGUAGES: { - 'en-AU': 'en-AU', - 'de-DE': 'de-DE', - 'en-CA': 'en-CA', - 'en-GB': 'en-GB', - 'en-IN': 'en-IN', - 'en-US': 'en-US', - 'es-ES': 'es-ES', - 'es-MX': 'es-MX', - 'es-US': 'es-US', - 'fr-CA': 'fr-CA', - 'fr-FR': 'fr-FR', - 'hi-IN': 'hi-IN', - 'it-IT': 'it-IT', - 'ja-JP': 'ja-JP', - 'pt-BR': 'pt-BR' - } + REGION: { + DEFAULT: "default", + NA: "NA", + EU: "EU", + FE: "FE", + }, + LANGUAGES: { + "en-AU": "en-AU", + "de-DE": "de-DE", + "en-CA": "en-CA", + "en-GB": "en-GB", + "en-IN": "en-IN", + "en-US": "en-US", + "es-ES": "es-ES", + "es-MX": "es-MX", + "es-US": "es-US", + "fr-CA": "fr-CA", + "fr-FR": "fr-FR", + "hi-IN": "hi-IN", + "it-IT": "it-IT", + "ja-JP": "ja-JP", + "pt-BR": "pt-BR", + }, }; module.exports.AWS = { - IAM: { - USER: { - NEW_USER_BASE_URL: 'https://console.aws.amazon.com/iam/home?region=undefined#/users$new?', - POLICY_ARN: { - IAM_FULL: 'arn:aws:iam::aws:policy/IAMFullAccess', - CFN_FULL: 'arn:aws:iam::aws:policy/AWSCloudFormationFullAccess', - S3_FULL: 'arn:aws:iam::aws:policy/AmazonS3FullAccess', - LAMBDA_FULL: 'arn:aws:iam::aws:policy/AWSLambda_FullAccess', - CLOUD_WATCH_FULL: 'arn:aws:iam::aws:policy/CloudWatchLogsFullAccess' - } + IAM: { + USER: { + NEW_USER_BASE_URL: "https://console.aws.amazon.com/iam/home?region=undefined#/users$new?", + POLICY_ARN: { + IAM_FULL: "arn:aws:iam::aws:policy/IAMFullAccess", + CFN_FULL: "arn:aws:iam::aws:policy/AWSCloudFormationFullAccess", + S3_FULL: "arn:aws:iam::aws:policy/AmazonS3FullAccess", + LAMBDA_FULL: "arn:aws:iam::aws:policy/AWSLambda_FullAccess", + CLOUD_WATCH_FULL: "arn:aws:iam::aws:policy/CloudWatchLogsFullAccess", + }, + }, + ROLE: { + LAMBDA_BASIC_ROLE: { + POLICY_ARN: "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole", + POLICY: { + Version: "2012-10-17", + Statement: [ + { + Effect: "Allow", + Principal: { + Service: "lambda.amazonaws.com", + }, + Action: "sts:AssumeRole", + }, + ], }, - ROLE: { - LAMBDA_BASIC_ROLE: { - POLICY_ARN: 'arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole', - POLICY: { - Version: '2012-10-17', - Statement: [ - { - Effect: 'Allow', - Principal: { - Service: 'lambda.amazonaws.com' - }, - Action: 'sts:AssumeRole' - } - ] - } - } - } - } + }, + }, + }, }; module.exports.LAMBDA = { - DEFAULT_CONFIG: { - // default values to account for Java runtime cold start - MEMORY_SIZE: 512, - TIMEOUT: 15 - }, - FUNCTION_STATE: { - ACTIVE: 'Active', - INACTIVE: 'Inactive', - PENDING: 'Pending', - FAILED: 'Failed' - }, - LAST_UPDATE_STATUS: { - SUCCESSFUL: 'Successful', - FAILED: 'Failed', - IN_PROGRESS: 'InProgress' - } + DEFAULT_CONFIG: { + // default values to account for Java runtime cold start + MEMORY_SIZE: 512, + TIMEOUT: 15, + }, + FUNCTION_STATE: { + ACTIVE: "Active", + INACTIVE: "Inactive", + PENDING: "Pending", + FAILED: "Failed", + }, + LAST_UPDATE_STATUS: { + SUCCESSFUL: "Successful", + FAILED: "Failed", + IN_PROGRESS: "InProgress", + }, }; module.exports.PLACEHOLDER = { - ENVIRONMENT_VAR: { - AWS_CREDENTIALS: '__AWS_CREDENTIALS_IN_ENVIRONMENT_VARIABLE__', - PROFILE_NAME: '__ENVIRONMENT_ASK_PROFILE__' - } + ENVIRONMENT_VAR: { + AWS_CREDENTIALS: "__AWS_CREDENTIALS_IN_ENVIRONMENT_VARIABLE__", + PROFILE_NAME: "__ENVIRONMENT_ASK_PROFILE__", + }, }; module.exports.SMAPI = { - ENDPOINT: 'https://api.amazonalexa.com', - VERSION: { - V0: 'v0', - V1: 'v1', - V2: 'v2' - }, - API_NAME: { - // Skill - CREATE_SKILL: 'create-skill', - DELETE_SKILL: 'delete-skill', - LIST_SKILLS: 'list-skills', - GET_SKILL_STATUS: 'get-skill-status', - SUBMIT: 'submit', - WITHDRAW: 'withdraw', - ENABLE_SKILL: 'enable-skill', - DISABLE_SKILL: 'disable-skill', - GET_SKILL_ENABLEMENT: 'get-skill-enablement', - GET_SKILL_CREDENTIALS: 'get-skill-credentials', - LIST_VENDORS: 'list-vendors', - GET_METRICS: 'get-metrics', - // Evaluations - NLU_PROFILE: 'nlu-profile', - // Utterance transcripts - INTENT_REQUEST_HISTORY: 'intent-requests-history', - LIST_CERTIFICATIONS: 'list-certifications', - GET_CERTIFICATION: 'get-certification', - // Manifest - GET_MANIFEST: 'get-manifest', - UPDATE_MANIFEST: 'update-manifest', - // Model - GET_INTERACTION_MODEL: 'get-interaction-model', - SET_INTERACTION_MODEL: 'set-interaction-model', - HEAD_INTERACTION_MODEL: 'head-interaction-model', - GET_UTTERANCE_DATA: 'get-utterance-data', - LIST_INTERACTION_MODEL_VERSIONS: 'list-interaction-model-versions', - // ISP - CREATE_ISP: 'create-isp', - GET_ISP: 'get-isp', - UPDATE_ISP: 'update-isp', - ASSOCIATE_ISP: 'associate-isp', - DISASSOCIATE_ISP: 'disassociate-isp', - LIST_ISP_FOR_SKILL: 'list-isp-for-skill', - LIST_ISP_FOR_VENDOR: 'list-isp-for-vendor', - LIST_SKILLS_FOR_ISP: 'list-skills-for-isp', - DELETE_ISP: 'delete-isp', - RESET_ISP_ENTITLEMENT: 'reset-isp-entitlement', - // Skill Package - CREATE_UPLOAD: 'create-upload', - IMPORT_PACKAGE: 'import-package', - GET_IMPORT_STATUS: 'get-import-status', - EXPORT_PACKAGE: 'export-package', - GET_EXPORT_STATUS: 'get-export-status', - // Account Linking - SET_ACCOUNT_LINKING: 'set-account-linking', - GET_ACCOUNT_LINKING: 'get-account-linking', - DELETE_ACCOUNT_LINKING: 'delete-account-linking', - // Testing - SIMULATE_SKILL: 'simulate-skill', - INVOKE_SKILL: 'invoke-skill', - GET_SIMULATION: 'get-simulation', - VALIDATE_SKILL: 'validate-skill', - GET_VALIDATION: 'get-validation', - // Beta Test - CREATE_BETA_TEST: 'create-beta-test', - UPDATE_BETA_TEST: 'update-beta-test', - GET_BETA_TEST: 'get-beta-test', - START_BETA_TEST: 'start-beta-test', - END_BETA_TEST: 'end-beta-test', - LIST_BETA_TESTERS: 'list-beta-testers', - ADD_BETA_TESTERS: 'add-beta-testers', - REMOVE_BETA_TESTERS: 'remove-beta-testers', - SEND_REMINDER_TO_BETA_TESTERS: 'send-reminder-to-beta-testers', - REQUEST_FEEDBACK_FROM_BETA_TESTERS: 'request-feedback-from-beta-testers', - // Private Skill - ADD_PRIVATE_DISTRIBUTION_ACCOUNT: 'add-private-distribution-account', - LIST_PRIVATE_DISTRIBUTION_ACCOUNTS: 'list-private-distribution-accounts', - DELETE_PRIVATE_DISTRIBUTION_ACCOUNT: 'delete-private-distribution-account', - // Catalog - CREATE_CATALOG: 'create-catalog', - GET_CATALOG: 'get-catalog', - LIST_CATALOGS: 'list-catalogs', - UPLOAD_CATALOG: 'create-catalog-upload', - GET_CATALOG_UPLOAD: 'get-catalog-upload', - LIST_CATALOG_UPLOADS: 'list-catalog-uploads', - ASSOCIATE_CATALOG_WITH_SKILL: 'associate-catalog-with-skill', - COMPLET_CATALOG_UPLOAD: 'complete-catalog-upload', - // Hosted Skills - CREATE_HOSTED_SKILL: 'create-alexa-hosted-skill', - GET_HOSTED_SKILLS_META_DATA: 'get-alexa-hosted-skill', - GET_GIT_CREDENTIALS: 'get-git-credentials', - GET_HOSTED_SKILLS_PERMISSION: 'get-alexa-hosted-skill-permission', - // Task - GET_TASK: 'get-task', - SEARCH_TASK: 'search-task' - }, - DEFAULT_MAX_RESULT_PER_PAGE: 50 + ENDPOINT: "https://api.amazonalexa.com", + VERSION: { + V0: "v0", + V1: "v1", + V2: "v2", + }, + API_NAME: { + // Skill + CREATE_SKILL: "create-skill", + DELETE_SKILL: "delete-skill", + LIST_SKILLS: "list-skills", + GET_SKILL_STATUS: "get-skill-status", + SUBMIT: "submit", + WITHDRAW: "withdraw", + ENABLE_SKILL: "enable-skill", + DISABLE_SKILL: "disable-skill", + GET_SKILL_ENABLEMENT: "get-skill-enablement", + GET_SKILL_CREDENTIALS: "get-skill-credentials", + LIST_VENDORS: "list-vendors", + GET_METRICS: "get-metrics", + // Evaluations + NLU_PROFILE: "nlu-profile", + // Utterance transcripts + INTENT_REQUEST_HISTORY: "intent-requests-history", + LIST_CERTIFICATIONS: "list-certifications", + GET_CERTIFICATION: "get-certification", + // Manifest + GET_MANIFEST: "get-manifest", + UPDATE_MANIFEST: "update-manifest", + // Model + GET_INTERACTION_MODEL: "get-interaction-model", + SET_INTERACTION_MODEL: "set-interaction-model", + HEAD_INTERACTION_MODEL: "head-interaction-model", + GET_UTTERANCE_DATA: "get-utterance-data", + LIST_INTERACTION_MODEL_VERSIONS: "list-interaction-model-versions", + // ISP + CREATE_ISP: "create-isp", + GET_ISP: "get-isp", + UPDATE_ISP: "update-isp", + ASSOCIATE_ISP: "associate-isp", + DISASSOCIATE_ISP: "disassociate-isp", + LIST_ISP_FOR_SKILL: "list-isp-for-skill", + LIST_ISP_FOR_VENDOR: "list-isp-for-vendor", + LIST_SKILLS_FOR_ISP: "list-skills-for-isp", + DELETE_ISP: "delete-isp", + RESET_ISP_ENTITLEMENT: "reset-isp-entitlement", + // Skill Package + CREATE_UPLOAD: "create-upload", + IMPORT_PACKAGE: "import-package", + GET_IMPORT_STATUS: "get-import-status", + EXPORT_PACKAGE: "export-package", + GET_EXPORT_STATUS: "get-export-status", + // Account Linking + SET_ACCOUNT_LINKING: "set-account-linking", + GET_ACCOUNT_LINKING: "get-account-linking", + DELETE_ACCOUNT_LINKING: "delete-account-linking", + // Testing + SIMULATE_SKILL: "simulate-skill", + INVOKE_SKILL: "invoke-skill", + GET_SIMULATION: "get-simulation", + MODIFY_LAST_TURN: "modify-last-turn", + VALIDATE_SKILL: "validate-skill", + GET_VALIDATION: "get-validation", + // Beta Test + CREATE_BETA_TEST: "create-beta-test", + UPDATE_BETA_TEST: "update-beta-test", + GET_BETA_TEST: "get-beta-test", + START_BETA_TEST: "start-beta-test", + END_BETA_TEST: "end-beta-test", + LIST_BETA_TESTERS: "list-beta-testers", + ADD_BETA_TESTERS: "add-beta-testers", + REMOVE_BETA_TESTERS: "remove-beta-testers", + SEND_REMINDER_TO_BETA_TESTERS: "send-reminder-to-beta-testers", + REQUEST_FEEDBACK_FROM_BETA_TESTERS: "request-feedback-from-beta-testers", + // Private Skill + ADD_PRIVATE_DISTRIBUTION_ACCOUNT: "add-private-distribution-account", + LIST_PRIVATE_DISTRIBUTION_ACCOUNTS: "list-private-distribution-accounts", + DELETE_PRIVATE_DISTRIBUTION_ACCOUNT: "delete-private-distribution-account", + // Catalog + CREATE_CATALOG: "create-catalog", + GET_CATALOG: "get-catalog", + LIST_CATALOGS: "list-catalogs", + UPLOAD_CATALOG: "create-catalog-upload", + GET_CATALOG_UPLOAD: "get-catalog-upload", + LIST_CATALOG_UPLOADS: "list-catalog-uploads", + ASSOCIATE_CATALOG_WITH_SKILL: "associate-catalog-with-skill", + COMPLET_CATALOG_UPLOAD: "complete-catalog-upload", + // Hosted Skills + CREATE_HOSTED_SKILL: "create-alexa-hosted-skill", + GET_HOSTED_SKILLS_META_DATA: "get-alexa-hosted-skill", + GET_GIT_CREDENTIALS: "get-git-credentials", + GET_HOSTED_SKILLS_PERMISSION: "get-alexa-hosted-skill-permission", + // Task + GET_TASK: "get-task", + SEARCH_TASK: "search-task", + }, + DEFAULT_MAX_RESULT_PER_PAGE: 50, }; module.exports.HTTP_REQUEST = { - VERB: { - GET: 'GET', - PUT: 'PUT', - POST: 'POST', - DELETE: 'DELETE', - HEAD: 'HEAD' - }, - STATUS_CODE: { - OK: 200, - ACCEPTED: 202, - NO_CONTENT: 204, - SEE_OTHER: 303, - BAD_REQUEST: 400, - UNAUTHORIZED: 401, - FORBIDDEN: 403, - NOT_FOUND: 404, - PRECONDITION_FAILED: 412, - TOO_MANY_REQUESTS: 429, - INTERNAL_SERVER_ERROR: 500 - } + VERB: { + GET: "GET", + PUT: "PUT", + POST: "POST", + DELETE: "DELETE", + HEAD: "HEAD", + }, + STATUS_CODE: { + OK: 200, + ACCEPTED: 202, + NO_CONTENT: 204, + SEE_OTHER: 303, + BAD_REQUEST: 400, + UNAUTHORIZED: 401, + FORBIDDEN: 403, + NOT_FOUND: 404, + PRECONDITION_FAILED: 412, + TOO_MANY_REQUESTS: 429, + INTERNAL_SERVER_ERROR: 500, + }, }; -const SCOPES_SKILLS_READWRITE = 'alexa::ask:skills:readwrite'; -const SCOPES_MODELS_READWRITE = 'alexa::ask:models:readwrite'; -const SCOPES_SKILLS_TEST = 'alexa::ask:skills:test'; -const SCOPES_CATALOG_READ = 'alexa::ask:catalogs:read'; -const SCOPES_CATALOG_READWRITE = 'alexa::ask:catalogs:readwrite'; -const SCOPES_SUBSCRIPTIONS = 'alexa::ask:subscriptions'; -const SCOPES_SKILLS_DEBUG = 'alexa::ask:skills:debug'; +const SCOPES_SKILLS_READWRITE = "alexa::ask:skills:readwrite"; +const SCOPES_MODELS_READWRITE = "alexa::ask:models:readwrite"; +const SCOPES_SKILLS_TEST = "alexa::ask:skills:test"; +const SCOPES_CATALOG_READ = "alexa::ask:catalogs:read"; +const SCOPES_CATALOG_READWRITE = "alexa::ask:catalogs:readwrite"; +const SCOPES_SUBSCRIPTIONS = "alexa::ask:subscriptions"; +const SCOPES_SKILLS_DEBUG = "alexa::ask:skills:debug"; -const DEFAULT_PUBLIC_SCOPES = `${SCOPES_SKILLS_READWRITE} ${SCOPES_MODELS_READWRITE} ${SCOPES_SKILLS_TEST} ${SCOPES_CATALOG_READ}` - + ` ${SCOPES_CATALOG_READWRITE} ${SCOPES_SUBSCRIPTIONS}`; +const DEFAULT_PUBLIC_SCOPES = + `${SCOPES_SKILLS_READWRITE} ${SCOPES_MODELS_READWRITE} ${SCOPES_SKILLS_TEST} ${SCOPES_CATALOG_READ}` + + ` ${SCOPES_CATALOG_READWRITE} ${SCOPES_SUBSCRIPTIONS}`; module.exports.LWA = { - S3_RESPONSE_PARSER_URL: 'https://ask-cli-static-content.s3-us-west-2.amazonaws.com/html/ask-cli-no-browser.html', - DEFAULT_STATE: 'Ask-SkillModel-ReadWrite', - DEFAULT_PUBLIC_SCOPES, - DEFAULT_SCOPES: `${DEFAULT_PUBLIC_SCOPES} ${SCOPES_SKILLS_DEBUG}`, - SIGNIN_URL: 'https://www.amazon.com/ap/signin', - // Below are the details for the ask-cli's default LWA client which is used internally if another client is not provided by the users. - // Use of this client outside of the CLI is unauthorized and unsupported by Amazon. - // To create an LWA client for other use, please follow the documentation at https://developer.amazon.com/docs/login-with-amazon/register-web.html - CLI_INTERNAL_ONLY_LWA_CLIENT: { - CLIENT_ID: 'amzn1.application-oa2-client.aad322b5faab44b980c8f87f94fbac56', - CLIENT_CONFIRMATION: '1642d8869b829dda3311d6c6539f3ead55192e3fc767b9071c888e60ef151cf9' - }, - DEFAULT_AUTHORIZE_HOST: 'https://www.amazon.com', - DEFAULT_AUTHORIZE_PATH: '/ap/oa', - DEFAULT_TOKEN_HOST: 'https://api.amazon.com', - DEFAULT_TOKEN_PATH: '/auth/o2/token', - LOCAL_PORT: 9090 + S3_RESPONSE_PARSER_URL: "https://ask-cli-static-content.s3-us-west-2.amazonaws.com/html/ask-cli-no-browser.html", + DEFAULT_STATE: "Ask-SkillModel-ReadWrite", + DEFAULT_PUBLIC_SCOPES, + DEFAULT_SCOPES: `${DEFAULT_PUBLIC_SCOPES} ${SCOPES_SKILLS_DEBUG}`, + SIGNIN_URL: "https://www.amazon.com/ap/signin", + // Below are the details for the ask-cli's default LWA client which is used internally if another client is not provided by the users. + // Use of this client outside of the CLI is unauthorized and unsupported by Amazon. + // To create an LWA client for other use, please follow the documentation at https://developer.amazon.com/docs/login-with-amazon/register-web.html + CLI_INTERNAL_ONLY_LWA_CLIENT: { + CLIENT_ID: "amzn1.application-oa2-client.aad322b5faab44b980c8f87f94fbac56", + CLIENT_CONFIRMATION: "1642d8869b829dda3311d6c6539f3ead55192e3fc767b9071c888e60ef151cf9", + }, + DEFAULT_AUTHORIZE_HOST: "https://www.amazon.com", + DEFAULT_AUTHORIZE_PATH: "/ap/oa", + DEFAULT_TOKEN_HOST: "https://api.amazon.com", + DEFAULT_TOKEN_PATH: "/auth/o2/token", + LOCAL_PORT: 9090, }; module.exports.REGEX_VALIDATIONS = { - PROFILE_NAME: /(^[a-zA-Z0-9-_]+$)(?!__ENVIRONMENT_ASK_PROFILE__)/g + PROFILE_NAME: /(^[a-zA-Z0-9-_]+$)(?!__ENVIRONMENT_ASK_PROFILE__)/g, }; -module.exports.ASK_DEFAULT_PROFILE_NAME = 'default'; -module.exports.AWS_DEFAULT_PROFILE_NAME = 'ask_cli_default'; -module.exports.LOCALHOST_PORT = '9090'; +module.exports.ASK_DEFAULT_PROFILE_NAME = "default"; +module.exports.AWS_DEFAULT_PROFILE_NAME = "ask_cli_default"; +module.exports.LOCALHOST_PORT = "9090"; module.exports.FILE_PERMISSION = { - USER_READ_WRITE: '0600' + USER_READ_WRITE: "0600", }; module.exports.RUN = { - DEFAULT_DEBUG_PORT: '5000', - NODE: { - SCRIPT_LOCATION: path.join('node_modules', 'ask-sdk-local-debug', 'dist', 'LocalDebuggerInvoker.js') - }, - PYTHON: { - SCRIPT_LOCATION: path.join('ask_sdk_local_debug', 'local_debugger_invoker.py') - } + DEFAULT_DEBUG_PORT: "5000", + NODE: { + SCRIPT_LOCATION: path.join("node_modules", "ask-sdk-local-debug", "dist", "LocalDebuggerInvoker.js"), + }, + PYTHON: { + SCRIPT_LOCATION: path.join("ask_sdk_local_debug", "local_debugger_invoker.py"), + }, }; module.exports.RUNTIME = { - NODE: 'node', - PYTHON: 'python', - JAVA: 'java' + NODE: "node", + PYTHON: "python", + JAVA: "java", }; -module.exports.GIT_USAGE_HOSTED_SKILL_DOCUMENTATION = 'https://developer.amazon.com/en-US/docs/alexa/hosted-skills/alexa-hosted-skills-ask-cli.html'; +module.exports.COMPILER = { + ASK_COMPILER: "ask-compiler", + ASK_DECOMPILER: "ask-decompiler", + ACDL_PATH: "conversations", + TARGETDIR: "skill-package", + MANIFEST: "skill.json", +}; + +module.exports.DEPLOYMENT_TYPE = { + ALEXA_CONVERSATIONS: "alexa-conversations", + INTERACTION_MODEL: "interaction-model", +}; + +module.exports.TEN_MEGA_BYTES = 1000 * 1000 * 10; + +module.exports.GIT_USAGE_HOSTED_SKILL_DOCUMENTATION = + "https://developer.amazon.com/en-US/docs/alexa/hosted-skills/alexa-hosted-skills-ask-cli.html"; + +module.exports.ACDL_BETA_MESSAGE = + "Alexa Conversations Description Language is currently in beta and may have breaking changes before it reaches General Availability. Please report any bugs or issues on GitHub: https://github.com/alexa/ask-cli/issues"; diff --git a/lib/utils/dynamic-config.js b/lib/utils/dynamic-config.js index 3f48aed3..81203a08 100644 --- a/lib/utils/dynamic-config.js +++ b/lib/utils/dynamic-config.js @@ -1,56 +1,56 @@ -const os = require('os'); +const os = require("os"); -const CONSTANTS = require('@src/utils/constants'); -const pkg = require('@root/package.json'); -const stringUtils = require('@src/utils/string-utils'); +const CONSTANTS = require("./constants"); +const pkg = require("../../package.json"); +const stringUtils = require("./string-utils"); function resolve(chain) { - for (const item of chain) { - if (stringUtils.isNonBlankString(item) && item !== 'undefined') { - return item; - } + for (const item of chain) { + if (stringUtils.isNonBlankString(item) && item !== "undefined") { + return item; } - return null; + } + return null; } class DynamicConfig { - static get lwaClientId() { - return resolve([process.env.ASK_LWA_CLIENT_ID, CONSTANTS.LWA.CLI_INTERNAL_ONLY_LWA_CLIENT.CLIENT_ID]); - } - - static get lwaClientConfirmation() { - return resolve([process.env.ASK_LWA_CLIENT_CONFIRMATION, CONSTANTS.LWA.CLI_INTERNAL_ONLY_LWA_CLIENT.CLIENT_CONFIRMATION]); - } - - static get lwaAuthorizationHost() { - return resolve([process.env.ASK_LWA_AUTHORIZE_HOST, CONSTANTS.LWA.DEFAULT_AUTHORIZE_HOST]); - } - - static get lwaTokenHost() { - return resolve([process.env.ASK_LWA_TOKEN_HOST, CONSTANTS.LWA.DEFAULT_TOKEN_HOST]); - } - - static get smapiBaseUrl() { - return resolve([process.env.ASK_SMAPI_SERVER_BASE_URL, CONSTANTS.SMAPI.ENDPOINT]); - } - - static get s3Scripts() { - const baseUrl = resolve([process.env.ASK_S3_SCRIPTS_BASE_URL, 'https://ask-tools-core-content.s3-us-west-2.amazonaws.com']); - return { - authInfo: `${baseUrl}/auth_info`, - prePush: `${baseUrl}/git-hooks-templates/pre-push/pre-push`, - askPrePush: `${baseUrl}/git-hooks-templates/pre-push/ask-pre-push`, - gitCredentialHelper: `${baseUrl}/helpers/prod/git-credential-helper`, - }; - } - - static get userAgent() { - const cliUserAgentStr = `ask-cli/${pkg.version} Node/${process.version} ${os.type()}/${os.release()}`; - if (stringUtils.isNonBlankString(process.env.ASK_DOWNSTREAM_CLIENT)) { - return `${process.env.ASK_DOWNSTREAM_CLIENT} (ask-cli downstream client) ${cliUserAgentStr}`; - } - return cliUserAgentStr; - } + static get lwaClientId() { + return resolve([process.env.ASK_LWA_CLIENT_ID, CONSTANTS.LWA.CLI_INTERNAL_ONLY_LWA_CLIENT.CLIENT_ID]); + } + + static get lwaClientConfirmation() { + return resolve([process.env.ASK_LWA_CLIENT_CONFIRMATION, CONSTANTS.LWA.CLI_INTERNAL_ONLY_LWA_CLIENT.CLIENT_CONFIRMATION]); + } + + static get lwaAuthorizationHost() { + return resolve([process.env.ASK_LWA_AUTHORIZE_HOST, CONSTANTS.LWA.DEFAULT_AUTHORIZE_HOST]); + } + + static get lwaTokenHost() { + return resolve([process.env.ASK_LWA_TOKEN_HOST, CONSTANTS.LWA.DEFAULT_TOKEN_HOST]); + } + + static get smapiBaseUrl() { + return resolve([process.env.ASK_SMAPI_SERVER_BASE_URL, CONSTANTS.SMAPI.ENDPOINT]); + } + + static get s3Scripts() { + const baseUrl = resolve([process.env.ASK_S3_SCRIPTS_BASE_URL, "https://ask-tools-core-content.s3-us-west-2.amazonaws.com"]); + return { + authInfo: `${baseUrl}/auth_info`, + prePush: `${baseUrl}/git-hooks-templates/pre-push/pre-push`, + askPrePush: `${baseUrl}/git-hooks-templates/pre-push/ask-pre-push`, + gitCredentialHelper: `${baseUrl}/helpers/prod/git-credential-helper`, + }; + } + + static get userAgent() { + const cliUserAgentStr = `ask-cli/${pkg.version} Node/${process.version} ${os.type()}/${os.release()}`; + if (stringUtils.isNonBlankString(process.env.ASK_DOWNSTREAM_CLIENT)) { + return `${process.env.ASK_DOWNSTREAM_CLIENT} (ask-cli downstream client) ${cliUserAgentStr}`; + } + return cliUserAgentStr; + } } module.exports = DynamicConfig; diff --git a/lib/utils/hash-utils.js b/lib/utils/hash-utils.js index 233a0d10..8686a70f 100644 --- a/lib/utils/hash-utils.js +++ b/lib/utils/hash-utils.js @@ -1,10 +1,10 @@ -const crypto = require('crypto'); -const folderHash = require('folder-hash'); -const fs = require('fs'); +const crypto = require("crypto"); +const folderHash = require("folder-hash"); +const fs = require("fs"); module.exports = { - getHash, - getFileHash + getHash, + getFileHash, }; /** @@ -13,25 +13,25 @@ module.exports = { * @param {*} callback { error, hashCode } */ function getHash(sourcePath, callback) { - const options = { - algo: 'sha1', - encoding: 'base64', - folders: { - exclude: ['.*', 'node_modules', 'test_coverage', 'dist', 'build'], - ignoreRootName: true - }, - }; + const options = { + algo: "sha1", + encoding: "base64", + folders: { + exclude: [".*", "node_modules", "test_coverage", "dist", "build"], + ignoreRootName: true, + }, + }; - folderHash.hashElement(sourcePath, options, (error, result) => { - callback(error, error ? null : result.hash); - }); + folderHash.hashElement(sourcePath, options, (error, result) => { + callback(error, error ? null : result.hash); + }); } /** * Returns hash of a file * @param{String} filePath */ function getFileHash(filePath) { - const sum = crypto.createHash('sha256'); - sum.update(fs.readFileSync(filePath)); - return sum.digest('hex'); + const sum = crypto.createHash("sha256"); + sum.update(fs.readFileSync(filePath)); + return sum.digest("hex"); } diff --git a/lib/utils/local-host-server.js b/lib/utils/local-host-server.js index 8811b475..8ecdb7b4 100644 --- a/lib/utils/local-host-server.js +++ b/lib/utils/local-host-server.js @@ -1,25 +1,25 @@ -const http = require('http'); +const http = require("http"); module.exports = class LocalHostServer { - constructor(PORT) { - this.port = PORT; - this.server = null; - } + constructor(PORT) { + this.port = PORT; + this.server = null; + } - create(requestHandler) { - this.server = http.createServer(requestHandler); - } + create(requestHandler) { + this.server = http.createServer(requestHandler); + } - listen(callback) { - this.server.listen(this.port, callback); - } + listen(callback) { + this.server.listen(this.port, callback); + } - registerEvent(eventName, callback) { - this.server.on(eventName, callback); - } + registerEvent(eventName, callback) { + this.server.on(eventName, callback); + } - destroy() { - this.server.close(); - this.server.unref(); - } + destroy() { + this.server.close(); + this.server.unref(); + } }; diff --git a/lib/utils/logger-utility.js b/lib/utils/logger-utility.js index b1a728cf..f521475a 100644 --- a/lib/utils/logger-utility.js +++ b/lib/utils/logger-utility.js @@ -1,109 +1,106 @@ -'use strict'; +"use strict"; -const bunyan = require('bunyan'); +const bunyan = require("bunyan"); const LEVEL_MAPPING = { - 10: 'TRACE', - 20: 'DEBUG', - 30: 'INFO', - 40: 'WARN', - 50: 'ERROR', - 60: 'FATAL' + 10: "TRACE", + 20: "DEBUG", + 30: "INFO", + 40: "WARN", + 50: "ERROR", + 60: "FATAL", }; - /* * Singleton for Logger utility. Will only init once throughout the application */ module.exports = (function () { + // Instance stores a reference to the Logger + let instance; - // Instance stores a reference to the Logger - let instance; - - let logBuffer = []; - - function init() { + let logBuffer = []; - function displayLogs () { - console.warn('\n\n-------------------- Debug Mode --------------------'); + function init() { + function displayLogs() { + console.warn("\n\n-------------------- Debug Mode --------------------"); - for (let item of logBuffer) { - // display separators for each item before-hand except the first time - if (item !== logBuffer[0]) { - console.warn('----------------------------------------'); - } - item = JSON.parse(item); - - console.warn('[' + item.time + '] - ' + LEVEL_MAPPING[item.level] + ' - ' + item.activity.toUpperCase()); - if (item['request-id']) { - console.warn('request-id: ' + item['request-id']); - } - console.warn(item.request.method + ' ' + item.request.url); - console.warn('status code: ' + item.response.statusCode + ' ' + item.response.statusMessage); - if (item.error) { - console.warn('error: ' + item.error); - } - console.warn('\nRequest headers: ' + JSON.stringify(item.request.headers)); - if (item.request.body) { - console.warn('\nRequest body: ' + item.request.body); - } - console.warn('\nResponse headers: ' + JSON.stringify(item.response.headers)); - if (item.body) { - console.warn('\nResponse body: ' + JSON.stringify(item.body)); - } - } - console.warn(); + for (let item of logBuffer) { + // display separators for each item before-hand except the first time + if (item !== logBuffer[0]) { + console.warn("----------------------------------------"); } + item = JSON.parse(item); - let logger = bunyan.createLogger({ - name: 'logger', - type: 'raw', - stream: new CaptureStream(logBuffer), - level: 'debug' - }); - - process.on('exit', () => { - displayLogs(); - }); + console.warn("[" + item.time + "] - " + LEVEL_MAPPING[item.level] + " - " + item.activity.toUpperCase()); + if (item["request-id"]) { + console.warn("request-id: " + item["request-id"]); + } + console.warn(item.request.method + " " + item.request.url); + console.warn("status code: " + item.response.statusCode + " " + item.response.statusMessage); + if (item.error) { + console.warn("error: " + item.error); + } + console.warn("\nRequest headers: " + JSON.stringify(item.request.headers)); + if (item.request.body) { + console.warn("\nRequest body: " + item.request.body); + } + console.warn("\nResponse headers: " + JSON.stringify(item.response.headers)); + if (item.body) { + console.warn("\nResponse body: " + JSON.stringify(item.body)); + } + } + console.warn(); + } - // ctrl-c interrupt - process.on('SIGINT', () => { - process.exit(1); - }); + let logger = bunyan.createLogger({ + name: "logger", + type: "raw", + stream: new CaptureStream(logBuffer), + level: "debug", + }); - return { - /* - * Record debug content - * @params debugContent - */ - debug: (debugContent) => { - logger.debug(debugContent); - }, + process.on("exit", () => { + displayLogs(); + }); - /* - * Display prettified logs to console - */ - display: displayLogs - }; - } + // ctrl-c interrupt + process.on("SIGINT", () => { + process.exit(1); + }); return { - getInstance: function () { - if (!instance) { - instance = init(); - } - return instance; - } + /* + * Record debug content + * @params debugContent + */ + debug: (debugContent) => { + logger.debug(debugContent); + }, + + /* + * Display prettified logs to console + */ + display: displayLogs, }; + } + + return { + getInstance: function () { + if (!instance) { + instance = init(); + } + return instance; + }, + }; })(); /* * Inner class to rewrite the behaviour of bunyan stream */ function CaptureStream(buffer) { - this.buffer = buffer; + this.buffer = buffer; } -CaptureStream.prototype.write = function(info) { - this.buffer.push(info); +CaptureStream.prototype.write = function (info) { + this.buffer.push(info); }; diff --git a/lib/utils/metrics.js b/lib/utils/metrics.js index 6ba42df3..e4b74c55 100644 --- a/lib/utils/metrics.js +++ b/lib/utils/metrics.js @@ -1,4 +1,4 @@ -const { MetricClient } = require('@src/clients/metric-client'); +const {MetricClient} = require("../clients/metric-client"); // metric client singleton const metricClient = new MetricClient(); diff --git a/lib/utils/profile-helper.js b/lib/utils/profile-helper.js index 0bb817f7..a7e2c6f5 100644 --- a/lib/utils/profile-helper.js +++ b/lib/utils/profile-helper.js @@ -1,66 +1,69 @@ -const R = require('ramda'); -const fs = require('fs-extra'); -const os = require('os'); -const path = require('path'); +const R = require("ramda"); +const fs = require("fs-extra"); +const os = require("os"); +const path = require("path"); -const CONSTANT = require('./constants'); +const CONSTANT = require("./constants"); module.exports = { - runtimeProfile, - isEnvProfile, - checkASKProfileExist, - setupProfile, - resolveVendorId + runtimeProfile, + isEnvProfile, + checkASKProfileExist, + setupProfile, + resolveVendorId, }; function runtimeProfile(profile) { - const askProfile = profile || _findEnvProfile() || process.env.ASK_DEFAULT_PROFILE || 'default'; - if (!module.exports.checkASKProfileExist(askProfile)) { - throw (`Can't resolve profile [${askProfile}] as it doesn't exist. Please run "ask configure --profile ${askProfile}" first.`); - } - return askProfile; + const askProfile = profile || _findEnvProfile() || process.env.ASK_DEFAULT_PROFILE || "default"; + if (!module.exports.checkASKProfileExist(askProfile)) { + throw `Can't resolve profile [${askProfile}] as it doesn't exist. Please run "ask configure --profile ${askProfile}" first.`; + } + return askProfile; } function isEnvProfile() { - return !!((process.env.AWS_ACCESS_KEY_ID && process.env.AWS_SECRET_ACCESS_KEY) - && (process.env.ASK_REFRESH_TOKEN || process.env.ASK_ACCESS_TOKEN) - && process.env.ASK_VENDOR_ID); + return !!( + process.env.AWS_ACCESS_KEY_ID && + process.env.AWS_SECRET_ACCESS_KEY && + (process.env.ASK_REFRESH_TOKEN || process.env.ASK_ACCESS_TOKEN) && + process.env.ASK_VENDOR_ID + ); } function _findEnvProfile() { - if (isEnvProfile()) { - // Only when user set every required parameter in ENV, we will treat profile as ENV - return CONSTANT.PLACEHOLDER.ENVIRONMENT_VAR.PROFILE_NAME; - } - return null; + if (isEnvProfile()) { + // Only when user set every required parameter in ENV, we will treat profile as ENV + return CONSTANT.PLACEHOLDER.ENVIRONMENT_VAR.PROFILE_NAME; + } + return null; } function checkASKProfileExist(profileName) { - if (profileName === CONSTANT.PLACEHOLDER.ENVIRONMENT_VAR.PROFILE_NAME) { - return true; - } - const askCliConfig = path.join(os.homedir(), '.ask', 'cli_config'); - const askProfile = JSON.parse(fs.readFileSync(askCliConfig, 'utf-8')); - return Object.prototype.hasOwnProperty.call(askProfile.profiles, profileName); + if (profileName === CONSTANT.PLACEHOLDER.ENVIRONMENT_VAR.PROFILE_NAME) { + return true; + } + const askCliConfig = path.join(os.homedir(), ".ask", "cli_config"); + const askProfile = JSON.parse(fs.readFileSync(askCliConfig, "utf-8")); + return Object.prototype.hasOwnProperty.call(askProfile.profiles, profileName); } function setupProfile(awsProfile, askProfile) { - const homeConfigPath = path.join(os.homedir(), '.ask', 'cli_config'); - const homeConfig = fs.readJSONSync(homeConfigPath); - const updatedConfig = R.set(R.lensPath(['profiles', askProfile, 'aws_profile']), awsProfile, homeConfig); - fs.writeJSONSync(homeConfigPath, updatedConfig); + const homeConfigPath = path.join(os.homedir(), ".ask", "cli_config"); + const homeConfig = fs.readJSONSync(homeConfigPath); + const updatedConfig = R.set(R.lensPath(["profiles", askProfile, "aws_profile"]), awsProfile, homeConfig); + fs.writeJSONSync(homeConfigPath, updatedConfig); } function resolveVendorId(profile) { - if (profile === CONSTANT.PLACEHOLDER.ENVIRONMENT_VAR.PROFILE_NAME) { - return process.env.ASK_VENDOR_ID; - } + if (profile === CONSTANT.PLACEHOLDER.ENVIRONMENT_VAR.PROFILE_NAME) { + return process.env.ASK_VENDOR_ID; + } - const configFile = path.join(os.homedir(), '.ask', 'cli_config'); - if (!fs.existsSync(configFile)) { - throw new Error('The app config for ask-cli does not exist. Please run "ask configure" to complete the CLI initialization.'); - } else { - const cliConfig = JSON.parse(fs.readFileSync(configFile, 'utf-8')); - return R.view(R.lensPath(['profiles', profile, 'vendor_id']), cliConfig); - } + const configFile = path.join(os.homedir(), ".ask", "cli_config"); + if (!fs.existsSync(configFile)) { + throw new Error('The app config for ask-cli does not exist. Please run "ask configure" to complete the CLI initialization.'); + } else { + const cliConfig = JSON.parse(fs.readFileSync(configFile, "utf-8")); + return R.view(R.lensPath(["profiles", profile, "vendor_id"]), cliConfig); + } } diff --git a/lib/utils/retry-utility.js b/lib/utils/retry-utility.js index c4136b37..c6a7cc92 100644 --- a/lib/utils/retry-utility.js +++ b/lib/utils/retry-utility.js @@ -1,7 +1,8 @@ -const async = require('async'); +const async = require("async"); +const CONSTANTS = require("./constants"); module.exports = { - retry + retry, }; /** @@ -15,52 +16,57 @@ module.exports = { * leads to the termination of the while loop in the retry logic. */ function retry(retryConfig, retryCall, shouldRetryCondition, callback) { - let lastResponse; - if (!retryConfig) { - return callback('[Error]: Invalid retry configuration. Retry configuration with values - base, factor and maxRetry needs to be specified'); - } - if (!retryConfig.base || retryConfig.base < 0) { - return callback('[Error]: Invalid retry configuration: base. Base is a required configuration and its value needs to be greater than 0'); - } - if (!retryConfig.factor || retryConfig.factor < 0) { - return callback('[Error]: Invalid retry configuration: factor. Factor is a required configuration and its value needs to be greater than 0'); - } - if (!retryConfig.maxRetry) { - return callback('[Error]: Invalid retry configuration: maxRetry. ' - + 'MaxRetry is a required configuration and its value needs to be greater than 0'); - } - if (!(Number.isInteger(retryConfig.maxRetry) && retryConfig.maxRetry > 0)) { - return callback('[Error]: Invalid retry configuration: maxRetry. Value needs to be an integer and greater than 0'); - } - let pollCount = -1; - async.doWhilst( - (loopCallback) => { - let retryInterval = retryConfig.base * (Math.pow(retryConfig.factor, pollCount++)); - // The very first call is not a retry and hence should not be penalised with a timeout. - if (pollCount === 0) { - retryInterval = 0; - } - setTimeout( - () => { - retryCall((err, res) => { - lastResponse = res; - loopCallback(err, err ? null : res); - }); - }, - retryInterval - ); - }, - () => { - if (!retryConfig.maxRetry || retryConfig.maxRetry > pollCount) { - return shouldRetryCondition(lastResponse); - } - return false; - }, - (err, res) => { - if (retryConfig.maxRetry && retryConfig.maxRetry <= pollCount) { - return callback('[Error]: Retry attempt exceeded.', res); - } - callback(err, err ? null : res); - } + let lastResponse; + if (!retryConfig) { + return callback( + "[Error]: Invalid retry configuration. Retry configuration with values - base, factor and maxRetry needs to be specified", ); + } + if (!retryConfig.base || retryConfig.base < 0) { + return callback( + "[Error]: Invalid retry configuration: base. Base is a required configuration and its value needs to be greater than 0", + ); + } + if (!retryConfig.factor || retryConfig.factor < 0) { + return callback( + "[Error]: Invalid retry configuration: factor. Factor is a required configuration and its value needs to be greater than 0", + ); + } + if (!retryConfig.maxRetry) { + return callback( + "[Error]: Invalid retry configuration: maxRetry. " + "MaxRetry is a required configuration and its value needs to be greater than 0", + ); + } + if (!(Number.isInteger(retryConfig.maxRetry) && retryConfig.maxRetry > 0)) { + return callback("[Error]: Invalid retry configuration: maxRetry. Value needs to be an integer and greater than 0"); + } + let pollCount = -1; + async.doWhilst( + (loopCallback) => { + const exponentialBackoff = retryConfig.base * Math.pow(retryConfig.factor, pollCount++); + let retryInterval = Math.min(exponentialBackoff, CONSTANTS.CONFIGURATION.RETRY.MAX_RETRY_INTERVAL); + // The very first call is not a retry and hence should not be penalised with a timeout. + if (pollCount === 0) { + retryInterval = 0; + } + setTimeout(() => { + retryCall((err, res) => { + lastResponse = res; + loopCallback(err, err ? null : res); + }); + }, retryInterval); + }, + () => { + if (!retryConfig.maxRetry || retryConfig.maxRetry > pollCount) { + return shouldRetryCondition(lastResponse); + } + return false; + }, + (err, res) => { + if (retryConfig.maxRetry && retryConfig.maxRetry <= pollCount) { + return callback("[Error]: Retry attempt exceeded.", res); + } + callback(err, err ? null : res); + }, + ); } diff --git a/lib/utils/stream-utility.js b/lib/utils/stream-utility.js index 51a84325..207deb28 100644 --- a/lib/utils/stream-utility.js +++ b/lib/utils/stream-utility.js @@ -1,4 +1,4 @@ -const stream = require('stream'); +const stream = require("stream"); /** * Class for ParallelTransform for Stream. @@ -6,82 +6,82 @@ const stream = require('stream'); * @extends stream.Transform */ module.exports.ParallelStream = class ParallelStream extends stream.Transform { - /** - * Create a ParallelStream - * @param {function} transform - * @param {function} onReadable - * @param {function} onFinish - * @param {object} options - */ - constructor(transform, onReadable, onFinish, options) { - super({ objectMode: options.isObjectMode }); + /** + * Create a ParallelStream + * @param {function} transform + * @param {function} onReadable + * @param {function} onFinish + * @param {object} options + */ + constructor(transform, onReadable, onFinish, options) { + super({objectMode: options.isObjectMode}); - this.transform = transform; - this.onReadable = onReadable; - this.onFinish = onFinish; - this.willTransform = options.willTransform || null; + this.transform = transform; + this.onReadable = onReadable; + this.onFinish = onFinish; + this.willTransform = options.willTransform || null; - this.active = 0; // Task not yet finished is active - this.concurrency = options.concurrency; // Used to throttle the maximum tasks running in parallel + this.active = 0; // Task not yet finished is active + this.concurrency = options.concurrency; // Used to throttle the maximum tasks running in parallel - this.terminateCallback = null; // This callback is used to store the _flush's done() - this.continueCallback = null; // This callback is used to store _transform's done() - } + this.terminateCallback = null; // This callback is used to store the _flush's done() + this.continueCallback = null; // This callback is used to store _transform's done() + } - /** - * Implement the transform logic, which will handle the stream buffer data with custom logic. - * @param {Buffer} chunk - * @param {string} enc - * @param {function} done - */ - _transform(chunk, enc, done) { - this.onReadable(chunk, enc); - if (!this.willTransform || this.willTransform()) { - this.active++; - this.transform(chunk, enc, this._onTaskComplete.bind(this), this.push.bind(this)); - } + /** + * Implement the transform logic, which will handle the stream buffer data with custom logic. + * @param {Buffer} chunk + * @param {string} enc + * @param {function} done + */ + _transform(chunk, enc, done) { + this.onReadable(chunk, enc); + if (!this.willTransform || this.willTransform()) { + this.active++; + this.transform(chunk, enc, this._onTaskComplete.bind(this), this.push.bind(this)); + } - if (this.active < this.concurrency) { - done(); - } else { - this.continueCallback = done; - } + if (this.active < this.concurrency) { + done(); + } else { + this.continueCallback = done; } + } - /** - * Implement the flush logic, which will only be called when stream is about to close. - * @param {function} done - */ - _flush(done) { - if (this.active > 0) { - // Delay the done callback if there are still any tasks active. - this.terminateCallback = done; - } else { - // Call overall onFinish when all task finishes. - this.onFinish(); - done(); - } + /** + * Implement the flush logic, which will only be called when stream is about to close. + * @param {function} done + */ + _flush(done) { + if (this.active > 0) { + // Delay the done callback if there are still any tasks active. + this.terminateCallback = done; + } else { + // Call overall onFinish when all task finishes. + this.onFinish(); + done(); } + } - /** - * The onTaskComplete handler for each task. - * @param {string} err - */ - _onTaskComplete(err) { - this.active--; - if (err) { - return this.emit('error', err); - } + /** + * The onTaskComplete handler for each task. + * @param {string} err + */ + _onTaskComplete(err) { + this.active--; + if (err) { + return this.emit("error", err); + } - // Trigger the delayed done() from _transform - const tmpContinueCallback = this.continueCallback; - this.continueCallback = null; - tmpContinueCallback && tmpContinueCallback(); // eslint-disable-line no-unused-expressions + // Trigger the delayed done() from _transform + const tmpContinueCallback = this.continueCallback; + this.continueCallback = null; + tmpContinueCallback && tmpContinueCallback(); // eslint-disable-line no-unused-expressions - // When all the tasks finish, trigger terminateCallback i.e. the done() from _flush - if (this.active === 0) { - this.onFinish(); - this.terminateCallback && this.terminateCallback(); // eslint-disable-line no-unused-expressions - } + // When all the tasks finish, trigger terminateCallback i.e. the done() from _flush + if (this.active === 0) { + this.onFinish(); + this.terminateCallback && this.terminateCallback(); // eslint-disable-line no-unused-expressions } + } }; diff --git a/lib/utils/string-utils.js b/lib/utils/string-utils.js index 0a72a79b..51ef093f 100644 --- a/lib/utils/string-utils.js +++ b/lib/utils/string-utils.js @@ -1,62 +1,64 @@ -const R = require('ramda'); -const CONSTANTS = require('@src/utils/constants'); +const R = require("ramda"); +const CONSTANTS = require("./constants"); module.exports = { - getParamNames, - camelCase, - kebabCase, - standardize, - canParseAsJson, - isNonEmptyString, - isNonBlankString, - isLambdaFunctionName, - filterNonAlphanumeric, - splitStringFilterAndMapTo, - validateSyntax + getParamNames, + camelCase, + kebabCase, + standardize, + canParseAsJson, + isNonEmptyString, + isNonBlankString, + isLambdaFunctionName, + filterNonAlphanumeric, + splitStringFilterAndMapTo, + validateSyntax, }; function getParamNames(func) { - const STRIP_COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg; - const ARGUMENT_NAMES = /([^\s,]+)/g; - const fnStr = func.toString().replace(STRIP_COMMENTS, ''); - let result = fnStr.slice(fnStr.indexOf('(') + 1, fnStr.indexOf(')')).match(ARGUMENT_NAMES); - if (result === null) result = []; - return result; + const STRIP_COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/gm; + const ARGUMENT_NAMES = /([^\s,]+)/g; + const fnStr = func.toString().replace(STRIP_COMMENTS, ""); + let result = fnStr.slice(fnStr.indexOf("(") + 1, fnStr.indexOf(")")).match(ARGUMENT_NAMES); + if (result === null) result = []; + return result; } function camelCase(str) { - return str - .replace(/(?:^\w|[A-Z]|\b\w)/g, (word, index) => (index === 0 ? word.toLowerCase() : word.toUpperCase())) - .replace(/\s+/g, '') - .replace(/-/g, ''); + return str + .replace(/(?:^\w|[A-Z]|\b\w)/g, (word, index) => (index === 0 ? word.toLowerCase() : word.toUpperCase())) + .replace(/\s+/g, "") + .replace(/-/g, ""); } function kebabCase(str) { - return str - && str - .match(/[A-Z]{2,}(?=[A-Z][a-z]+[0-9]*|\b)|[A-Z]?[a-z]+[0-9]*|[A-Z]|[0-9]+/g) - .map(x => x.toLowerCase()) - .join('-'); + return ( + str && + str + .match(/[A-Z]{2,}(?=[A-Z][a-z]+[0-9]*|\b)|[A-Z]?[a-z]+[0-9]*|[A-Z]|[0-9]+/g) + .map((x) => x.toLowerCase()) + .join("-") + ); } function standardize(str) { - return filterNonAlphanumeric(camelCase(str).toLowerCase()); + return filterNonAlphanumeric(camelCase(str).toLowerCase()); } function canParseAsJson(value) { - try { - JSON.parse(value); - return true; - } catch (err) { - return false; - } + try { + JSON.parse(value); + return true; + } catch (err) { + return false; + } } function isNonEmptyString(str) { - return R.is(String, str) && !R.isEmpty(str); + return R.is(String, str) && !R.isEmpty(str); } function isNonBlankString(str) { - return isNonEmptyString(str) && !!str.trim(); + return isNonEmptyString(str) && !!str.trim(); } /** @@ -64,13 +66,13 @@ function isNonBlankString(str) { * @param {string} str */ function isLambdaFunctionName(str) { - if (!str) { - return false; - } - // This regex can be used to check if the str - // could be a valid lambda function name - const lambdaFunctionNameRegex = /^([a-zA-Z0-9-_]+)$/; - return lambdaFunctionNameRegex.test(str); + if (!str) { + return false; + } + // This regex can be used to check if the str + // could be a valid lambda function name + const lambdaFunctionNameRegex = /^([a-zA-Z0-9-_]+)$/; + return lambdaFunctionNameRegex.test(str); } /** @@ -78,27 +80,27 @@ function isLambdaFunctionName(str) { * @param {string} str */ function filterNonAlphanumeric(str) { - if (!str) { - return str; - } - return str.replace(/[^a-zA-Z0-9-]+/g, ''); + if (!str) { + return str; + } + return str.replace(/[^a-zA-Z0-9-]+/g, ""); } /** * Applies the sequence of operations split, filter and map on a given string. */ function splitStringFilterAndMapTo(string, delimiter, filterBy, mapper) { - let arr = []; - if (isNonBlankString(string)) { - arr = string.split(delimiter); - } - if (Object.prototype.toString.call(filterBy) === '[object Function]') { - arr = arr.filter(filterBy); - } - if (Object.prototype.toString.call(mapper) === '[object Function]') { - arr = arr.map(mapper); - } - return arr; + let arr = []; + if (isNonBlankString(string)) { + arr = string.split(delimiter); + } + if (Object.prototype.toString.call(filterBy) === "[object Function]") { + arr = arr.filter(filterBy); + } + if (Object.prototype.toString.call(mapper) === "[object Function]") { + arr = arr.map(mapper); + } + return arr; } /** @@ -108,5 +110,5 @@ function splitStringFilterAndMapTo(string, delimiter, filterBy, mapper) { * returns true if the value adheres with the regex pattern. */ function validateSyntax(name, value) { - return isNonBlankString(value) ? CONSTANTS.REGEX_VALIDATIONS[name].test(value) : false; + return isNonBlankString(value) ? CONSTANTS.REGEX_VALIDATIONS[name].test(value) : false; } diff --git a/lib/utils/unflatten.js b/lib/utils/unflatten.js index 6074792e..be23e3c8 100644 --- a/lib/utils/unflatten.js +++ b/lib/utils/unflatten.js @@ -1,22 +1,23 @@ const explodeProperty = (currUnflattened, key, flattenedObj, delimiter) => { - const keys = key.split(delimiter); - const value = flattenedObj[key]; - const lastKeyIndex = keys.length - 1; + const keys = key.split(delimiter); + const value = flattenedObj[key]; + const lastKeyIndex = keys.length - 1; - for (let idx = 0; idx < lastKeyIndex; idx++) { - const currKey = keys[idx]; - if (!currUnflattened[currKey]) { - currUnflattened[currKey] = {}; - } - currUnflattened = currUnflattened[currKey]; + for (let idx = 0; idx < lastKeyIndex; idx++) { + const currKey = keys[idx]; + if (!currUnflattened[currKey]) { + currUnflattened[currKey] = {}; } + currUnflattened = currUnflattened[currKey]; + } - currUnflattened[keys[lastKeyIndex]] = value; + currUnflattened[keys[lastKeyIndex]] = value; }; -const unflatten = (flattened, delimiter = '.') => Object.keys(flattened).reduce((acc, key) => { +const unflatten = (flattened, delimiter = ".") => + Object.keys(flattened).reduce((acc, key) => { explodeProperty(acc, key, flattened, delimiter); return acc; -}, {}); + }, {}); module.exports = unflatten; diff --git a/lib/utils/url-utils.js b/lib/utils/url-utils.js index 1974ec22..ed081b0e 100644 --- a/lib/utils/url-utils.js +++ b/lib/utils/url-utils.js @@ -1,50 +1,54 @@ -const validUrl = require('valid-url'); -const path = require('path'); -const url = require('url'); +const validUrl = require("valid-url"); +const path = require("path"); +const url = require("url"); module.exports = { - isValidUrl, - isLambdaArn, - isHttpsUrl, - isUrlOfficialTemplate, - isUrlWithJsonExtension + isValidUrl, + isLambdaArn, + isHttpsUrl, + isUrlOfficialTemplate, + isUrlWithJsonExtension, }; function isValidUrl(urlString) { - return typeof urlString === 'string' && !!validUrl.isUri(urlString); + return typeof urlString === "string" && !!validUrl.isUri(urlString); } function isLambdaArn(urlString) { - if (!isValidUrl(urlString)) { - return false; - } - const lambdaRegex = new RegExp([ - 'arn:aws:lambda:[a-z]+-[a-z]+-[0-9]:[0-9]{12}:', - 'function:[a-zA-Z0-9-_]+([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})?', - '(:[a-zA-Z0-9-_]+)?' - ].join('')); - return lambdaRegex.test(urlString); + if (!isValidUrl(urlString)) { + return false; + } + const lambdaRegex = new RegExp( + [ + "arn:aws:lambda:[a-z]+-[a-z]+-[0-9]:[0-9]{12}:", + "function:[a-zA-Z0-9-_]+([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})?", + "(:[a-zA-Z0-9-_]+)?", + ].join(""), + ); + return lambdaRegex.test(urlString); } function isHttpsUrl(urlString) { - if (!isValidUrl(urlString)) { - return false; - } - return url.parse(urlString).protocol === 'https:'; + if (!isValidUrl(urlString)) { + return false; + } + return url.parse(urlString).protocol === "https:"; } function isUrlOfficialTemplate(inputUrl) { - if (!isValidUrl(inputUrl)) { - return false; - } - const urlSource = url.parse(inputUrl).pathname.split('/')[1]; - return urlSource === 'alexa'; + if (!isValidUrl(inputUrl)) { + return false; + } + const hostname = url.parse(inputUrl).hostname; + const urlSource = url.parse(inputUrl).pathname.split("/")[1]; + + return hostname === "github.com" && urlSource === "alexa"; } function isUrlWithJsonExtension(inputUrl) { - if (!isValidUrl(inputUrl)) { - return false; - } - const urlType = path.extname(inputUrl); - return urlType === '.json'; + if (!isValidUrl(inputUrl)) { + return false; + } + const urlType = path.extname(inputUrl); + return urlType === ".json"; } diff --git a/lib/utils/zip-utils.js b/lib/utils/zip-utils.js index 983ee5df..0d039087 100644 --- a/lib/utils/zip-utils.js +++ b/lib/utils/zip-utils.js @@ -1,16 +1,16 @@ -const fs = require('fs'); -const tmp = require('tmp'); -const path = require('path'); -const archiver = require('archiver'); -const AdmZip = require('adm-zip'); +const fs = require("fs"); +const tmp = require("tmp"); +const path = require("path"); +const archiver = require("archiver"); +const AdmZip = require("adm-zip"); -const httpClient = require('@src/clients/http-client'); -const Messenger = require('@src/view/messenger'); -const CONSTANTS = require('@src/utils/constants'); +const httpClient = require("../clients/http-client"); +const Messenger = require("../view/messenger"); +const CONSTANTS = require("./constants"); module.exports = { - createTempZip, - unzipRemoteZipFile + createTempZip, + unzipRemoteZipFile, }; /** @@ -18,68 +18,73 @@ module.exports = { * @param {string} src The file path of resource want to zip * @param {callback} callback { error, filePath } */ -function createTempZip(src, outputDir, callback) { - if (!src) { - return callback('Zip file path must be set.'); - } +function createTempZip(src, callback) { + if (!src) { + return callback("Zip file path must be set."); + } - if (!outputDir) { - return callback('Zip file output path must be set.'); + fs.access(src, (fs.constants || fs).W_OK, (err) => { + if (err) { + return callback(`File access error. ${err}`); + } + if (path.extname(src) === ".zip" || path.extname(src) === ".jar") { + Messenger.getInstance().debug(`The source file ${src} has already been compressed. Skip the zipping`); + return callback(null, src); } - fs.access(src, (fs.constants || fs).W_OK, (err) => { - if (err) { - return callback(`File access error. ${err}`); - } - if (path.extname(src) === '.zip' || path.extname(src) === '.jar') { - Messenger.getInstance().debug(`The source file ${src} has already been compressed. Skip the zipping`); - return callback(null, src); - } - // Create the temp zip at the same level of the source file - const zipFilePath = tmp.tmpNameSync({ - prefix: 'askcli_temp_', - postfix: '.zip', - dir: outputDir - }); - const writeStream = fs.createWriteStream(zipFilePath); - const archive = archiver('zip'); - const stats = fs.statSync(src); + // Create the temp zip at the same level of the source file + const zipFilePath = tmp.tmpNameSync({ + prefix: "askcli_temp_", + postfix: ".zip", + }); + const writeStream = fs.createWriteStream(zipFilePath); + const archive = archiver("zip"); + const stats = fs.statSync(src); - archive.on('error', (archiveErr) => { - callback(`Archive error. ${archiveErr}`); - }); + archive.on("error", (archiveErr) => { + callback(`Archive error. ${archiveErr}`); + }); - archive.pipe(writeStream); - if (stats.isFile()) { - archive.file(src, { name: path.basename(src) }); - } else if (stats.isDirectory()) { - archive.glob('**/*', { - cwd: src, - ignore: path.basename(zipFilePath) - }, {}); - } - archive.finalize(); + archive.pipe(writeStream); + if (stats.isFile()) { + archive.file(src, {name: path.basename(src)}); + } else if (stats.isDirectory()) { + archive.glob( + "**/*", + { + cwd: src, + ignore: path.basename(zipFilePath), + }, + {}, + ); + } + archive.finalize(); - writeStream.on('close', () => { - callback(null, zipFilePath); - }); + writeStream.on("close", () => { + callback(null, zipFilePath); }); + }); } function unzipRemoteZipFile(url, targetPath, doDebug, callback) { - httpClient.request({ - url, - method: CONSTANTS.HTTP_REQUEST.VERB.GET, - encoding: null - }, 'get-zip-file', doDebug, (err, response) => { - if (err) { - return callback(err); - } - const zip = new AdmZip(response.body); - try { - zip.extractAllTo(targetPath, false); - } catch (unzipErr) { - return callback(unzipErr); - } - callback(); - }); + httpClient.request( + { + url, + method: CONSTANTS.HTTP_REQUEST.VERB.GET, + encoding: null, + }, + "get-zip-file", + doDebug, + (err, response) => { + if (err) { + return callback(err); + } + const zip = new AdmZip(response.body); + try { + zip.extractAllTo(targetPath, false); + } catch (unzipErr) { + return callback(unzipErr); + } + callback(); + }, + ); } diff --git a/lib/view/cli-repl-view.js b/lib/view/cli-repl-view.js deleted file mode 100644 index 7fac3bbc..00000000 --- a/lib/view/cli-repl-view.js +++ /dev/null @@ -1,135 +0,0 @@ -const repl = require('repl'); -const SpinnerView = require('@src/view/spinner-view'); -const Messenger = require('@src/view/messenger'); -const stringUtils = require('@src/utils/string-utils'); - -module.exports = class CliReplView { - /** - * Constructor for CLI REPL View - * @param {String} prompt What string to display as the prompt for the REPL. - * @throws {Error} throws error if an undefined configuration is passed. - * @throws {Error} throws error if prompt is not a non-empty string. - */ - constructor(configuration) { - if (!configuration) { - throw 'Cannot have an undefined configuration.'; - } - const { prompt, evalFunc, header, footer, prettifyHeaderFooter, inputStream } = configuration; - this.prompt = prompt || '> '; - this.eval = evalFunc; - this.header = header; - this.footer = footer; - this.prettifyHeaderFooter = prettifyHeaderFooter || (arg => arg); - this.inputStream = inputStream || process.stdin; - this.progressSpinner = new SpinnerView(); - if (!stringUtils.isNonEmptyString(this.prompt)) { - throw 'Prompt must be a non-empty string.'; - } - this.printHeaderFooter(this.header); - // Initialize custom REPL server. - const replConfig = { - prompt: this.prompt, - eval: (cmd, context, filename, callback) => { - this.eval(cmd, callback); - }, - ignoreUndefined: true, - input: this.inputStream, - output: process.stdout - }; - this.replServer = repl.start(replConfig); - this.replServer.removeAllListeners('SIGINT'); - this.clearSpecialCommands(); - this.registerQuitCommand(() => {}); - } - - /** - * Function to print a header or footer line. - * @param {String} data the string that contains the information the caller whats to embed into header/footer. - */ - printHeaderFooter(data) { - if (stringUtils.isNonEmptyString(data)) { - Messenger.getInstance().info(this.prettifyHeaderFooter(data)); - } - } - - /** - * Register a special command to the repl - * @param {String} name name of new special command. - * @param {String} name name of new special command. - * @param {String} helpMessage description of special command - * @param {Function} func function to execute when special command received - * @param {Boolean} displayPrompt specify whether or not to display the prompt after the special command executes. Default: true - */ - registerSpecialCommand(name, helpMessage, func, displayPrompt) { - const shouldDisplayPrompt = displayPrompt === undefined ? true : displayPrompt; - this.replServer.defineCommand(name, { - help: helpMessage || this.replServer.commands[name].help, - action: (args) => { - func(args); - if (shouldDisplayPrompt) this.replServer.displayPrompt(); - } - }); - } - - /** - * Register a special exit command to the repl - * @param {Function} func function to execute when special command received - */ - registerQuitCommand(func) { - this.replServer.removeAllListeners('close'); - this.registerSpecialCommand( - 'quit', - 'Quit repl session.', - () => { - this.close(); - }, - false - ); - this.replServer.on('close', () => { - func(); - this.progressSpinner.terminate(); - this.printHeaderFooter(this.footer); - }); - } - - /** - * Remove all special commands from REPL server - * Remove close event listeners to remove all quit handlers. - */ - clearSpecialCommands() { - this.replServer.commands = { help: this.replServer.commands.help }; - this.replServer.removeAllListeners('close'); - } - - /** - * Wrapper to close instance. This involves terminating the SpinnerView, disposing the Messenger View, and closing the REPL Server. - */ - close() { - this.replServer.close(); - } - - // SpinnerView wrapper functions - - /** - * Wrapper for starting the SpinnerView with a specified message. - * @param {String} text text to display when the spinner starts. - */ - startProgressSpinner(text) { - this.progressSpinner.start(text); - } - - /** - * Wrapper for updating the text of the SpinnerView - * @param {String} text text to replace current message of spinner. - */ - updateProgressSpinner(text) { - this.progressSpinner.update(text); - } - - /** - * Wrapper for terminating the SpinnerView, clearing it from the console - */ - terminateProgressSpinner() { - this.progressSpinner.terminate(); - } -}; diff --git a/lib/view/cli-repl-view.ts b/lib/view/cli-repl-view.ts new file mode 100644 index 00000000..48676425 --- /dev/null +++ b/lib/view/cli-repl-view.ts @@ -0,0 +1,156 @@ +import repl from "repl"; + +import SpinnerView from "./spinner-view"; +import Messenger from "./messenger"; +import * as stringUtils from "../utils/string-utils"; + +export interface CliReplViewConfig { + prompt: string; + evalFunc: (cmd: string, callback: (err: Error | null, result: any) => void) => void; + header: string; + footer: string; + prettifyHeaderFooter?: (arg: string) => string; + inputStream?: NodeJS.ReadableStream; +} + +export class CliReplView { + prompt: string; + eval; + header; + footer; + prettifyHeaderFooter; + inputStream; + progressSpinner; + replServer; + + /** + * Constructor for CLI REPL View + * @param {String} prompt What string to display as the prompt for the REPL. + * @throws {Error} throws error if an undefined configuration is passed. + * @throws {Error} throws error if prompt is not a non-empty string. + */ + constructor(configuration: CliReplViewConfig) { + if (!configuration) { + throw "Cannot have an undefined configuration."; + } + const {prompt, evalFunc, header, footer, prettifyHeaderFooter, inputStream} = configuration; + this.prompt = prompt || "> "; + this.eval = evalFunc; + this.header = header; + this.footer = footer; + this.prettifyHeaderFooter = prettifyHeaderFooter || ((arg: string) => arg); + this.inputStream = inputStream || process.stdin; + this.progressSpinner = new SpinnerView(); + if (!stringUtils.isNonEmptyString(this.prompt)) { + throw "Prompt must be a non-empty string."; + } + this.printHeaderFooter(this.header); + // Initialize custom REPL server. + const replConfig: repl.ReplOptions = { + prompt: this.prompt, + eval: (cmd, _context, _filename, callback) => { + this.eval(cmd, callback); + }, + ignoreUndefined: true, + input: this.inputStream, + output: process.stdout, + }; + this.replServer = repl.start(replConfig); + this.replServer.removeAllListeners("SIGINT"); + this.clearSpecialCommands(); + this.registerQuitCommand(() => {}); + } + + /** + * Function to print a header or footer line. + * @param {String} data the string that contains the information the caller whats to embed into header/footer. + */ + printHeaderFooter(data: string) { + if (stringUtils.isNonEmptyString(data)) { + Messenger.getInstance().info(this.prettifyHeaderFooter(data)); + } + } + + /** + * Register a special command to the repl + * @param {String} name name of new special command. + * @param {String} name name of new special command. + * @param {String} helpMessage description of special command + * @param {Function} func function to execute when special command received + * @param {Boolean} displayPrompt specify whether or not to display the prompt after the special command executes. Default: true + */ + registerSpecialCommand(name: string, helpMessage: string, func: (args: string) => void, displayPrompt?: boolean) { + const shouldDisplayPrompt = displayPrompt === undefined ? true : displayPrompt; + this.replServer.defineCommand(name, { + help: helpMessage || this.replServer.commands[name]?.help, + action: (args) => { + func(args); + if (shouldDisplayPrompt) this.replServer.displayPrompt(); + }, + }); + } + + /** + * Register a special exit command to the repl + * @param {Function} func function to execute when special command received + */ + registerQuitCommand(func: () => void) { + this.replServer.removeAllListeners("close"); + this.registerSpecialCommand( + "quit", + "Quit repl session.", + () => { + this.close(); + }, + false, + ); + this.replServer.on("close", () => { + func(); + this.progressSpinner.terminate(); + this.printHeaderFooter(this.footer); + }); + } + + /** + * Remove all special commands from REPL server + * Remove close event listeners to remove all quit handlers. + */ + clearSpecialCommands() { + (this.replServer.commands as any) = { + help: this.replServer.commands.help, + }; + this.replServer.removeAllListeners("close"); + } + + /** + * Wrapper to close instance. This involves terminating the SpinnerView, disposing the Messenger View, and closing the REPL Server. + */ + close() { + this.replServer.close(); + } + + // SpinnerView wrapper functions + + /** + * Wrapper for starting the SpinnerView with a specified message. + * @param {String} text text to display when the spinner starts. + */ + startProgressSpinner(text: string) { + this.progressSpinner.start(text); + } + + /** + * Wrapper for updating the text of the SpinnerView + * @param {String} text text to replace current message of spinner. + */ + updateProgressSpinner(text: string) { + this.progressSpinner.update(text); + } + + /** + * Wrapper for terminating the SpinnerView, clearing it from the console + */ + terminateProgressSpinner() { + this.progressSpinner.terminate(); + } +} diff --git a/lib/view/dialog-repl-view.js b/lib/view/dialog-repl-view.js deleted file mode 100644 index 8c78f409..00000000 --- a/lib/view/dialog-repl-view.js +++ /dev/null @@ -1,39 +0,0 @@ -const CliReplView = require('@src/view/cli-repl-view'); - -module.exports = class DialogReplView extends CliReplView { - /** - * Constructor for DialogReplView. - * @param {Object} configuration config object. - */ - constructor(configuration) { - const conf = configuration || {}; - conf.prettifyHeaderFooter = (arg) => { - const lines = arg.split('\n'); - const terminalWidth = process.stdout.columns; - const halfWidth = Math.floor(terminalWidth / 2); - const bar = '='.repeat(terminalWidth); - const formattedLines = lines.map((line) => { - const paddedLine = ` ${line.trim()} `; - const offset = halfWidth - Math.floor(paddedLine.length / 2); - if (offset < 0) { - return `===${paddedLine}===`; - } - return bar.slice(0, offset) + paddedLine + bar.slice(offset + paddedLine.length); - }); - return `\n${formattedLines.join('\n')}\n`; - }; - super(conf); - } - - /** - * Specify the record special command. - * @param {Function} func What function to execute when .record command is inputted. - */ - registerRecordCommand(func) { - this.registerSpecialCommand( - 'record', - 'Record input utterances to a replay file of a specified name.', - func - ); - } -}; diff --git a/lib/view/dialog-repl-view.ts b/lib/view/dialog-repl-view.ts new file mode 100644 index 00000000..ed89fc25 --- /dev/null +++ b/lib/view/dialog-repl-view.ts @@ -0,0 +1,35 @@ +import {CliReplView, CliReplViewConfig} from "./cli-repl-view"; + +export class DialogReplView extends CliReplView { + /** + * Constructor for DialogReplView. + * @param {Object} configuration config object. + */ + constructor(configuration: CliReplViewConfig) { + const conf = configuration || {}; + conf.prettifyHeaderFooter = (arg) => { + const lines = arg.split("\n"); + const terminalWidth = process.stdout.columns; + const halfWidth = Math.floor(terminalWidth / 2); + const bar = "=".repeat(terminalWidth); + const formattedLines = lines.map((line) => { + const paddedLine = ` ${line.trim()} `; + const offset = halfWidth - Math.floor(paddedLine.length / 2); + if (offset < 0) { + return `===${paddedLine}===`; + } + return bar.slice(0, offset) + paddedLine + bar.slice(offset + paddedLine.length); + }); + return `\n${formattedLines.join("\n")}\n`; + }; + super(conf); + } + + /** + * Specify the record special command. + * @param {Function} func What function to execute when .record command is inputted. + */ + registerRecordCommand(func: (args: string) => void) { + this.registerSpecialCommand("record", "Record input utterances to a replay file of a specified name.", func); + } +} diff --git a/lib/view/import-status/import-status-view-events.ts b/lib/view/import-status/import-status-view-events.ts new file mode 100644 index 00000000..f66b390e --- /dev/null +++ b/lib/view/import-status/import-status-view-events.ts @@ -0,0 +1,22 @@ +export type ImportStatusViewEvents = + | "buildingACLight" + | "buildingACFull" + | "buildACSuccess" + | "buildACFailed" + | "buildIMSuccess" + | "buildIMFailed" + | "fetchingSkillIdSuccess" + | "fetchingNewSkillIdSuccess" + | "fetchingImportIdSuccess" + | "fetchingIdFailed" + | "cancelTask"; +export const IMPORT_STATUS_BUILDING_AC_LIGHT_EVENT: ImportStatusViewEvents = "buildingACLight"; +export const IMPORT_STATUS_BUILDING_AC_FULL_EVENT: ImportStatusViewEvents = "buildingACFull"; +export const IMPORT_STATUS_AC_BUILD_SUCCESS_EVENT: ImportStatusViewEvents = "buildACSuccess"; +export const IMPORT_STATUS_AC_BUILD_FAILED_EVENT: ImportStatusViewEvents = "buildACFailed"; +export const IMPORT_STATUS_IM_BUILD_SUCCESS_EVENT: ImportStatusViewEvents = "buildIMSuccess"; +export const IMPORT_STATUS_IM_BUILD_FAILED_EVENT: ImportStatusViewEvents = "buildIMFailed"; +export const IMPORT_STATUS_FETCHING_SKILL_ID_SUCESS_EVENT: ImportStatusViewEvents = "fetchingSkillIdSuccess"; +export const IMPORT_STATUS_FETCHING_NEW_SKILL_ID_SUCESS_EVENT: ImportStatusViewEvents = "fetchingNewSkillIdSuccess"; +export const IMPORT_STATUS_FETCHING_IMPORT_ID_SUCESS_EVENT: ImportStatusViewEvents = "fetchingImportIdSuccess"; +export const IMPORT_STATUS_CANCEL_TASK_EVENT: ImportStatusViewEvents = "cancelTask"; diff --git a/lib/view/import-status/import-status-view-observable.ts b/lib/view/import-status/import-status-view-observable.ts new file mode 100644 index 00000000..cebfd737 --- /dev/null +++ b/lib/view/import-status/import-status-view-observable.ts @@ -0,0 +1,109 @@ +import {EventEmitter} from "events"; +import {Observable} from "rxjs"; +import { + IMPORT_STATUS_AC_BUILD_FAILED_EVENT, + IMPORT_STATUS_AC_BUILD_SUCCESS_EVENT, + IMPORT_STATUS_BUILDING_AC_FULL_EVENT, + IMPORT_STATUS_BUILDING_AC_LIGHT_EVENT, + IMPORT_STATUS_FETCHING_IMPORT_ID_SUCESS_EVENT, + IMPORT_STATUS_FETCHING_NEW_SKILL_ID_SUCESS_EVENT, + IMPORT_STATUS_FETCHING_SKILL_ID_SUCESS_EVENT, + IMPORT_STATUS_IM_BUILD_FAILED_EVENT, + IMPORT_STATUS_IM_BUILD_SUCCESS_EVENT, + IMPORT_STATUS_CANCEL_TASK_EVENT, +} from "./import-status-view-events"; + +export class ImportStatusViewObservable { + private emitter: EventEmitter; + private id: string; + + constructor(emitter: EventEmitter, id: string) { + this.id = id; + this.emitter = emitter; + } + + getObservable() { + return (_ctx: any, task: {taskId: string; title: string; enabled?: boolean}) => { + task.taskId = this.id; + task.enabled = true; + return new Observable((observer: {complete: () => void; error: (error: Error) => void; next: (message: string) => void}) => { + this.emitter.on(IMPORT_STATUS_CANCEL_TASK_EVENT, () => { + if (task.enabled) { + const status = `[${task.taskId}] task stopped polling for status.`; + observer.error(new Error(status)); + task.enabled = false; + } + }); + + this.emitter.on(IMPORT_STATUS_FETCHING_SKILL_ID_SUCESS_EVENT, (value: string) => { + if (task.enabled) { + const message = `Using pre-existing skill id: ${value}`; + task.title = message; + observer.complete(); + task.enabled = false; + } + }); + + this.emitter.on(IMPORT_STATUS_FETCHING_NEW_SKILL_ID_SUCESS_EVENT, (value: string) => { + if (task.enabled) { + const message = `Received a new skill id: ${value}`; + task.title = message; + observer.complete(); + task.enabled = false; + } + }); + + this.emitter.on(IMPORT_STATUS_FETCHING_IMPORT_ID_SUCESS_EVENT, (value: string) => { + const message = `Importing skill using import id: ${value}`; + task.title = message; + observer.complete(); + task.enabled = false; + }); + + this.emitter.on(IMPORT_STATUS_IM_BUILD_SUCCESS_EVENT, () => { + const status = `[${task.taskId}] build is complete.`; + task.title = status; + observer.complete(); + task.enabled = false; + }); + + this.emitter.on(IMPORT_STATUS_IM_BUILD_FAILED_EVENT, () => { + const status = `[${task.taskId}] build has failed.`; + task.title = status; + observer.error(new Error(status)); + task.enabled = false; + }); + + this.emitter.on(IMPORT_STATUS_BUILDING_AC_LIGHT_EVENT, () => { + const status = `[${task.taskId}] build is now in progress...`; + task.title = status; + observer.next("Building Alexa Conversations light build"); + }); + + this.emitter.on(IMPORT_STATUS_BUILDING_AC_FULL_EVENT, () => { + const status = `[${task.taskId}] Alexa Conversations light build is successful for locale: ${task.taskId}.`; + task.title = status; + observer.next( + "You can now test some Alexa Conversations dialogs while we continue to train your model with additional simulated dialogs.", + ); + }); + + this.emitter.on(IMPORT_STATUS_AC_BUILD_SUCCESS_EVENT, () => { + const message = + `[${task.taskId}] Alexa Conversations full build is successful for locale: ${task.taskId}. ` + + "You can now test Alexa Conversations dialogs."; + task.title = message; + observer.complete(); + task.enabled = false; + }); + + this.emitter.on(IMPORT_STATUS_AC_BUILD_FAILED_EVENT, (errorMessage: string) => { + const message = `[${task.taskId}] Alexa Conversations build failed. Error: ${errorMessage}`; + task.title = message; + observer.error(new Error(errorMessage)); + task.enabled = false; + }); + }); + }; + } +} diff --git a/lib/view/import-status/import-status-view.ts b/lib/view/import-status/import-status-view.ts new file mode 100644 index 00000000..ed70f28c --- /dev/null +++ b/lib/view/import-status/import-status-view.ts @@ -0,0 +1,130 @@ +import Listr from "listr"; +import {EventEmitter} from "events"; +import {ListrTask} from "listr"; +import {ImportStatusViewObservable} from "./import-status-view-observable"; +import { + ImportStatusViewEvents, + IMPORT_STATUS_CANCEL_TASK_EVENT, + IMPORT_STATUS_FETCHING_IMPORT_ID_SUCESS_EVENT, + IMPORT_STATUS_FETCHING_NEW_SKILL_ID_SUCESS_EVENT, + IMPORT_STATUS_FETCHING_SKILL_ID_SUCESS_EVENT, +} from "./import-status-view-events"; +import {retry} from "../../utils/retry-utility"; +import Messenger from "../messenger"; + +/** + * View class used to print the status of an skill import + */ +export class ImportStatusView { + private listr: Listr; + private listrTasks: ListrTask[] = []; + private eventMapping: Map = new Map(); + private skillIdTaskTitle = "Retrieving skill id..."; + private importIdTaskTitle = "Retrieving import id..."; + + constructor(locales: string[], listr?: Listr) { + // add skill id and import id tasks + this.addTask(this.skillIdTaskTitle); + this.addTask(this.importIdTaskTitle); + // add all locales tasks + locales.map((taskTitle) => this.addTask(taskTitle, `[${taskTitle}] Import model builder task.`)); + // initialize listr if not injected + this.listr = listr ? listr : new Listr([], {concurrent: true, exitOnError: true}); + this.listr.add(this.listrTasks); + Messenger.getInstance().pause(); + this.listr.run().catch((error) => { + Messenger.getInstance().warn(error?.message); + }); + } + + private addTask(taskTitle: string, initialText?: string): void { + const emitter = new EventEmitter(); + const task: any = new ImportStatusViewObservable(emitter, taskTitle).getObservable(); + + this.listrTasks.push({ + title: initialText ? initialText : taskTitle, + task: task, + }); + + this.eventMapping.set(taskTitle, emitter); + } + + /** + * Function used to publish an update to one of the locales/tasks + * @param {string} taskTitle title of the task. i.e. for a locale import model build task 'en-US' + * @param {ImportStatusViewEvents} importStatusPollViewEventName Import status view event to emit + * @param {string} value Optional value to pass along with the event + */ + public publishEvent(taskTitle: string, importStatusPollViewEventName: ImportStatusViewEvents, value?: string): void { + this.eventMapping.get(taskTitle)?.emit(importStatusPollViewEventName, value); + } + + /** + * Call this idempotence function once a skill id has been found + * this will publish the skill id on the terminal and completes the task + * @param skillId Alexa skill id + * @param fromLocalConfigurationFiles set to true, if this skill id was retreived from the local ask-state file. false if it was retrieved from the SMAPI service api calls + */ + public displaySkillId(skillId: string, fromLocalConfigurationFiles: boolean) { + const eventToPublish = fromLocalConfigurationFiles + ? IMPORT_STATUS_FETCHING_SKILL_ID_SUCESS_EVENT + : IMPORT_STATUS_FETCHING_NEW_SKILL_ID_SUCESS_EVENT; + this.eventMapping.get(this.skillIdTaskTitle)?.emit(eventToPublish, skillId); + } + + /** + * Call this idempotence function with the import id once it has been retrieved from the SMAPI service calls + * this will publish the import id on the terminal and completes the task + * @param importId Alexa skill model build import id + */ + public displayImportId(importId: string) { + this.eventMapping.get(this.importIdTaskTitle)?.emit(IMPORT_STATUS_FETCHING_IMPORT_ID_SUCESS_EVENT, importId); + } + + /** + * Call this function to stop all tasks from continuing to print/update on the terminal + */ + public stop() { + this.eventMapping.forEach((emitter) => { + emitter.emit(IMPORT_STATUS_CANCEL_TASK_EVENT); + }); + } + + /** + * Async function that only returns once all the tasks have been disabled + * @returns This promise returns once all the tasks have been disabled + */ + public async waitForCompletion(): Promise { + return new Promise((resolve) => { + const retryEverySecondFor2Hrs = { + base: 1000, + factor: 1.0, + maxRetry: 2 * 60 * 60, + }; + const retryCall = (loopCallback: (isRunning: boolean) => {}) => { + loopCallback(this.isRunning()); + }; + const shouldRetryCondition = (isRunning: boolean) => { + return isRunning === true ? true : false; + }; + const onRetryCompletion = () => { + Messenger.getInstance().resume(); + resolve(); + }; + + retry(retryEverySecondFor2Hrs, retryCall, shouldRetryCondition, onRetryCompletion); + }); + } + + private isRunning(): boolean { + let isRunning = false; + + this.listrTasks.forEach((task) => { + if (task.enabled) { + isRunning = true; + } + }); + + return isRunning; + } +} diff --git a/lib/view/json-view.js b/lib/view/json-view.js index ec02e88d..ee4def1d 100644 --- a/lib/view/json-view.js +++ b/lib/view/json-view.js @@ -1,7 +1,7 @@ -const CONSTANTS = require('@src/utils/constants'); +const CONSTANTS = require("../utils/constants"); module.exports = { - toString + toString, }; /** @@ -10,13 +10,13 @@ module.exports = { * @returns formatted JSON string or serialization error */ function toString(jsonObject) { - try { - // handle issue when Error object serialized to {} - if (jsonObject instanceof Error) { - jsonObject = { message: jsonObject.message, stack: jsonObject.stack, detail: jsonObject }; - } - return JSON.stringify(jsonObject, null, CONSTANTS.CONFIGURATION.JSON_DISPLAY_INDENT); - } catch (e) { - return e.toString(); + try { + // handle issue when Error object serialized to {} + if (jsonObject instanceof Error) { + jsonObject = {message: jsonObject.message, stack: jsonObject.stack, detail: jsonObject}; } + return JSON.stringify(jsonObject, null, CONSTANTS.CONFIGURATION.JSON_DISPLAY_INDENT); + } catch (e) { + return e.toString(); + } } diff --git a/lib/view/messenger.js b/lib/view/messenger.js index fd7fa6e9..51be0a15 100644 --- a/lib/view/messenger.js +++ b/lib/view/messenger.js @@ -1,243 +1,302 @@ -const chalk = require('chalk'); -const path = require('path'); -const fs = require('fs'); +const chalk = require("chalk"); +const path = require("path"); +const fs = require("fs"); // A map used to define message levels // and set their display styles const MESSAGE_CATEGORY_MAPPING = { - TRACE: { - level: 10, - display: {} + TRACE: { + level: 10, + display: {}, + }, + DEBUG: { + level: 20, + display: { + color: "gray", + bold: false, + prefix: "[Debug]: ", + method: "warn", }, - DEBUG: { - level: 20, - display: { - color: 'gray', - bold: false, - prefix: '[Debug]: ', - method: 'warn', - } + }, + INFO: { + level: 30, + display: { + color: null, + bold: false, + prefix: "", + method: "log", }, - INFO: { - level: 30, - display: { - color: null, - bold: false, - prefix: '', - method: 'log' - } + }, + WARN: { + level: 40, + display: { + color: "yellow", + bold: true, + prefix: "[Warn]: ", + method: "warn", }, - WARN: { - level: 40, - display: { - color: 'yellow', - bold: true, - prefix: '[Warn]: ', - method: 'warn' - } + }, + ERROR: { + level: 50, + display: { + color: "red", + bold: true, + prefix: "[Error]: ", + method: "error", }, - ERROR: { - level: 50, - display: { - color: 'red', - bold: true, - prefix: '[Error]: ', - method: 'error' - } + }, + FATAL: { + level: 60, + display: { + color: "rgb(128, 0, 0)", + bold: true, + prefix: "[Fatal]: ", + method: "error", }, - FATAL: { - level: 60, - display: { - color: 'rgb(128, 0, 0)', - bold: true, - prefix: '[Fatal]: ', - method: 'error' - } - } + }, }; let instance = null; class Messenger { - // Make this class as a singleton - constructor({ doDebug }) { - if (!instance) { - instance = this; - } - // TODO: change buffer data type to avoid overflow - // Used to record all CLI std behaviors - this._buffer = []; - // This flag is for debug use in order to - // determine whether commands is working on debug mode - this.doDebug = doDebug || false; - return instance; + // Make this class as a singleton + constructor({doDebug = false}) { + if (!instance) { + instance = this; } + // TODO: change buffer data type to avoid overflow + // Used to record all CLI std behaviors + this._buffer = []; + this.pausedMessages = []; + this.pauseMessageDisplay = false; + // This flag is for debug use in order to + // determine whether commands is working on debug mode + this.doDebug = doDebug || false; + return instance; + } - static getInstance() { - return instance || new Messenger({}); - } + static getInstance() { + return instance || new Messenger({}); + } - // If the commander works under debug mode, write all debug level messages to local file - // when the messanger instance get disposed and set to null - dispose() { - if (this.doDebug) { - this.writeLogToFile(); - } - instance = null; + /** + * If the commander works under debug mode, write all debug level messages to local file + * when the messanger instance get disposed and set to null + */ + dispose() { + if (this.doDebug) { + this.writeLogToFile(); } + this.resume(); + instance = null; + } - // Used to track http request behaviors - // Record information to buffer - trace(data) { - const operation = 'TRACE'; - this._buffer.push({ - time: Messenger.getTime(), - operation, - level: MESSAGE_CATEGORY_MAPPING[operation].level, - msg: data - }); + buffer(entry) { + if (this.doDebug) { + this._buffer.push(entry); } + } - // Used to track CLI internal debug messages - // Record CLI behaviors to buffer and - // expose debug messages immediately when user have --debug option set - debug(data) { - const operation = 'DEBUG'; - this._buffer.push({ - time: Messenger.getTime(), - operation, - level: MESSAGE_CATEGORY_MAPPING[operation].level, - msg: data - }); - if (this.doDebug) { - Messenger.displayMessage(operation, data); - } - } + /** + * Used to track http request behaviors + * Record information to buffer + */ + trace(data) { + const operation = "TRACE"; + this.buffer({ + time: Messenger.getTime(), + operation, + level: MESSAGE_CATEGORY_MAPPING[operation].level, + msg: data, + }); + } - // Used to display the information during the CLI command execution - info(data) { - const operation = 'INFO'; - this._buffer.push({ - time: Messenger.getTime(), - operation, - level: MESSAGE_CATEGORY_MAPPING[operation].level, - msg: data - }); - Messenger.displayMessage(operation, data); + /** + * Used to track CLI internal debug messages + * Record CLI behaviors to buffer and + * expose debug messages immediately when user have --debug option set + * @param {*} data the message to display + */ + debug(data) { + const operation = "DEBUG"; + this.buffer({ + time: Messenger.getTime(), + operation, + level: MESSAGE_CATEGORY_MAPPING[operation].level, + msg: data, + }); + if (this.doDebug) { + this.displayMessage(operation, data); } + } - // record warn message to buffer and - // print to console - warn(data) { - const operation = 'WARN'; - this._buffer.push({ - time: Messenger.getTime(), - operation, - level: MESSAGE_CATEGORY_MAPPING[operation].level, - msg: data - }); - Messenger.displayMessage(operation, data); - } + /** + * Used to display the information during the CLI command execution + * @param {*} data the message to display + */ + info(data) { + const operation = "INFO"; + this.buffer({ + time: Messenger.getTime(), + operation, + level: MESSAGE_CATEGORY_MAPPING[operation].level, + msg: data, + }); + this.displayMessage(operation, data); + } - // record error message to buffer and - // print to console - error(data) { - const msg = data.constructor.name === 'Error' ? data.message : data; - - const operation = 'ERROR'; - this._buffer.push({ - time: Messenger.getTime(), - operation, - level: MESSAGE_CATEGORY_MAPPING[operation].level, - msg, - }); - Messenger.displayMessage(operation, msg); - } + /** + * record warn message to buffer and + * print to console + * @param {*} data the message to display + */ + warn(data) { + const operation = "WARN"; + this.buffer({ + time: Messenger.getTime(), + operation, + level: MESSAGE_CATEGORY_MAPPING[operation].level, + msg: data, + }); + this.displayMessage(operation, data); + } + + /** + * record error message to buffer and + * print to console + * @param {*} data the message to display + */ + error(data) { + const msg = data.constructor.name === "Error" ? data.message : data; + + const operation = "ERROR"; + this.buffer({ + time: Messenger.getTime(), + operation, + level: MESSAGE_CATEGORY_MAPPING[operation].level, + msg, + }); + this.displayMessage(operation, msg); + } + + /** + * record fatal message to buffer and + * print to console + * @param {*} data the message to display + */ + fatal(data) { + const msg = data.constructor.name === "Error" ? data.stack.substring(7) : data; + + const operation = "FATAL"; + this.buffer({ + time: Messenger.getTime(), + operation, + level: MESSAGE_CATEGORY_MAPPING[operation].level, + msg, + }); + this.displayMessage(operation, msg); + } + + /** + * Starts buffering any new message and prevent them from getting displayed on the terminal + * until either the resume command is called or the Messenger object is disposed + */ + pause() { + this.pauseMessageDisplay = true; + } - // record fatal message to buffer and - // print to console - fatal(data) { - const msg = data.constructor.name === 'Error' ? data.stack.substring(7) : data; - - const operation = 'FATAL'; - this._buffer.push({ - time: Messenger.getTime(), - operation, - level: MESSAGE_CATEGORY_MAPPING[operation].level, - msg, - }); - Messenger.displayMessage(operation, msg); + /** + * If paused was previously called this will resume display messages + * as well as display any message that was previously paused. + */ + resume() { + this.pauseMessageDisplay = false; + while (this.pausedMessages.length > 0) { + const message = this.pausedMessages.shift(); + this.displayMessage(message.operation, message.data); } + } - /** - * A view wrapper, print std in different styles according to different message category - * @param {string} operation The message category - * @param {string} data The text content to be displayed - */ - static displayMessage(operation, data) { - const { color, method, bold, prefix } = MESSAGE_CATEGORY_MAPPING[operation].display; - const msg = prefix + data; - Messenger.displayWithStyle(color, method, bold, msg); + /** + * A view wrapper, print std in different styles according to different message category + * @param {string} operation The message category + * @param {string} data The text content to be displayed + */ + displayMessage(operation, data) { + if (this.pauseMessageDisplay) { + this.pausedMessages.push({ + operation: operation, + data: data, + }); + } else { + const {color, method, bold, prefix} = MESSAGE_CATEGORY_MAPPING[operation].display; + const msg = prefix + data; + Messenger.displayWithStyle(color, method, bold, msg); } + } - /** - * The print function to display message in different styles - * @param {string} color set the color of the text - * @param {string} method set the console method, could be log, warn and error - * @param {boolean} bold a boolean value decide whether the font should be bold - * @param {string} msg The text content to be displayed - */ - static displayWithStyle(color, method, bold, msg) { - const boldTag = bold ? 'bold' : undefined; - const colorTag = color || undefined; - const finalTemplateTag = [boldTag, colorTag].filter(str => str).join('.'); - if (!finalTemplateTag) { - console[method](msg); - } else { - console[method](chalk`{${finalTemplateTag} ${msg}}`); - } + /** + * The print function to display message in different styles + * @param {string} color set the color of the text + * @param {string} method set the console method, could be log, warn and error + * @param {boolean} bold a boolean value decide whether the font should be bold + * @param {string} msg The text content to be displayed + */ + static displayWithStyle(color, method, bold, msg) { + const boldTag = bold ? "bold" : undefined; + const colorTag = color || undefined; + const finalTemplateTag = [boldTag, colorTag].filter((str) => str).join("."); + if (!finalTemplateTag) { + console[method](msg); + } else { + console[method](chalk`{${finalTemplateTag} ${msg}}`); } + } - // Read Trace level info from buffer, - // modify the structure to make it easy to read, - // write restructured info to a log file - writeLogToFile() { - const time = Messenger.getTime(); - const filePath = path.join(process.cwd(), `ask-cli-${time}.log`); - const content = []; - for (const item of this._buffer) { - if (item.operation === 'TRACE') { - content.push(`\n[${item.time}] - ${item.operation} - ${item.msg.activity.toUpperCase()}`); - if (item.msg['request-id']) { - content.push(`\nrequest-id: ${item.msg['request-id']}`); - } - content.push(`\n${item.msg.request.method} ${item.msg.request.url}`); - content.push(`\nstatus code: ${item.msg.response.statusCode} ${item.msg.response.statusMessage}`); - if (item.msg.error) { - content.push(`\nerror: ${item.msg.error}\n`); - } - content.push(`\nRequest headers: ${JSON.stringify(item.msg.request.headers)}`); - if (item.msg.request.body) { - content.push(`\nRequest body: ${item.msg.request.body}`); - } - content.push(`\nResponse headers: ${JSON.stringify(item.msg.response.headers)}`); - if (item.msg.body) { - content.push(`\nResponse body: ${JSON.stringify(item.msg.body)}`); - } - content.push('\n----------------------------------------'); - } + /** + * Read Trace level info from buffer, + * modify the structure to make it easy to read, + * write restructured info to a log file + */ + writeLogToFile() { + const time = Messenger.getTime(); + const filePath = path.join(process.cwd(), `ask-cli-${time}.log`); + const content = []; + for (const item of this._buffer) { + if (item.operation === "TRACE") { + content.push(`\n[${item.time}] - ${item.operation} - ${item.msg.activity.toUpperCase()}`); + if (item.msg["request-id"]) { + content.push(`\nrequest-id: ${item.msg["request-id"]}`); + } + content.push(`\n${item.msg.request.method} ${item.msg.request.url}`); + content.push(`\nstatus code: ${item.msg.response.statusCode} ${item.msg.response.statusMessage}`); + if (item.msg.error) { + content.push(`\nerror: ${item.msg.error}\n`); + } + content.push(`\nRequest headers: ${JSON.stringify(item.msg.request.headers)}`); + if (item.msg.request.body) { + content.push(`\nRequest body: ${item.msg.request.body}`); } - if (content.length >= 1) { - fs.writeFileSync(filePath, content); - console.log(`\nDetail log has been recorded at ${filePath}`); + content.push(`\nResponse headers: ${JSON.stringify(item.msg.response.headers)}`); + if (item.msg.body) { + content.push(`\nResponse body: ${JSON.stringify(item.msg.body)}`); } + content.push("\n----------------------------------------"); + } } - - // Used to get system time and format the time into the pattern of "week-month-day-year-hour:minute:second-time zone". - // eg: Mon-Apr-01-2019-11:31:21-GMT-0700-(PDT) - static getTime() { - return new Date().toString().replace(/ /g, '-'); + if (content.length >= 1) { + fs.writeFileSync(filePath, content); + console.log(`\nDetail log has been recorded at ${filePath}`); } + } + + /** + * Used to get system time and format the time into the pattern of "week-month-day-year-hour:minute:second-time zone". + * @returns string representation of the current date ie. Mon-Apr-01-2019-11:31:21-GMT-0700-(PDT) + */ + static getTime() { + return new Date().toString().replace(/ /g, "-"); + } } module.exports = Messenger; diff --git a/lib/view/multi-tasks-view.js b/lib/view/multi-tasks-view.js index 55a66ba4..da3b554c 100644 --- a/lib/view/multi-tasks-view.js +++ b/lib/view/multi-tasks-view.js @@ -1,138 +1,145 @@ -const Listr = require('listr'); -const { EventEmitter } = require('events'); -const { Observable } = require('rxjs'); -const CliError = require('@src/exceptions/cli-error'); +const Listr = require("listr"); +const {EventEmitter} = require("events"); +const {Observable} = require("rxjs"); +const CliError = require("../exceptions/cli-error"); /** * Reactive (rxjs) task class which serve as the middleware for Listr task registration */ class ListrReactiveTask { - /** - * Constructor method which will initiate an eventEmitter for each instance. - * @param {Funciton} taskHandle the task handle which will be executed later, in the interface of: - * (reporter, callback) => { // use reporter and callback in the actual logic } - * @param {String} taskId taskId used to track task result - */ - constructor(taskHandle, taskId) { - this.taskHandle = taskHandle; - this.taskId = taskId; + /** + * Constructor method which will initiate an eventEmitter for each instance. + * @param {Function} taskHandle the task handle which will be executed later, in the interface of: + * (reporter, callback) => { // use reporter and callback in the actual logic } + * @param {String} taskId taskId used to track task result + */ + constructor(taskHandle, taskId) { + this.taskHandle = taskHandle; + this.taskId = taskId; - this._eventEmitter = new EventEmitter(); - } + this._eventEmitter = new EventEmitter(); + } - /** - * Reporter getter function which returns methods used for task executor to send updates - * - reporter.updateStatus update "status" for a task - */ - get reporter() { - return { - skipTask: (reason) => { - this._eventEmitter.emit('skip', reason); - }, - updateStatus: (status) => { - this._eventEmitter.emit('status', status); - } - }; - } + /** + * Reporter getter function which returns methods used for task executor to send updates + * - reporter.updateStatus update "status" for a task + */ + get reporter() { + return { + skipTask: (reason) => { + this._eventEmitter.emit("skip", reason); + }, + updateStatus: (status) => { + this._eventEmitter.emit("status", status); + }, + }; + } - /** - * Execute the task handle, and convert task callback result to managed event. - */ - execute() { - this.taskHandle(this.reporter, (err, result) => { - if (err) { - this._eventEmitter.emit('error', err); - } else { - this._eventEmitter.emit('complete', result); - } - }); - } + /** + * Execute the task handle, and convert task callback result to managed event. + */ + execute() { + this.taskHandle(this.reporter, (err, result) => { + if (err) { + this._eventEmitter.emit("error", err); + } else { + this._eventEmitter.emit("complete", result); + } + }); + } - /** - * Connect EventEmitter to Rx.Observable by mapping the listened events to subscriber's action. - * Mapping is: event observable - * status subscriber.next - * error subscriber.error + record error.context to task context - * skill task.skip - * title task.next - * complete subscriber.complete + record result to task context - */ - buildObservable() { - return (ctx, task) => new Observable((subscriber) => { - this._eventEmitter.on('status', (status) => { - subscriber.next(status); - }); - this._eventEmitter.on('error', (error) => { - subscriber.error(error); - if (error.context) { - ctx[this.taskId] = error.context; - } - }); - this._eventEmitter.on('skip', (reason) => { - task.skip(reason); - }); - this._eventEmitter.on('title', (title) => { - task.title = title; - }); - this._eventEmitter.on('complete', (result) => { - subscriber.complete(); - if (result) { - ctx[this.taskId] = result; - } - }); + /** + * Connect EventEmitter to Rx.Observable by mapping the listened events to subscriber's action. + * Mapping is: event observable + * status subscriber.next + * error subscriber.error + record error.context to task context + * skill task.skip + * title task.next + * complete subscriber.complete + record result to task context + */ + buildObservable() { + return (ctx, task) => + new Observable((subscriber) => { + this._eventEmitter.on("status", (status) => { + subscriber.next(status); }); - } + this._eventEmitter.on("error", (error) => { + subscriber.error(error); + if (error.context) { + ctx[this.taskId] = error.context; + } + }); + this._eventEmitter.on("skip", (reason) => { + task.skip(reason); + }); + this._eventEmitter.on("title", (title) => { + task.title = title; + }); + this._eventEmitter.on("complete", (result) => { + subscriber.complete(); + if (result) { + ctx[this.taskId] = result; + } + }); + }); + } } /** * MultiTasksView wraps Listr to inject ListrReactiveTask as the interface of each registered task. */ class MultiTasksView { - /** - * Constructor using the same options definition for Listr. - * @param {Object} options - */ - constructor(options) { - this.taskRunner = new Listr([], options); - this._listrTasks = []; - } + /** + * Constructor using the same options definition for Listr. + * @param {Object} options + */ + constructor(options) { + this.taskRunner = new Listr([], options); + this._listrTasks = []; + } - /** - * Load task as ListrReactiveTask instance. - * @param {Function} task the task handle which will be executed later, in the interface of: - * (reporter, callback) => { // use reporter and callback in the actual logic } - * @param {String} title the initial task title to be displayed - * @param {String} taskId the identifier for the task to be used to pass back result - */ - loadTask(task, title, taskId) { - const newTask = new ListrReactiveTask(task, taskId); - this._listrTasks.push(newTask); - this.taskRunner.add({ title, task: newTask.buildObservable() }); + /** + * Load task as ListrReactiveTask instance. + * @param {Function} task the task handle which will be executed later, in the interface of: + * (reporter, callback) => { // use reporter and callback in the actual logic } + * @param {String} title the initial task title to be displayed + * @param {String} taskId the identifier for the task to be used to pass back result + */ + loadTask(task, title, taskId) { + const newTask = new ListrReactiveTask(task, taskId); + this._listrTasks.push(newTask); + this.taskRunner.add({title, task: newTask.buildObservable()}); + } + + /** + * Register the event listeners and start the multi-tasks. + * @param {Function} callback (error, context) context.${taskId} contains the result for each task + */ + start(callback) { + if (this._listrTasks.length === 0) { + return callback({error: "No tasks in current multi-tasks runner."}); } - /** - * Register the event listeners and start the multi-tasks. - * @param {Function} callback (error, context) context.${taskId} contains the result for each task - */ - start(callback) { - if (this._listrTasks.length === 0) { - return callback({ error: 'No tasks in current multi-tasks runner.' }); - } + this._listrTasks.forEach((task) => { + task.execute(); + }); - this._listrTasks.forEach((task) => { - task.execute(); - }); - this.taskRunner.run().then((context) => { - callback(null, context); - }).catch((listrError) => { - const errorMessage = listrError.errors - .map(e => e.message || e).join('\n'); - callback({ - error: new CliError(errorMessage), - partialResult: listrError.context - }); + this.taskRunner + .run() + .then((context) => { + callback(null, context); + }) + .catch((listrError) => { + let errorMessage = listrError.resultMessage || listrError.message || listrError; + if (listrError.errors) { + errorMessage = listrError.errors.map((e) => e.resultMessage || e.message || e).join("\n"); + } + callback({ + error: new CliError(errorMessage), + partialResult: listrError.context, }); - } + }); + } } module.exports = MultiTasksView; diff --git a/lib/view/prompt-view.js b/lib/view/prompt-view.js deleted file mode 100644 index b4c92c3b..00000000 --- a/lib/view/prompt-view.js +++ /dev/null @@ -1,37 +0,0 @@ -const fs = require('fs'); -const inquirer = require('inquirer'); - -const stringUtils = require('@src/utils/string-utils'); - -module.exports = { - getProjectFolderName -}; - -/** - * To get user's input project folder name - * @param {string} defaultName a default project name - * @param {callback} callback { error, response } - */ -function getProjectFolderName(defaultName, callback) { - inquirer.prompt([{ - message: 'Please type in your folder name for the skill project (alphanumeric): ', - type: 'input', - default: defaultName, - name: 'projectFolderName', - validate: (input) => { - if (!input || stringUtils.filterNonAlphanumeric(input) === '') { - return 'Project folder name should consist of alphanumeric character(s) plus "-" only.'; - } - try { - fs.accessSync(process.cwd(), fs.constants.W_OK); - } catch (error) { - return `No write access inside of the folder: ${process.cwd()}.`; - } - return true; - } - }]).then((answer) => { - callback(null, stringUtils.filterNonAlphanumeric(answer.projectFolderName)); - }).catch((error) => { - callback(error); - }); -} diff --git a/lib/view/prompt-view.ts b/lib/view/prompt-view.ts new file mode 100644 index 00000000..35f933fb --- /dev/null +++ b/lib/view/prompt-view.ts @@ -0,0 +1,38 @@ +import {accessSync, constants} from "fs"; +import inquirer from "inquirer"; +import {filterNonAlphanumeric} from "../utils/string-utils"; +import {uiCallback} from "../model/callback"; + +/** + * To get user's input project folder name + * @param {string} defaultName a default project name + * @param {uiCallback} callback { error, response } + */ +export function getProjectFolderName(defaultName: string, callback: uiCallback) { + inquirer + .prompt([ + { + message: "Please type in your folder name for the skill project (alphanumeric): ", + type: "input", + default: defaultName, + name: "projectFolderName", + validate: (input) => { + if (!input || filterNonAlphanumeric(input) === "") { + return 'Project folder name should consist of alphanumeric character(s) plus "-" only.'; + } + try { + accessSync(process.cwd(), constants.W_OK); + } catch (error) { + return `No write access inside of the folder: ${process.cwd()}.`; + } + return true; + }, + }, + ]) + .then((answer) => { + callback(null, filterNonAlphanumeric(answer.projectFolderName)); + }) + .catch((error) => { + callback(error); + }); +} diff --git a/lib/view/spinner-view.js b/lib/view/spinner-view.js index 275556a3..3380b39d 100644 --- a/lib/view/spinner-view.js +++ b/lib/view/spinner-view.js @@ -1,42 +1,54 @@ -const ora = require('ora'); +const ora = require("ora"); const TERMINATE_STYLE = { - SUCCEED: 'succeed', - FAIL: 'fail', - WARN: 'warn', - INFO: 'info', - PERSIST: 'stopAndPersist', - CLEAR: 'stop' + SUCCEED: "succeed", + FAIL: "fail", + WARN: "warn", + INFO: "info", + PERSIST: "stopAndPersist", + CLEAR: "stop", }; class SpinnerView { - constructor(oraConfig) { - if (!oraConfig) { - oraConfig = {}; - } - if (!oraConfig.color) { - oraConfig.color = 'yellow'; - } - if (!oraConfig.spinner) { - oraConfig.spinner = process.platform === 'darwin' ? 'dots' : 'balloon'; - } - this.oraSpinner = ora(oraConfig); + constructor(oraConfig) { + if (!oraConfig) { + oraConfig = {}; } - - start(text) { - this.oraSpinner.start(text); + if (!oraConfig.color) { + oraConfig.color = "yellow"; } - - update(text) { - this.oraSpinner.text = text; + if (!oraConfig.spinner) { + oraConfig.spinner = process.platform === "darwin" ? "dots" : "balloon"; } + this.oraSpinner = ora(oraConfig); + } + + start(text) { + this.oraSpinner.start(text); + } - terminate(style, optionalMessage) { - if (!style) { - style = TERMINATE_STYLE.CLEAR; - } - this.oraSpinner[style](optionalMessage); + update(text) { + this.oraSpinner.text = text; + } + + terminate(style, optionalMessage) { + if (!style) { + style = TERMINATE_STYLE.CLEAR; } + this.oraSpinner[style](optionalMessage); + } + + /** + * Terminates and prints the newMessage, + * then restarts the spinner with the previous message + * @param {String} [style=succeed] - one of the TERMINATE_STYLE constants values + * @param {String} newMessage - the text to print before starting the spinner again + **/ + restart(style, newMessage) { + const originalMessage = this.oraSpinner.text; + this.terminate(style, newMessage); + this.start(originalMessage); + } } module.exports = SpinnerView; diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 00000000..c36ecc83 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,12203 @@ +{ + "name": "ask-cli", + "version": "2.29.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "ask-cli", + "version": "2.29.0", + "hasInstallScript": true, + "license": "Apache 2.0", + "dependencies": { + "@alexa/acdl": "^0.3.0", + "adm-zip": "^0.5.9", + "archiver": "^5.3.0", + "ask-smapi-model": "~1.19.7", + "ask-smapi-sdk": "^1.3.0", + "async": "^2.6.1", + "aws-profile-handler": "2.0.3", + "aws-sdk": "^2.1111.0", + "axios": "^0.26.1", + "bunyan": "^1.8.15", + "chalk": "4.0.0", + "commander": "^4.1.1", + "date-fns": "^2.28.0", + "folder-hash": "^4.0.2", + "fs-extra": "^10.0.1", + "inquirer": "^8.2.2", + "js-yaml": "^4.1.0", + "jsonfile": "^6.1.0", + "lint-staged": "^12.3.7", + "listr": "^0.14.3", + "mustache": "^4.2.0", + "nodemon": "^2.0.15", + "open": "^8.4.0", + "ora": "^3.4.0", + "portscanner": "^2.2.0", + "pretty-bytes": "^5.6.0", + "ramda": "^0.28.0", + "request": "^2.88.2", + "rxjs": "^7.5.5", + "semver": "^7.3.6", + "tmp": "^0.2.1", + "uuid": "^8.3.2", + "valid-url": "^1.0.9" + }, + "bin": { + "ask": "dist/bin/ask.js" + }, + "devDependencies": { + "@commitlint/cli": "^16.2.3", + "@commitlint/config-conventional": "^16.2.1", + "@istanbuljs/nyc-config-typescript": "^1.0.2", + "@stoplight/prism-cli": "^4.8.0", + "@types/chai": "^4.3.0", + "@types/chai-as-promised": "^7.1.5", + "@types/chai-json-schema": "^1.4.6", + "@types/chai-uuid": "^1.0.2", + "@types/fs-extra": "^9.0.13", + "@types/inquirer": "^8.2.1", + "@types/jsonfile": "^6.1.0", + "@types/listr": "0.14.4", + "@types/mocha": "^9.1.1", + "@types/portscanner": "^2.1.1", + "@types/proxyquire": "^1.3.28", + "@types/ramda": "^0.28.7", + "@types/semver": "^7.3.9", + "@types/sinon": "^10.0.11", + "@types/sinon-chai": "^3.2.8", + "@types/uuid": "^8.3.4", + "@types/vscode": "^1.34.0", + "@vscode/test-electron": "^1.6.1", + "chai": "^4.3.6", + "chai-as-promised": "^7.1.1", + "chai-json-schema": "^1.5.1", + "chai-uuid": "^1.0.6", + "copyfiles": "^2.4.1", + "husky": "^7.0.4", + "mocha": "^9.2.2", + "mocha-chai-jest-snapshot": "^1.1.3", + "mocha.parallel": "^0.15.6", + "npm-bundle": "3.0.3", + "npm-check-updates": "^12.5.8", + "nyc": "^15.1.0", + "postman-collection": "4.1.3", + "prettier": "^2.6.2", + "proxyquire": "^2.1.3", + "sinon": "^13.0.1", + "sinon-chai": "^3.7.0", + "standard-version": "^9.3.2", + "ts-node": "^10.7.0", + "typescript": "^4.6.3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@alexa/acdl": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@alexa/acdl/-/acdl-0.3.0.tgz", + "integrity": "sha512-sd4+HMCHEas1swyXctr0JlzyYS7nBy2kPEUsWHqQ5IpizJQeuDIEaIQ0SRYz8tvl3peCuvxNgFuOExhwtdu4zg==", + "dependencies": { + "@alexa/ask-expressions-spec": "^0.0.2", + "@types/fs-extra": "^9.0.13", + "ajv": "^8.6.3", + "ajv-formats": "^2.1.1", + "antlr4ts": "^0.5.0-alpha.4", + "archiver": "^5.3.0", + "ask-sdk-model-runtime": "^1.4.0", + "ask-smapi-model": "^1.20.1", + "ask-smapi-sdk": "^1.3.0", + "aws-sdk": "^2.1010.0", + "fs-extra": "^10.0.0", + "immutable": "4.0.0", + "resolve": "^1.20.0", + "source-map-support": "^0.5.20", + "yargs": "^17.1.1" + }, + "bin": { + "acc": "dist/cjs/acc.js" + } + }, + "node_modules/@alexa/acdl/node_modules/ask-smapi-model": { + "version": "1.23.0", + "integrity": "sha512-wGpHSvd1qIwqDw5YJPpga0HUFQItoT13LZAm1s4hpCcxY18vwPu5IK6w19syGztWAc2qn4k6fDDhz1UrgPm07A==", + "dependencies": { + "ask-sdk-model-runtime": "^1.1.0" + } + }, + "node_modules/@alexa/ask-expressions-spec": { + "version": "0.0.2", + "integrity": "sha512-/yk3yp6HCCtAlzujRByxY9JqHt/h1LVQE0KUKM16TlVD318gWHBH50zuSpAse5K+doCDWQYLrgxHc5etE0AKAw==" + }, + "node_modules/@ampproject/remapping": { + "version": "2.2.0", + "integrity": "sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==", + "dev": true, + "dependencies": { + "@jridgewell/gen-mapping": "^0.1.0", + "@jridgewell/trace-mapping": "^0.3.9" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.18.6", + "integrity": "sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==", + "dev": true, + "dependencies": { + "@babel/highlight": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.20.10", + "integrity": "sha512-sEnuDPpOJR/fcafHMjpcpGN5M2jbUGUHwmuWKM/YdPzeEDJg8bgmbcWQFUfE32MQjti1koACvoPVsDe8Uq+idg==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.20.12", + "integrity": "sha512-XsMfHovsUYHFMdrIHkZphTN/2Hzzi78R08NuHfDBehym2VsPDL6Zn/JAD/JQdnRvbSsbQc4mVaU1m6JgtTEElg==", + "dev": true, + "dependencies": { + "@ampproject/remapping": "^2.1.0", + "@babel/code-frame": "^7.18.6", + "@babel/generator": "^7.20.7", + "@babel/helper-compilation-targets": "^7.20.7", + "@babel/helper-module-transforms": "^7.20.11", + "@babel/helpers": "^7.20.7", + "@babel/parser": "^7.20.7", + "@babel/template": "^7.20.7", + "@babel/traverse": "^7.20.12", + "@babel/types": "^7.20.7", + "convert-source-map": "^1.7.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.2", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/core/node_modules/semver": { + "version": "6.3.0", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/generator": { + "version": "7.20.7", + "integrity": "sha512-7wqMOJq8doJMZmP4ApXTzLxSr7+oO2jroJURrVEp6XShrQUObV8Tq/D0NCcoYg2uHqUrjzO0zwBjoYzelxK+sw==", + "dev": true, + "dependencies": { + "@babel/types": "^7.20.7", + "@jridgewell/gen-mapping": "^0.3.2", + "jsesc": "^2.5.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/generator/node_modules/@jridgewell/gen-mapping": { + "version": "0.3.2", + "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", + "dev": true, + "dependencies": { + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.20.7", + "integrity": "sha512-4tGORmfQcrc+bvrjb5y3dG9Mx1IOZjsHqQVUz7XCNHO+iTmqxWnVg3KRygjGmpRLJGdQSKuvFinbIb0CnZwHAQ==", + "dev": true, + "dependencies": { + "@babel/compat-data": "^7.20.5", + "@babel/helper-validator-option": "^7.18.6", + "browserslist": "^4.21.3", + "lru-cache": "^5.1.1", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-compilation-targets/node_modules/semver": { + "version": "6.3.0", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-environment-visitor": { + "version": "7.18.9", + "integrity": "sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-function-name": { + "version": "7.19.0", + "integrity": "sha512-WAwHBINyrpqywkUH0nTnNgI5ina5TFn85HKS0pbPDfxFfhyR/aNQEn4hGi1P1JyT//I0t4OgXUlofzWILRvS5w==", + "dev": true, + "dependencies": { + "@babel/template": "^7.18.10", + "@babel/types": "^7.19.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-hoist-variables": { + "version": "7.18.6", + "integrity": "sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==", + "dev": true, + "dependencies": { + "@babel/types": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.18.6", + "integrity": "sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA==", + "dev": true, + "dependencies": { + "@babel/types": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.20.11", + "integrity": "sha512-uRy78kN4psmji1s2QtbtcCSaj/LILFDp0f/ymhpQH5QY3nljUZCaNWz9X1dEj/8MBdBEFECs7yRhKn8i7NjZgg==", + "dev": true, + "dependencies": { + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-module-imports": "^7.18.6", + "@babel/helper-simple-access": "^7.20.2", + "@babel/helper-split-export-declaration": "^7.18.6", + "@babel/helper-validator-identifier": "^7.19.1", + "@babel/template": "^7.20.7", + "@babel/traverse": "^7.20.10", + "@babel/types": "^7.20.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.20.2", + "integrity": "sha512-8RvlJG2mj4huQ4pZ+rU9lqKi9ZKiRmuvGuM2HlWmkmgOhbs6zEAw6IEiJ5cQqGbDzGZOhwuOQNtZMi/ENLjZoQ==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-simple-access": { + "version": "7.20.2", + "integrity": "sha512-+0woI/WPq59IrqDYbVGfshjT5Dmk/nnbdpcF8SnMhhXObpTq2KNBdLFRFrkVdbDOyUmHBCxzm5FHV1rACIkIbA==", + "dev": true, + "dependencies": { + "@babel/types": "^7.20.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-split-export-declaration": { + "version": "7.18.6", + "integrity": "sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==", + "dev": true, + "dependencies": { + "@babel/types": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.19.4", + "integrity": "sha512-nHtDoQcuqFmwYNYPz3Rah5ph2p8PFeFCsZk9A/48dPc/rGocJ5J3hAAZ7pb76VWX3fZKu+uEr/FhH5jLx7umrw==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.19.1", + "integrity": "sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.18.6", + "integrity": "sha512-XO7gESt5ouv/LRJdrVjkShckw6STTaB7l9BrpBaAHDeF5YZT+01PCwmR0SJHnkW6i8OwW/EVWRShfi4j2x+KQw==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.20.13", + "integrity": "sha512-nzJ0DWCL3gB5RCXbUO3KIMMsBY2Eqbx8mBpKGE/02PgyRQFcPQLbkQ1vyy596mZLaP+dAfD+R4ckASzNVmW3jg==", + "dev": true, + "dependencies": { + "@babel/template": "^7.20.7", + "@babel/traverse": "^7.20.13", + "@babel/types": "^7.20.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight": { + "version": "7.18.6", + "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==", + "dev": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.18.6", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight/node_modules/ansi-styles": { + "version": "3.2.1", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/chalk": { + "version": "2.4.2", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/color-convert": { + "version": "1.9.3", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/@babel/highlight/node_modules/color-name": { + "version": "1.1.3", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true + }, + "node_modules/@babel/highlight/node_modules/has-flag": { + "version": "3.0.0", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/supports-color": { + "version": "5.5.0", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/parser": { + "version": "7.20.13", + "integrity": "sha512-gFDLKMfpiXCsjt4za2JA9oTMn70CeseCehb11kRZgvd7+F67Hih3OHOK24cRrWECJ/ljfPGac6ygXAs/C8kIvw==", + "dev": true, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/plugin-syntax-async-generators": { + "version": "7.8.4", + "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-bigint": { + "version": "7.8.3", + "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-class-properties": { + "version": "7.12.13", + "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.12.13" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-meta": { + "version": "7.10.4", + "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-json-strings": { + "version": "7.8.3", + "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-logical-assignment-operators": { + "version": "7.10.4", + "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": { + "version": "7.8.3", + "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-numeric-separator": { + "version": "7.10.4", + "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-object-rest-spread": { + "version": "7.8.3", + "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-catch-binding": { + "version": "7.8.3", + "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-chaining": { + "version": "7.8.3", + "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-top-level-await": { + "version": "7.14.5", + "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-typescript": { + "version": "7.20.0", + "integrity": "sha512-rd9TkG+u1CExzS4SM1BlMEhMXwFLKVjOAFFCDx9PbX5ycJWDoWMcwdJH9RhkPu1dOgn5TrxLot/Gx6lWFuAUNQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.19.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/template": { + "version": "7.20.7", + "integrity": "sha512-8SegXApWe6VoNw0r9JHpSteLKTpTiLZ4rMlGIm9JQ18KiCtyQiAMEazujAHrUS5flrcqYZa75ukev3P6QmUwUw==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.18.6", + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.20.13", + "integrity": "sha512-kMJXfF0T6DIS9E8cgdLCSAL+cuCK+YEZHWiLK0SXpTo8YRj5lpJu3CDNKiIBCne4m9hhTIqUg6SYTAI39tAiVQ==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.18.6", + "@babel/generator": "^7.20.7", + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-function-name": "^7.19.0", + "@babel/helper-hoist-variables": "^7.18.6", + "@babel/helper-split-export-declaration": "^7.18.6", + "@babel/parser": "^7.20.13", + "@babel/types": "^7.20.7", + "debug": "^4.1.0", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/types": { + "version": "7.20.7", + "integrity": "sha512-69OnhBxSSgK0OzTJai4kyPDiKTIe3j+ctaHdIGVbRahTLAT7L3R9oeXHC2aVSuGYt3cVnoAMDmOCgJ2yaiLMvg==", + "dev": true, + "dependencies": { + "@babel/helper-string-parser": "^7.19.4", + "@babel/helper-validator-identifier": "^7.19.1", + "to-fast-properties": "^2.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@commitlint/cli": { + "version": "16.3.0", + "integrity": "sha512-P+kvONlfsuTMnxSwWE1H+ZcPMY3STFaHb2kAacsqoIkNx66O0T7sTpBxpxkMrFPyhkJiLJnJWMhk4bbvYD3BMA==", + "dev": true, + "dependencies": { + "@commitlint/format": "^16.2.1", + "@commitlint/lint": "^16.2.4", + "@commitlint/load": "^16.3.0", + "@commitlint/read": "^16.2.1", + "@commitlint/types": "^16.2.1", + "lodash": "^4.17.19", + "resolve-from": "5.0.0", + "resolve-global": "1.0.0", + "yargs": "^17.0.0" + }, + "bin": { + "commitlint": "cli.js" + }, + "engines": { + "node": ">=v12" + } + }, + "node_modules/@commitlint/config-conventional": { + "version": "16.2.4", + "integrity": "sha512-av2UQJa3CuE5P0dzxj/o/B9XVALqYzEViHrMXtDrW9iuflrqCStWBAioijppj9URyz6ONpohJKAtSdgAOE0gkA==", + "dev": true, + "dependencies": { + "conventional-changelog-conventionalcommits": "^4.3.1" + }, + "engines": { + "node": ">=v12" + } + }, + "node_modules/@commitlint/config-validator": { + "version": "16.2.1", + "integrity": "sha512-hogSe0WGg7CKmp4IfNbdNES3Rq3UEI4XRPB8JL4EPgo/ORq5nrGTVzxJh78omibNuB8Ho4501Czb1Er1MoDWpw==", + "dev": true, + "dependencies": { + "@commitlint/types": "^16.2.1", + "ajv": "^6.12.6" + }, + "engines": { + "node": ">=v12" + } + }, + "node_modules/@commitlint/config-validator/node_modules/ajv": { + "version": "6.12.6", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/@commitlint/config-validator/node_modules/json-schema-traverse": { + "version": "0.4.1", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "node_modules/@commitlint/ensure": { + "version": "16.2.1", + "integrity": "sha512-/h+lBTgf1r5fhbDNHOViLuej38i3rZqTQnBTk+xEg+ehOwQDXUuissQ5GsYXXqI5uGy+261ew++sT4EA3uBJ+A==", + "dev": true, + "dependencies": { + "@commitlint/types": "^16.2.1", + "lodash": "^4.17.19" + }, + "engines": { + "node": ">=v12" + } + }, + "node_modules/@commitlint/execute-rule": { + "version": "16.2.1", + "integrity": "sha512-oSls82fmUTLM6cl5V3epdVo4gHhbmBFvCvQGHBRdQ50H/690Uq1Dyd7hXMuKITCIdcnr9umyDkr8r5C6HZDF3g==", + "dev": true, + "engines": { + "node": ">=v12" + } + }, + "node_modules/@commitlint/format": { + "version": "16.2.1", + "integrity": "sha512-Yyio9bdHWmNDRlEJrxHKglamIk3d6hC0NkEUW6Ti6ipEh2g0BAhy8Od6t4vLhdZRa1I2n+gY13foy+tUgk0i1Q==", + "dev": true, + "dependencies": { + "@commitlint/types": "^16.2.1", + "chalk": "^4.0.0" + }, + "engines": { + "node": ">=v12" + } + }, + "node_modules/@commitlint/is-ignored": { + "version": "16.2.4", + "integrity": "sha512-Lxdq9aOAYCOOOjKi58ulbwK/oBiiKz+7Sq0+/SpFIEFwhHkIVugvDvWjh2VRBXmRC/x5lNcjDcYEwS/uYUvlYQ==", + "dev": true, + "dependencies": { + "@commitlint/types": "^16.2.1", + "semver": "7.3.7" + }, + "engines": { + "node": ">=v12" + } + }, + "node_modules/@commitlint/is-ignored/node_modules/lru-cache": { + "version": "6.0.0", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@commitlint/is-ignored/node_modules/semver": { + "version": "7.3.7", + "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@commitlint/is-ignored/node_modules/yallist": { + "version": "4.0.0", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/@commitlint/lint": { + "version": "16.2.4", + "integrity": "sha512-AUDuwOxb2eGqsXbTMON3imUGkc1jRdtXrbbohiLSCSk3jFVXgJLTMaEcr39pR00N8nE9uZ+V2sYaiILByZVmxQ==", + "dev": true, + "dependencies": { + "@commitlint/is-ignored": "^16.2.4", + "@commitlint/parse": "^16.2.1", + "@commitlint/rules": "^16.2.4", + "@commitlint/types": "^16.2.1" + }, + "engines": { + "node": ">=v12" + } + }, + "node_modules/@commitlint/load": { + "version": "16.3.0", + "integrity": "sha512-3tykjV/iwbkv2FU9DG+NZ/JqmP0Nm3b7aDwgCNQhhKV5P74JAuByULkafnhn+zsFGypG1qMtI5u+BZoa9APm0A==", + "dev": true, + "dependencies": { + "@commitlint/config-validator": "^16.2.1", + "@commitlint/execute-rule": "^16.2.1", + "@commitlint/resolve-extends": "^16.2.1", + "@commitlint/types": "^16.2.1", + "@types/node": ">=12", + "chalk": "^4.0.0", + "cosmiconfig": "^7.0.0", + "cosmiconfig-typescript-loader": "^2.0.0", + "lodash": "^4.17.19", + "resolve-from": "^5.0.0", + "typescript": "^4.4.3" + }, + "engines": { + "node": ">=v12" + } + }, + "node_modules/@commitlint/message": { + "version": "16.2.1", + "integrity": "sha512-2eWX/47rftViYg7a3axYDdrgwKv32mxbycBJT6OQY/MJM7SUfYNYYvbMFOQFaA4xIVZt7t2Alyqslbl6blVwWw==", + "dev": true, + "engines": { + "node": ">=v12" + } + }, + "node_modules/@commitlint/parse": { + "version": "16.2.1", + "integrity": "sha512-2NP2dDQNL378VZYioLrgGVZhWdnJO4nAxQl5LXwYb08nEcN+cgxHN1dJV8OLJ5uxlGJtDeR8UZZ1mnQ1gSAD/g==", + "dev": true, + "dependencies": { + "@commitlint/types": "^16.2.1", + "conventional-changelog-angular": "^5.0.11", + "conventional-commits-parser": "^3.2.2" + }, + "engines": { + "node": ">=v12" + } + }, + "node_modules/@commitlint/read": { + "version": "16.2.1", + "integrity": "sha512-tViXGuaxLTrw2r7PiYMQOFA2fueZxnnt0lkOWqKyxT+n2XdEMGYcI9ID5ndJKXnfPGPppD0w/IItKsIXlZ+alw==", + "dev": true, + "dependencies": { + "@commitlint/top-level": "^16.2.1", + "@commitlint/types": "^16.2.1", + "fs-extra": "^10.0.0", + "git-raw-commits": "^2.0.0" + }, + "engines": { + "node": ">=v12" + } + }, + "node_modules/@commitlint/resolve-extends": { + "version": "16.2.1", + "integrity": "sha512-NbbCMPKTFf2J805kwfP9EO+vV+XvnaHRcBy6ud5dF35dxMsvdJqke54W3XazXF1ZAxC4a3LBy4i/GNVBAthsEg==", + "dev": true, + "dependencies": { + "@commitlint/config-validator": "^16.2.1", + "@commitlint/types": "^16.2.1", + "import-fresh": "^3.0.0", + "lodash": "^4.17.19", + "resolve-from": "^5.0.0", + "resolve-global": "^1.0.0" + }, + "engines": { + "node": ">=v12" + } + }, + "node_modules/@commitlint/rules": { + "version": "16.2.4", + "integrity": "sha512-rK5rNBIN2ZQNQK+I6trRPK3dWa0MtaTN4xnwOma1qxa4d5wQMQJtScwTZjTJeallFxhOgbNOgr48AMHkdounVg==", + "dev": true, + "dependencies": { + "@commitlint/ensure": "^16.2.1", + "@commitlint/message": "^16.2.1", + "@commitlint/to-lines": "^16.2.1", + "@commitlint/types": "^16.2.1", + "execa": "^5.0.0" + }, + "engines": { + "node": ">=v12" + } + }, + "node_modules/@commitlint/to-lines": { + "version": "16.2.1", + "integrity": "sha512-9/VjpYj5j1QeY3eiog1zQWY6axsdWAc0AonUUfyZ7B0MVcRI0R56YsHAfzF6uK/g/WwPZaoe4Lb1QCyDVnpVaQ==", + "dev": true, + "engines": { + "node": ">=v12" + } + }, + "node_modules/@commitlint/top-level": { + "version": "16.2.1", + "integrity": "sha512-lS6GSieHW9y6ePL73ied71Z9bOKyK+Ib9hTkRsB8oZFAyQZcyRwq2w6nIa6Fngir1QW51oKzzaXfJL94qwImyw==", + "dev": true, + "dependencies": { + "find-up": "^5.0.0" + }, + "engines": { + "node": ">=v12" + } + }, + "node_modules/@commitlint/types": { + "version": "16.2.1", + "integrity": "sha512-7/z7pA7BM0i8XvMSBynO7xsB3mVQPUZbVn6zMIlp/a091XJ3qAXRXc+HwLYhiIdzzS5fuxxNIHZMGHVD4HJxdA==", + "dev": true, + "dependencies": { + "chalk": "^4.0.0" + }, + "engines": { + "node": ">=v12" + } + }, + "node_modules/@cspotcode/source-map-support": { + "version": "0.8.1", + "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", + "dev": true, + "dependencies": { + "@jridgewell/trace-mapping": "0.3.9" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@cspotcode/source-map-support/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.9", + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "dev": true, + "dependencies": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, + "node_modules/@faker-js/faker": { + "version": "6.3.1", + "integrity": "sha512-8YXBE2ZcU/pImVOHX7MWrSR/X5up7t6rPWZlk34RwZEcdr3ua6X+32pSd6XuOQRN+vbuvYNfA6iey8NbrjuMFQ==", + "dev": true, + "engines": { + "node": ">=14.0.0", + "npm": ">=6.0.0" + } + }, + "node_modules/@gar/promisify": { + "version": "1.1.3", + "integrity": "sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==", + "dev": true + }, + "node_modules/@hutson/parse-repository-url": { + "version": "3.0.2", + "integrity": "sha512-H9XAx3hc0BQHY6l+IFSWHDySypcXsvsuLhgYLUGywmJ5pswRVQJUHpOsobnLYp2ZUaUlKiKDrgWWhosOwAEM8Q==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@istanbuljs/load-nyc-config": { + "version": "1.1.0", + "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", + "dev": true, + "dependencies": { + "camelcase": "^5.3.1", + "find-up": "^4.1.0", + "get-package-type": "^0.1.0", + "js-yaml": "^3.13.1", + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/argparse": { + "version": "1.0.10", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/find-up": { + "version": "4.1.0", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/js-yaml": { + "version": "3.14.1", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/locate-path": { + "version": "5.0.0", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/p-limit": { + "version": "2.3.0", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/p-locate": { + "version": "4.1.0", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/nyc-config-typescript": { + "version": "1.0.2", + "integrity": "sha512-iKGIyMoyJuFnJRSVTZ78POIRvNnwZaWIf8vG4ZS3rQq58MMDrqEX2nnzx0R28V2X8JvmKYiqY9FP2hlJsm8A0w==", + "dev": true, + "dependencies": { + "@istanbuljs/schema": "^0.1.2" + }, + "engines": { + "node": ">=8" + }, + "peerDependencies": { + "nyc": ">=15" + } + }, + "node_modules/@istanbuljs/schema": { + "version": "0.1.3", + "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/console": { + "version": "28.1.3", + "integrity": "sha512-QPAkP5EwKdK/bxIr6C1I4Vs0rm2nHiANzj/Z5X2JQkrZo6IqvC4ldZ9K95tF0HdidhA8Bo6egxSzUFPYKcEXLw==", + "dev": true, + "dependencies": { + "@jest/types": "^28.1.3", + "@types/node": "*", + "chalk": "^4.0.0", + "jest-message-util": "^28.1.3", + "jest-util": "^28.1.3", + "slash": "^3.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/@jest/expect-utils": { + "version": "28.1.3", + "integrity": "sha512-wvbi9LUrHJLn3NlDW6wF2hvIMtd4JUl2QNVrjq+IBSHirgfrR3o9RnVtxzdEGO2n9JyIWwHnLfby5KzqBGg2YA==", + "dev": true, + "dependencies": { + "jest-get-type": "^28.0.2" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/@jest/schemas": { + "version": "28.1.3", + "integrity": "sha512-/l/VWsdt/aBXgjshLWOFyFt3IVdYypu5y2Wn2rOO1un6nkqIn8SLXzgIMYXFyYsRWDyF5EthmKJMIdJvk08grg==", + "dev": true, + "dependencies": { + "@sinclair/typebox": "^0.24.1" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/@jest/test-result": { + "version": "28.1.3", + "integrity": "sha512-kZAkxnSE+FqE8YjW8gNuoVkkC9I7S1qmenl8sGcDOLropASP+BkcGKwhXoyqQuGOGeYY0y/ixjrd/iERpEXHNg==", + "dev": true, + "dependencies": { + "@jest/console": "^28.1.3", + "@jest/types": "^28.1.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "collect-v8-coverage": "^1.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/@jest/transform": { + "version": "28.1.3", + "integrity": "sha512-u5dT5di+oFI6hfcLOHGTAfmUxFRrjK+vnaP0kkVow9Md/M7V/MxqQMOz/VV25UZO8pzeA9PjfTpOu6BDuwSPQA==", + "dev": true, + "dependencies": { + "@babel/core": "^7.11.6", + "@jest/types": "^28.1.3", + "@jridgewell/trace-mapping": "^0.3.13", + "babel-plugin-istanbul": "^6.1.1", + "chalk": "^4.0.0", + "convert-source-map": "^1.4.0", + "fast-json-stable-stringify": "^2.0.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^28.1.3", + "jest-regex-util": "^28.0.2", + "jest-util": "^28.1.3", + "micromatch": "^4.0.4", + "pirates": "^4.0.4", + "slash": "^3.0.0", + "write-file-atomic": "^4.0.1" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/@jest/types": { + "version": "28.1.3", + "integrity": "sha512-RyjiyMUZrKz/c+zlMFO1pm70DcIlST8AeWTkoUdZevew44wcNZQHsEVOiCVtgVnlFFD82FPaXycys58cf2muVQ==", + "dev": true, + "dependencies": { + "@jest/schemas": "^28.1.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^17.0.8", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.1.1", + "integrity": "sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==", + "dev": true, + "dependencies": { + "@jridgewell/set-array": "^1.0.0", + "@jridgewell/sourcemap-codec": "^1.4.10" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.0", + "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/set-array": { + "version": "1.1.2", + "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.4.14", + "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", + "dev": true + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.17", + "integrity": "sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g==", + "dev": true, + "dependencies": { + "@jridgewell/resolve-uri": "3.1.0", + "@jridgewell/sourcemap-codec": "1.4.14" + } + }, + "node_modules/@jsdevtools/ono": { + "version": "7.1.3", + "integrity": "sha512-4JQNk+3mVzK3xh2rqd6RB4J46qUR19azEHBneZyTZM+c456qOrbbM/5xcR8huNCCcbVt7+UmizG6GuUvPvKUYg==", + "dev": true + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@npmcli/fs": { + "version": "2.1.2", + "integrity": "sha512-yOJKRvohFOaLqipNtwYB9WugyZKhC/DZC4VYPmpaCzDBrA8YpK3qHZ8/HGscMnE4GqbkLNuVcCnxkeQEdGt6LQ==", + "dev": true, + "dependencies": { + "@gar/promisify": "^1.1.3", + "semver": "^7.3.5" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/@npmcli/git": { + "version": "3.0.2", + "integrity": "sha512-CAcd08y3DWBJqJDpfuVL0uijlq5oaXaOJEKHKc4wqrjd00gkvTZB+nFuLn+doOOKddaQS9JfqtNoFCO2LCvA3w==", + "dev": true, + "dependencies": { + "@npmcli/promise-spawn": "^3.0.0", + "lru-cache": "^7.4.4", + "mkdirp": "^1.0.4", + "npm-pick-manifest": "^7.0.0", + "proc-log": "^2.0.0", + "promise-inflight": "^1.0.1", + "promise-retry": "^2.0.1", + "semver": "^7.3.5", + "which": "^2.0.2" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/@npmcli/git/node_modules/lru-cache": { + "version": "7.14.1", + "integrity": "sha512-ysxwsnTKdAx96aTRdhDOCQfDgbHnt8SK0KY8SEjO0wHinhWOFTESbjVCMPbU1uGXg/ch4lifqx0wfjOawU2+WA==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/@npmcli/git/node_modules/mkdirp": { + "version": "1.0.4", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true, + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@npmcli/installed-package-contents": { + "version": "1.0.7", + "integrity": "sha512-9rufe0wnJusCQoLpV9ZPKIVP55itrM5BxOXs10DmdbRfgWtHy1LDyskbwRnBghuB0PrF7pNPOqREVtpz4HqzKw==", + "dev": true, + "dependencies": { + "npm-bundled": "^1.1.1", + "npm-normalize-package-bin": "^1.0.1" + }, + "bin": { + "installed-package-contents": "index.js" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/@npmcli/move-file": { + "version": "2.0.1", + "integrity": "sha512-mJd2Z5TjYWq/ttPLLGqArdtnC74J6bOzg4rMDnN+p1xTacZ2yPRCk2y0oSWQtygLR9YVQXgOcONrwtnk3JupxQ==", + "deprecated": "This functionality has been moved to @npmcli/fs", + "dev": true, + "dependencies": { + "mkdirp": "^1.0.4", + "rimraf": "^3.0.2" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/@npmcli/move-file/node_modules/mkdirp": { + "version": "1.0.4", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true, + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@npmcli/node-gyp": { + "version": "2.0.0", + "integrity": "sha512-doNI35wIe3bBaEgrlPfdJPaCpUR89pJWep4Hq3aRdh6gKazIVWfs0jHttvSSoq47ZXgC7h73kDsUl8AoIQUB+A==", + "dev": true, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/@npmcli/promise-spawn": { + "version": "3.0.0", + "integrity": "sha512-s9SgS+p3a9Eohe68cSI3fi+hpcZUmXq5P7w0kMlAsWVtR7XbK3ptkZqKT2cK1zLDObJ3sR+8P59sJE0w/KTL1g==", + "dev": true, + "dependencies": { + "infer-owner": "^1.0.4" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/@npmcli/run-script": { + "version": "4.2.1", + "integrity": "sha512-7dqywvVudPSrRCW5nTHpHgeWnbBtz8cFkOuKrecm6ih+oO9ciydhWt6OF7HlqupRRmB8Q/gECVdB9LMfToJbRg==", + "dev": true, + "dependencies": { + "@npmcli/node-gyp": "^2.0.0", + "@npmcli/promise-spawn": "^3.0.0", + "node-gyp": "^9.0.0", + "read-package-json-fast": "^2.0.3", + "which": "^2.0.2" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/@samverschueren/stream-to-observable": { + "version": "0.3.1", + "integrity": "sha512-c/qwwcHyafOQuVQJj0IlBjf5yYgBI7YPJ77k4fOJYesb41jio65eaJODRUmfYKhTOFBrIZ66kgvGPlNbjuoRdQ==", + "dependencies": { + "any-observable": "^0.3.0" + }, + "engines": { + "node": ">=6" + }, + "peerDependenciesMeta": { + "rxjs": { + "optional": true + }, + "zen-observable": { + "optional": true + } + } + }, + "node_modules/@sinclair/typebox": { + "version": "0.24.51", + "integrity": "sha512-1P1OROm/rdubP5aFDSZQILU0vrLCJ4fvHt6EoqHEM+2D/G5MK3bIaymUKLit8Js9gbns5UyJnkP/TZROLw4tUA==", + "dev": true + }, + "node_modules/@sindresorhus/is": { + "version": "0.14.0", + "integrity": "sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/@sinonjs/commons": { + "version": "1.8.6", + "integrity": "sha512-Ky+XkAkqPZSm3NLBeUng77EBQl3cmeJhITaGHdYH8kjVB+aun3S4XBRti2zt17mtt0mIUDiNxYeoJm6drVvBJQ==", + "dev": true, + "dependencies": { + "type-detect": "4.0.8" + } + }, + "node_modules/@sinonjs/fake-timers": { + "version": "9.1.2", + "integrity": "sha512-BPS4ynJW/o92PUR4wgriz2Ud5gpST5vz6GQfMixEDK0Z8ZCUv2M7SkBLykH56T++Xs+8ln9zTGbOvNGIe02/jw==", + "dev": true, + "dependencies": { + "@sinonjs/commons": "^1.7.0" + } + }, + "node_modules/@sinonjs/samsam": { + "version": "6.1.3", + "integrity": "sha512-nhOb2dWPeb1sd3IQXL/dVPnKHDOAFfvichtBf4xV00/rU1QbPCQqKMbvIheIjqwVjh7qIgf2AHTHi391yMOMpQ==", + "dev": true, + "dependencies": { + "@sinonjs/commons": "^1.6.0", + "lodash.get": "^4.4.2", + "type-detect": "^4.0.8" + } + }, + "node_modules/@sinonjs/text-encoding": { + "version": "0.7.2", + "integrity": "sha512-sXXKG+uL9IrKqViTtao2Ws6dy0znu9sOaP1di/jKGW1M6VssO8vlpXCQcpZ+jisQ1tTFAC5Jo/EOzFbggBagFQ==", + "dev": true + }, + "node_modules/@stoplight/http-spec": { + "version": "5.5.2", + "integrity": "sha512-WW2CeTxIuvbT59lm+n47iyxLHO/Uj73Mnta2uW39WdE3uUkJIEqovFJPflsIrJCXUcNIIwLuB+I6ZMTuTGK2Uw==", + "dev": true, + "dependencies": { + "@stoplight/json": "^3.18.1", + "@stoplight/json-schema-generator": "1.0.1", + "@stoplight/types": "^13.6.0", + "@types/json-schema": "7.0.11", + "@types/swagger-schema-official": "~2.0.22", + "@types/type-is": "^1.6.3", + "fnv-plus": "^1.3.1", + "lodash.isequalwith": "^4.4.0", + "lodash.pick": "^4.4.0", + "lodash.pickby": "^4.6.0", + "openapi3-ts": "^2.0.2", + "postman-collection": "^4.1.2", + "tslib": "^2.3.1", + "type-is": "^1.6.18" + }, + "engines": { + "node": ">=14.13" + } + }, + "node_modules/@stoplight/json": { + "version": "3.20.1", + "integrity": "sha512-FXfud+uWgIj1xv6nUO9WnmgmnVikaxJcbtR4XQt4C42n5c2qua3U05Z/3B57hP5TJRSj+tpn9ID6/bFeyYYlEg==", + "dev": true, + "dependencies": { + "@stoplight/ordered-object-literal": "^1.0.3", + "@stoplight/path": "^1.3.2", + "@stoplight/types": "^13.6.0", + "jsonc-parser": "~2.2.1", + "lodash": "^4.17.21", + "safe-stable-stringify": "^1.1" + }, + "engines": { + "node": ">=8.3.0" + } + }, + "node_modules/@stoplight/json-schema-generator": { + "version": "1.0.1", + "integrity": "sha512-b9WT8Z5M7Nc/O6+JVEMvOdkLR1fePbCHnPlOpnRFxp+pkfM+VRwLaD4toWRpnpBlHXphRfDxFj5/zxcVvqeKDA==", + "dev": true, + "dependencies": { + "json-promise": "1.1.x", + "minimist": "1.2.6", + "mkdirp": "0.5.x", + "pretty-data": "0.40.x", + "request": "2.x.x" + }, + "bin": { + "json-schema-generator": "bin/cli.js" + } + }, + "node_modules/@stoplight/json-schema-merge-allof": { + "version": "0.7.8", + "integrity": "sha512-JTDt6GYpCWQSb7+UW1P91IAp/pcLWis0mmEzWVFcLsrNgtUYK7JLtYYz0ZPSR4QVL0fJ0YQejM+MPq5iNDFO4g==", + "dev": true, + "dependencies": { + "compute-lcm": "^1.1.0", + "json-schema-compare": "^0.2.2", + "lodash": "^4.17.4" + } + }, + "node_modules/@stoplight/json-schema-ref-parser": { + "version": "9.2.1", + "integrity": "sha512-iKWeomA0HHDcbG0G8yVzQFs9y5vtF/GtjEDSuhofdHcPxXMhnTUh8d9NdbhXPCVhwIRmdvzP3jMv2A3747hyWg==", + "dev": true, + "dependencies": { + "@jsdevtools/ono": "^7.1.3", + "@stoplight/path": "^1.3.2", + "@stoplight/yaml": "^4.0.2", + "abort-controller": "^3.0.0", + "call-me-maybe": "^1.0.1", + "fastestsmallesttextencoderdecoder": "^1.0.22", + "isomorphic-fetch": "^3.0.0" + } + }, + "node_modules/@stoplight/json-schema-sampler": { + "version": "0.2.2", + "integrity": "sha512-QP4ZwXh3dEn5wHZs2361kdf4BmaKiiP+pxIImAuVTLmulv9sBTB+ETG7Y5z9u4DOUQu2GNxfUY10iSwuBQMXrg==", + "dev": true, + "dependencies": { + "@types/json-schema": "^7.0.7", + "json-pointer": "^0.6.1" + } + }, + "node_modules/@stoplight/ordered-object-literal": { + "version": "1.0.4", + "integrity": "sha512-OF8uib1jjDs5/cCU+iOVy+GJjU3X7vk/qJIkIJFqwmlJKrrtijFmqwbu8XToXrwTYLQTP+Hebws5gtZEmk9jag==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@stoplight/path": { + "version": "1.3.2", + "integrity": "sha512-lyIc6JUlUA8Ve5ELywPC8I2Sdnh1zc1zmbYgVarhXIp9YeAB0ReeqmGEOWNtlHkbP2DAA1AL65Wfn2ncjK/jtQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@stoplight/prism-cli": { + "version": "4.10.5", + "integrity": "sha512-1DB3fNM+Lj7oSgfFQK+Zc8TY1lK4S5I9KB5hhJbTjqXFXhYNWucmDxcTyQWiNTp/FBOxGtuMpg+z0sr27Z/vkw==", + "dev": true, + "dependencies": { + "@stoplight/http-spec": "^5.5.2", + "@stoplight/json": "^3.18.1", + "@stoplight/json-schema-ref-parser": "9.2.1", + "@stoplight/prism-core": "^4.10.5", + "@stoplight/prism-http": "^4.10.5", + "@stoplight/prism-http-server": "^4.10.5", + "@stoplight/types": "^13.6.0", + "chalk": "^4.1.2", + "chokidar": "^3.5.2", + "fp-ts": "^2.11.5", + "json-schema-faker": "0.5.0-rcv.40", + "lodash": "^4.17.21", + "node-fetch": "^2.6.5", + "pino": "^6.13.3", + "signale": "^1.4.0", + "split2": "^3.2.2", + "tslib": "^2.3.1", + "uri-template-lite": "^22.9.0", + "urijs": "^1.19.11", + "yargs": "^16.2.0" + }, + "bin": { + "prism": "dist/index.js" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/@stoplight/prism-cli/node_modules/chalk": { + "version": "4.1.2", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@stoplight/prism-cli/node_modules/cliui": { + "version": "7.0.4", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "dev": true, + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "node_modules/@stoplight/prism-cli/node_modules/yargs": { + "version": "16.2.0", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "dev": true, + "dependencies": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@stoplight/prism-core": { + "version": "4.10.5", + "integrity": "sha512-HF6ScLTvW1J8scylJKoYh3k7vXGKTjOw3l8w7XpOoCM0VUDGG3w+9GBzTMmLCLpvvC+m1gaaTk1j58m8p2P11A==", + "dev": true, + "dependencies": { + "fp-ts": "^2.11.5", + "lodash": "^4.17.21", + "pino": "^6.13.3", + "tslib": "^2.3.1" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/@stoplight/prism-http": { + "version": "4.10.5", + "integrity": "sha512-jlA0oF4n1cUf9kfmGf3mWcXbbeyHRFqYObeIbfgPmc4WcmQLEKOw4pDOo1xpmO516PLHEeqtyd4EtRGtn/JZHg==", + "dev": true, + "dependencies": { + "@faker-js/faker": "^6.0.0", + "@stoplight/json": "^3.18.1", + "@stoplight/json-schema-merge-allof": "0.7.8", + "@stoplight/json-schema-sampler": "0.2.2", + "@stoplight/prism-core": "^4.10.5", + "@stoplight/types": "^13.0.0", + "@stoplight/yaml": "^4.2.3", + "abstract-logging": "^2.0.1", + "accepts": "^1.3.7", + "ajv": "^8.4.0", + "ajv-formats": "^2.1.1", + "caseless": "^0.12.0", + "content-type": "^1.0.4", + "fp-ts": "^2.11.5", + "http-proxy-agent": "^5.0.0", + "https-proxy-agent": "^5.0.0", + "json-schema-faker": "0.5.0-rcv.40", + "lodash": "^4.17.21", + "node-fetch": "^2.6.5", + "pino": "^6.13.3", + "tslib": "^2.3.1", + "type-is": "^1.6.18", + "uri-template-lite": "^22.9.0" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/@stoplight/prism-http-server": { + "version": "4.10.5", + "integrity": "sha512-rUFYVxnL/8+PVuwP9Bca5K+sv4QorpHcSyO6lj2/e8lwaWxMcUjXBZwxo8Qc7sr4baO+thM5yhlMmN7zc5mtYA==", + "dev": true, + "dependencies": { + "@stoplight/prism-core": "^4.10.5", + "@stoplight/prism-http": "^4.10.5", + "@stoplight/types": "^13.0.0", + "fast-xml-parser": "^3.20.3", + "fp-ts": "^2.11.5", + "io-ts": "^2.2.16", + "lodash": "^4.17.21", + "micri": "^4.3.0", + "node-fetch": "^2.6.5", + "parse-prefer-header": "1.0.0", + "tslib": "^2.3.1", + "type-is": "^1.6.18" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/@stoplight/types": { + "version": "13.8.0", + "integrity": "sha512-5glKswz7y9aACh+a+JegID+4xX//4TsIdv7iPl29hWnOoWrnlPbg3Gjc4nYUXXgMSaSlSsA15JU/0+rE89fR4A==", + "dev": true, + "dependencies": { + "@types/json-schema": "^7.0.4", + "utility-types": "^3.10.0" + }, + "engines": { + "node": "^12.20 || >=14.13" + } + }, + "node_modules/@stoplight/yaml": { + "version": "4.2.3", + "integrity": "sha512-Mx01wjRAR9C7yLMUyYFTfbUf5DimEpHMkRDQ1PKLe9dfNILbgdxyrncsOXM3vCpsQ1Hfj4bPiGl+u4u6e9Akqw==", + "dev": true, + "dependencies": { + "@stoplight/ordered-object-literal": "^1.0.1", + "@stoplight/types": "^13.0.0", + "@stoplight/yaml-ast-parser": "0.0.48", + "tslib": "^2.2.0" + }, + "engines": { + "node": ">=10.8" + } + }, + "node_modules/@stoplight/yaml-ast-parser": { + "version": "0.0.48", + "integrity": "sha512-sV+51I7WYnLJnKPn2EMWgS4EUfoP4iWEbrWwbXsj0MZCB/xOK8j6+C9fntIdOM50kpx45ZLC3s6kwKivWuqvyg==", + "dev": true + }, + "node_modules/@szmarczak/http-timer": { + "version": "1.1.2", + "integrity": "sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA==", + "dev": true, + "dependencies": { + "defer-to-connect": "^1.0.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@tootallnate/once": { + "version": "2.0.0", + "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", + "dev": true, + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tsconfig/node10": { + "version": "1.0.9", + "integrity": "sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==", + "dev": true + }, + "node_modules/@tsconfig/node12": { + "version": "1.0.11", + "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", + "dev": true + }, + "node_modules/@tsconfig/node14": { + "version": "1.0.3", + "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", + "dev": true + }, + "node_modules/@tsconfig/node16": { + "version": "1.0.3", + "integrity": "sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ==", + "dev": true + }, + "node_modules/@types/babel__traverse": { + "version": "7.18.3", + "integrity": "sha512-1kbcJ40lLB7MHsj39U4Sh1uTd2E7rLEa79kmDpI6cy+XiXsteB3POdQomoq4FxszMrO3ZYchkhYJw7A2862b3w==", + "dev": true, + "dependencies": { + "@babel/types": "^7.3.0" + } + }, + "node_modules/@types/chai": { + "version": "4.3.4", + "integrity": "sha512-KnRanxnpfpjUTqTCXslZSEdLfXExwgNxYPdiO2WGUj8+HDjFi8R3k5RVKPeSCzLjCcshCAtVO2QBbVuAV4kTnw==", + "dev": true + }, + "node_modules/@types/chai-as-promised": { + "version": "7.1.5", + "integrity": "sha512-jStwss93SITGBwt/niYrkf2C+/1KTeZCZl1LaeezTlqppAKeoQC7jxyqYuP72sxBGKCIbw7oHgbYssIRzT5FCQ==", + "dev": true, + "dependencies": { + "@types/chai": "*" + } + }, + "node_modules/@types/chai-json-schema": { + "version": "1.4.6", + "integrity": "sha512-Z+zM4XwNkno4nWkKkbeLvf6IZTnA7ffGpX0QAcql0wQdKniGc849Leblx4ojRsv7IjS4Ct16MGr1SLNrJQZsRg==", + "dev": true, + "dependencies": { + "@types/tv4": "*" + } + }, + "node_modules/@types/chai-uuid": { + "version": "1.0.2", + "integrity": "sha512-bT/Y19gztsbE5ZvKBCMHf6Ziiw3e3l2v962ycLIksjJEd85YSW+L3jrj6wO4yA53d6CRKifZ09QDa73OA2VUDw==", + "dev": true, + "dependencies": { + "@types/chai": "*", + "@types/node": "*" + } + }, + "node_modules/@types/fs-extra": { + "version": "9.0.13", + "integrity": "sha512-nEnwB++1u5lVDM2UI4c1+5R+FYaKfaAzS4OococimjVm3nQw3TuzH5UNsocrcTBbhnerblyHj4A49qXbIiZdpA==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/graceful-fs": { + "version": "4.1.6", + "integrity": "sha512-Sig0SNORX9fdW+bQuTEovKj3uHcUL6LQKbCrrqb1X7J6/ReAbhCXRAhc+SMejhLELFj2QcyuxmUooZ4bt5ReSw==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/inquirer": { + "version": "8.2.5", + "integrity": "sha512-QXlzybid60YtAwfgG3cpykptRYUx2KomzNutMlWsQC64J/WG/gQSl+P4w7A21sGN0VIxRVava4rgnT7FQmFCdg==", + "dev": true, + "dependencies": { + "@types/through": "*" + } + }, + "node_modules/@types/istanbul-lib-coverage": { + "version": "2.0.4", + "integrity": "sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g==", + "dev": true + }, + "node_modules/@types/istanbul-lib-report": { + "version": "3.0.0", + "integrity": "sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg==", + "dev": true, + "dependencies": { + "@types/istanbul-lib-coverage": "*" + } + }, + "node_modules/@types/istanbul-reports": { + "version": "3.0.1", + "integrity": "sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw==", + "dev": true, + "dependencies": { + "@types/istanbul-lib-report": "*" + } + }, + "node_modules/@types/json-schema": { + "version": "7.0.11", + "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==", + "dev": true + }, + "node_modules/@types/jsonfile": { + "version": "6.1.1", + "integrity": "sha512-GSgiRCVeapDN+3pqA35IkQwasaCh/0YFH5dEF6S88iDvEn901DjOeH3/QPY+XYP1DFzDZPvIvfeEgk+7br5png==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/listr": { + "version": "0.14.4", + "resolved": "https://registry.npmjs.org/@types/listr/-/listr-0.14.4.tgz", + "integrity": "sha512-+MWvidNujBUgJsi4yMVwEQQwaHe6oHedPSy+dwk3akGEeuIbvhWkK+TGsXSwbFup7Y0cCBb+wzzdD+yGKp7sOg==", + "dev": true, + "dependencies": { + "@types/node": "*", + "rxjs": "^6.5.1" + } + }, + "node_modules/@types/listr/node_modules/rxjs": { + "version": "6.6.7", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz", + "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==", + "dev": true, + "dependencies": { + "tslib": "^1.9.0" + }, + "engines": { + "npm": ">=2.0.0" + } + }, + "node_modules/@types/listr/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + }, + "node_modules/@types/minimist": { + "version": "1.2.2", + "integrity": "sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ==", + "dev": true + }, + "node_modules/@types/mocha": { + "version": "9.1.1", + "integrity": "sha512-Z61JK7DKDtdKTWwLeElSEBcWGRLY8g95ic5FoQqI9CMx0ns/Ghep3B4DfcEimiKMvtamNVULVNKEsiwV3aQmXw==", + "dev": true + }, + "node_modules/@types/node": { + "version": "18.11.18", + "integrity": "sha512-DHQpWGjyQKSHj3ebjFI/wRKcqQcdR+MoFBygntYOZytCqNfkd2ZC4ARDJ2DQqhjH5p85Nnd3jhUJIXrszFX/JA==" + }, + "node_modules/@types/normalize-package-data": { + "version": "2.4.1", + "integrity": "sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==", + "dev": true + }, + "node_modules/@types/parse-json": { + "version": "4.0.0", + "integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==", + "dev": true + }, + "node_modules/@types/portscanner": { + "version": "2.1.1", + "integrity": "sha512-1NsVIbgBKvrqxwtMN0V6CLji1ERwKSI/RWz0J3y++CzSwYNGBStCfpIFgxV3ZwxsDR5PoZqoUWhwraDm+Ztn0Q==", + "dev": true + }, + "node_modules/@types/prettier": { + "version": "2.7.2", + "integrity": "sha512-KufADq8uQqo1pYKVIYzfKbJfBAc0sOeXqGbFaSpv8MRmC/zXgowNZmFcbngndGk922QDmOASEXUZCaY48gs4cg==", + "dev": true + }, + "node_modules/@types/proxyquire": { + "version": "1.3.28", + "integrity": "sha512-SQaNzWQ2YZSr7FqAyPPiA3FYpux2Lqh3HWMZQk47x3xbMCqgC/w0dY3dw9rGqlweDDkrySQBcaScXWeR+Yb11Q==", + "dev": true + }, + "node_modules/@types/ramda": { + "version": "0.28.22", + "integrity": "sha512-DoIfh0sBxrL/aqADk+SGrfjJT9cB8modg+4NRlF7/Tfg4N2+KBEkAgpYYzrjiZxxR5YzWizjfVrTEdVDwYK7xQ==", + "dev": true, + "dependencies": { + "ts-toolbelt": "^6.15.1" + } + }, + "node_modules/@types/semver": { + "version": "7.3.13", + "integrity": "sha512-21cFJr9z3g5dW8B0CVI9g2O9beqaThGQ6ZFBqHfwhzLDKUxaqTIy3vnfah/UPkfOiF2pLq+tGz+W8RyCskuslw==", + "dev": true + }, + "node_modules/@types/sinon": { + "version": "10.0.13", + "integrity": "sha512-UVjDqJblVNQYvVNUsj0PuYYw0ELRmgt1Nt5Vk0pT5f16ROGfcKJY8o1HVuMOJOpD727RrGB9EGvoaTQE5tgxZQ==", + "dev": true, + "dependencies": { + "@types/sinonjs__fake-timers": "*" + } + }, + "node_modules/@types/sinon-chai": { + "version": "3.2.9", + "integrity": "sha512-/19t63pFYU0ikrdbXKBWj9PCdnKyTd0Qkz0X91Ta081cYsq90OxYdcWwK/dwEoDa6dtXgj2HJfmzgq+QZTHdmQ==", + "dev": true, + "dependencies": { + "@types/chai": "*", + "@types/sinon": "*" + } + }, + "node_modules/@types/sinonjs__fake-timers": { + "version": "8.1.2", + "integrity": "sha512-9GcLXF0/v3t80caGs5p2rRfkB+a8VBGLJZVih6CNFkx8IZ994wiKKLSRs9nuFwk1HevWs/1mnUmkApGrSGsShA==", + "dev": true + }, + "node_modules/@types/stack-utils": { + "version": "2.0.1", + "integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==", + "dev": true + }, + "node_modules/@types/swagger-schema-official": { + "version": "2.0.22", + "integrity": "sha512-7yQiX6MWSFSvc/1wW5smJMZTZ4fHOd+hqLr3qr/HONDxHEa2bnYAsOcGBOEqFIjd4yetwMOdEDdeW+udRAQnHA==", + "dev": true + }, + "node_modules/@types/through": { + "version": "0.0.30", + "integrity": "sha512-FvnCJljyxhPM3gkRgWmxmDZyAQSiBQQWLI0A0VFL0K7W1oRUrPJSqNO0NvTnLkBcotdlp3lKvaT0JrnyRDkzOg==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/tv4": { + "version": "1.2.31", + "integrity": "sha512-P97XU07fcpauSw3/fE2Q7eF6bHl4oHhwkikjnM7zlQLENrdC2rZuHSdNlMBhnW82NyBEsVJHII1Jk3d/MtQsQQ==", + "dev": true + }, + "node_modules/@types/type-is": { + "version": "1.6.3", + "integrity": "sha512-PNs5wHaNcBgCQG5nAeeZ7OvosrEsI9O4W2jAOO9BCCg4ux9ZZvH2+0iSCOIDBiKuQsiNS8CBlmfX9f5YBQ22cA==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/uuid": { + "version": "8.3.4", + "integrity": "sha512-c/I8ZRb51j+pYGAu5CrFMRxqZ2ke4y2grEBO5AUjgSkSk+qT2Ea+OdWElz/OiMf5MNpn2b17kuVBwZLQJXzihw==", + "dev": true + }, + "node_modules/@types/vscode": { + "version": "1.74.0", + "integrity": "sha512-LyeCIU3jb9d38w0MXFwta9r0Jx23ugujkAxdwLTNCyspdZTKUc43t7ppPbCiPoQ/Ivd/pnDFZrb4hWd45wrsgA==", + "dev": true + }, + "node_modules/@types/yargs": { + "version": "17.0.20", + "integrity": "sha512-eknWrTHofQuPk2iuqDm1waA7V6xPlbgBoaaXEgYkClhLOnB0TtbW+srJaOToAgawPxPlHQzwypFA2bhZaUGP5A==", + "dev": true, + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/@types/yargs-parser": { + "version": "21.0.0", + "integrity": "sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==", + "dev": true + }, + "node_modules/@ungap/promise-all-settled": { + "version": "1.1.2", + "integrity": "sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q==", + "dev": true + }, + "node_modules/@vscode/test-electron": { + "version": "1.6.2", + "integrity": "sha512-W01ajJEMx6223Y7J5yaajGjVs1QfW3YGkkOJHVKfAMEqNB1ZHN9wCcViehv5ZwVSSJnjhu6lYEYgwBdHtCxqhQ==", + "dev": true, + "dependencies": { + "http-proxy-agent": "^4.0.1", + "https-proxy-agent": "^5.0.0", + "rimraf": "^3.0.2", + "unzipper": "^0.10.11" + }, + "engines": { + "node": ">=8.9.3" + } + }, + "node_modules/@vscode/test-electron/node_modules/@tootallnate/once": { + "version": "1.1.2", + "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/@vscode/test-electron/node_modules/http-proxy-agent": { + "version": "4.0.1", + "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", + "dev": true, + "dependencies": { + "@tootallnate/once": "1", + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/abbrev": { + "version": "1.1.1", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" + }, + "node_modules/abort-controller": { + "version": "3.0.0", + "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", + "dev": true, + "dependencies": { + "event-target-shim": "^5.0.0" + }, + "engines": { + "node": ">=6.5" + } + }, + "node_modules/abstract-logging": { + "version": "2.0.1", + "integrity": "sha512-2BjRTZxTPvheOvGbBslFSYOUkr+SjPtOnrLP33f+VIWLzezQpZcqVg7ja3L4dBXmzzgwT+a029jRx5PCi3JuiA==", + "dev": true + }, + "node_modules/accepts": { + "version": "1.3.8", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "dev": true, + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/acorn": { + "version": "8.8.2", + "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-walk": { + "version": "8.2.0", + "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/add-stream": { + "version": "1.0.0", + "integrity": "sha512-qQLMr+8o0WC4FZGQTcJiKBVC59JylcPSrTtk6usvmIDFUOCKegapy1VHQwRbFMOFyb/inzUVqHs+eMYKDM1YeQ==", + "dev": true + }, + "node_modules/adm-zip": { + "version": "0.5.10", + "integrity": "sha512-x0HvcHqVJNTPk/Bw8JbLWlWoo6Wwnsug0fnYYro1HBrjxZ3G7/AZk7Ahv8JwDe1uIcz8eBqvu86FuF1POiG7vQ==", + "engines": { + "node": ">=6.0" + } + }, + "node_modules/agent-base": { + "version": "6.0.2", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dev": true, + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/agentkeepalive": { + "version": "4.2.1", + "integrity": "sha512-Zn4cw2NEqd+9fiSVWMscnjyQ1a8Yfoc5oBajLeo5w+YBHgDUcEBY2hS4YpTz6iN5f/2zQiktcuM6tS8x1p9dpA==", + "dev": true, + "dependencies": { + "debug": "^4.1.0", + "depd": "^1.1.2", + "humanize-ms": "^1.2.1" + }, + "engines": { + "node": ">= 8.0.0" + } + }, + "node_modules/aggregate-error": { + "version": "3.1.0", + "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", + "dependencies": { + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/aggregate-error/node_modules/indent-string": { + "version": "4.0.0", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "engines": { + "node": ">=8" + } + }, + "node_modules/ajv": { + "version": "8.12.0", + "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ajv-formats": { + "version": "2.1.1", + "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", + "dependencies": { + "ajv": "^8.0.0" + }, + "peerDependencies": { + "ajv": "^8.0.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + } + } + }, + "node_modules/ansi-align": { + "version": "3.0.1", + "integrity": "sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==", + "dev": true, + "dependencies": { + "string-width": "^4.1.0" + } + }, + "node_modules/ansi-colors": { + "version": "4.1.1", + "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/ansi-escapes": { + "version": "4.3.2", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "dependencies": { + "type-fest": "^0.21.3" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/antlr4ts": { + "version": "0.5.0-alpha.4", + "integrity": "sha512-WPQDt1B74OfPv/IMS2ekXAKkTZIHl88uMetg6q3OTqgFxZ/dxDXI0EWLyZid/1Pe6hTftyg5N7gel5wNAGxXyQ==" + }, + "node_modules/any-observable": { + "version": "0.3.0", + "integrity": "sha512-/FQM1EDkTsf63Ub2C6O7GuYFDsSXUwsaZDurV0np41ocwq0jthUAYCmhBX9f+KwlaCgIuWyr/4WlUQUBfKfZog==", + "engines": { + "node": ">=6" + } + }, + "node_modules/anymatch": { + "version": "3.1.3", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/append-transform": { + "version": "2.0.0", + "integrity": "sha512-7yeyCEurROLQJFv5Xj4lEGTy0borxepjFv1g22oAdqFu//SrAlDl1O1Nxx15SH1RoliUml6p8dwJW9jvZughhg==", + "dev": true, + "dependencies": { + "default-require-extensions": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/aproba": { + "version": "2.0.0", + "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==", + "dev": true + }, + "node_modules/archiver": { + "version": "5.3.1", + "integrity": "sha512-8KyabkmbYrH+9ibcTScQ1xCJC/CGcugdVIwB+53f5sZziXgwUh3iXlAlANMxcZyDEfTHMe6+Z5FofV8nopXP7w==", + "dependencies": { + "archiver-utils": "^2.1.0", + "async": "^3.2.3", + "buffer-crc32": "^0.2.1", + "readable-stream": "^3.6.0", + "readdir-glob": "^1.0.0", + "tar-stream": "^2.2.0", + "zip-stream": "^4.1.0" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/archiver-utils": { + "version": "2.1.0", + "integrity": "sha512-bEL/yUb/fNNiNTuUz979Z0Yg5L+LzLxGJz8x79lYmR54fmTIb6ob/hNQgkQnIUDWIFjZVQwl9Xs356I6BAMHfw==", + "dependencies": { + "glob": "^7.1.4", + "graceful-fs": "^4.2.0", + "lazystream": "^1.0.0", + "lodash.defaults": "^4.2.0", + "lodash.difference": "^4.5.0", + "lodash.flatten": "^4.4.0", + "lodash.isplainobject": "^4.0.6", + "lodash.union": "^4.6.0", + "normalize-path": "^3.0.0", + "readable-stream": "^2.0.0" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/archiver-utils/node_modules/readable-stream": { + "version": "2.3.7", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/archiver-utils/node_modules/safe-buffer": { + "version": "5.1.2", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/archiver-utils/node_modules/string_decoder": { + "version": "1.1.1", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/archiver/node_modules/async": { + "version": "3.2.4", + "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==" + }, + "node_modules/archy": { + "version": "1.0.0", + "integrity": "sha512-Xg+9RwCg/0p32teKdGMPTPnVXKD0w3DfHnFTficozsAgsvq2XenPJq/MYpzzQ/v8zrOyJn6Ds39VA4JIDwFfqw==", + "dev": true + }, + "node_modules/are-we-there-yet": { + "version": "3.0.1", + "integrity": "sha512-QZW4EDmGwlYur0Yyf/b2uGucHQMa8aFUP7eu9ddR73vvhFyt4V0Vl3QHPcTNJ8l6qYOBdxgXdnBXQrHilfRQBg==", + "dev": true, + "dependencies": { + "delegates": "^1.0.0", + "readable-stream": "^3.6.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/arg": { + "version": "4.1.3", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", + "dev": true + }, + "node_modules/argparse": { + "version": "2.0.1", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" + }, + "node_modules/array-ify": { + "version": "1.0.0", + "integrity": "sha512-c5AMf34bKdvPhQ7tBGhqkgKNUzMr4WUs+WDtC2ZUGOUncbxKMTvqxYctiseW3+L4bA8ec+GcZ6/A/FW4m8ukng==", + "dev": true + }, + "node_modules/array-union": { + "version": "2.1.0", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/arrify": { + "version": "1.0.1", + "integrity": "sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ask-sdk-model-runtime": { + "version": "1.4.0", + "integrity": "sha512-JSu9zGklm8jtaQMk344BTJqVSX/tenFNB7b+jgnoHDp4aRwmzCAlDnBiiNAVMXlbrBeIi+ms79yK1s2oq0PjFg==" + }, + "node_modules/ask-smapi-model": { + "version": "1.19.12", + "integrity": "sha512-sQaf624rnP/avcIm2Rpt1FOI/ysJzeAHsWudu6JdJbVLl3jc8M8ItRIS9iICyfslkF7CspA+N+4HI8cNTfXcRg==", + "dependencies": { + "ask-sdk-model-runtime": "^1.1.0" + } + }, + "node_modules/ask-smapi-sdk": { + "version": "1.3.0", + "integrity": "sha512-1mTYkHp9ZzB3l4C9ZVFMKmEw+Ynm0vgQcLunCl6yOc3cxWmiI8QkbjJAs93F28Bg6EPBOTo8UOUtyjFz9vu9LA==", + "dependencies": { + "ask-smapi-model": "^1.4.0" + } + }, + "node_modules/asn1": { + "version": "0.2.6", + "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==", + "dependencies": { + "safer-buffer": "~2.1.0" + } + }, + "node_modules/assert-plus": { + "version": "1.0.0", + "integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==", + "engines": { + "node": ">=0.8" + } + }, + "node_modules/assertion-error": { + "version": "1.1.0", + "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/astral-regex": { + "version": "2.0.0", + "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/async": { + "version": "2.6.4", + "integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==", + "dependencies": { + "lodash": "^4.17.14" + } + }, + "node_modules/asynckit": { + "version": "0.4.0", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" + }, + "node_modules/atomic-sleep": { + "version": "1.0.0", + "integrity": "sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==", + "dev": true, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/available-typed-arrays": { + "version": "1.0.5", + "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/aws-profile-handler": { + "version": "2.0.3", + "integrity": "sha512-CDArk54zuHtbB13OKXgiwaCGyyH8TJlh+24lI3vw8dD3DpRQtg7uJDjIDZplqIOQqQ6/qdynHf0EjkXdrV1GuA==" + }, + "node_modules/aws-sdk": { + "version": "2.1303.0", + "integrity": "sha512-KTzMliy60ParQgmnHB3jcAZVQmyLV1ZlNK4jUDP6Hzb0SPZFkGHzzjfSb224o8pB/HfR5n4fT3hOUVWMjISwdA==", + "dependencies": { + "buffer": "4.9.2", + "events": "1.1.1", + "ieee754": "1.1.13", + "jmespath": "0.16.0", + "querystring": "0.2.0", + "sax": "1.2.1", + "url": "0.10.3", + "util": "^0.12.4", + "uuid": "8.0.0", + "xml2js": "0.4.19" + }, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/aws-sdk/node_modules/uuid": { + "version": "8.0.0", + "integrity": "sha512-jOXGuXZAWdsTH7eZLtyXMqUb9EcWMGZNbL9YcGBJl4MH4nrxHmZJhEHvyLFrkxo+28uLb/NYRcStH48fnD0Vzw==", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/aws-sign2": { + "version": "0.7.0", + "integrity": "sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA==", + "engines": { + "node": "*" + } + }, + "node_modules/aws4": { + "version": "1.12.0", + "integrity": "sha512-NmWvPnx0F1SfrQbYwOi7OeaNGokp9XhzNioJ/CSBs8Qa4vxug81mhJEAVZwxXuBmYB5KDRfMq/F3RR0BIU7sWg==" + }, + "node_modules/axios": { + "version": "0.26.1", + "integrity": "sha512-fPwcX4EvnSHuInCMItEhAGnaSEXRBjtzh9fOtsE6E1G6p7vl7edEeZe11QHf18+6+9gR5PbKV/sGKNaD8YaMeA==", + "dependencies": { + "follow-redirects": "^1.14.8" + } + }, + "node_modules/babel-plugin-istanbul": { + "version": "6.1.1", + "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0", + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-instrument": "^5.0.4", + "test-exclude": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/babel-preset-current-node-syntax": { + "version": "1.0.1", + "integrity": "sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ==", + "dev": true, + "dependencies": { + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/plugin-syntax-bigint": "^7.8.3", + "@babel/plugin-syntax-class-properties": "^7.8.3", + "@babel/plugin-syntax-import-meta": "^7.8.3", + "@babel/plugin-syntax-json-strings": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.8.3", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.8.3", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-syntax-top-level-await": "^7.8.3" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "node_modules/base64-js": { + "version": "1.5.1", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/bcrypt-pbkdf": { + "version": "1.0.2", + "integrity": "sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==", + "dependencies": { + "tweetnacl": "^0.14.3" + } + }, + "node_modules/big-integer": { + "version": "1.6.51", + "integrity": "sha512-GPEid2Y9QU1Exl1rpO9B2IPJGHPSupF5GnVIP0blYvNOMer2bTvSWs1jGOUg04hTmu67nmLsQ9TBo1puaotBHg==", + "dev": true, + "engines": { + "node": ">=0.6" + } + }, + "node_modules/binary": { + "version": "0.3.0", + "integrity": "sha512-D4H1y5KYwpJgK8wk1Cue5LLPgmwHKYSChkbspQg5JtVuR5ulGckxfR62H3AE9UDkdMC8yyXlqYihuz3Aqg2XZg==", + "dev": true, + "dependencies": { + "buffers": "~0.1.1", + "chainsaw": "~0.1.0" + }, + "engines": { + "node": "*" + } + }, + "node_modules/binary-extensions": { + "version": "2.2.0", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "engines": { + "node": ">=8" + } + }, + "node_modules/bl": { + "version": "4.1.0", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "node_modules/bl/node_modules/buffer": { + "version": "5.7.1", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "node_modules/bluebird": { + "version": "3.7.2", + "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", + "dev": true + }, + "node_modules/boxen": { + "version": "5.1.2", + "integrity": "sha512-9gYgQKXx+1nP8mP7CzFyaUARhg7D3n1dF/FnErWmu9l6JvGpNUN278h0aSb+QjoiKSWG+iZ3uHrcqk0qrY9RQQ==", + "dev": true, + "dependencies": { + "ansi-align": "^3.0.0", + "camelcase": "^6.2.0", + "chalk": "^4.1.0", + "cli-boxes": "^2.2.1", + "string-width": "^4.2.2", + "type-fest": "^0.20.2", + "widest-line": "^3.1.0", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/boxen/node_modules/camelcase": { + "version": "6.3.0", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/boxen/node_modules/chalk": { + "version": "4.1.2", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/boxen/node_modules/type-fest": { + "version": "0.20.2", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.2", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dependencies": { + "fill-range": "^7.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browser-stdout": { + "version": "1.3.1", + "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", + "dev": true + }, + "node_modules/browserslist": { + "version": "4.21.4", + "integrity": "sha512-CBHJJdDmgjl3daYjN5Cp5kbTf1mUhZoS+beLklHIvkOWscs83YAhLlF3Wsh/lciQYAcbBJgTOD44VtG31ZM4Hw==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + } + ], + "dependencies": { + "caniuse-lite": "^1.0.30001400", + "electron-to-chromium": "^1.4.251", + "node-releases": "^2.0.6", + "update-browserslist-db": "^1.0.9" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/bser": { + "version": "2.1.1", + "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", + "dev": true, + "dependencies": { + "node-int64": "^0.4.0" + } + }, + "node_modules/buffer": { + "version": "4.9.2", + "integrity": "sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg==", + "dependencies": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4", + "isarray": "^1.0.0" + } + }, + "node_modules/buffer-crc32": { + "version": "0.2.13", + "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", + "engines": { + "node": "*" + } + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" + }, + "node_modules/buffer-indexof-polyfill": { + "version": "1.0.2", + "integrity": "sha512-I7wzHwA3t1/lwXQh+A5PbNvJxgfo5r3xulgpYDB5zckTu/Z9oUK9biouBKQUjEqzaz3HnAT6TYoovmE+GqSf7A==", + "dev": true, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/buffers": { + "version": "0.1.1", + "integrity": "sha512-9q/rDEGSb/Qsvv2qvzIzdluL5k7AaJOTrw23z9reQthrbF7is4CtlT0DXyO1oei2DCp4uojjzQ7igaSHp1kAEQ==", + "dev": true, + "engines": { + "node": ">=0.2.0" + } + }, + "node_modules/builtins": { + "version": "5.0.1", + "integrity": "sha512-qwVpFEHNfhYJIzNRBvd2C1kyo6jz3ZSMPyyuR47OPdiKWlbYnZNyDWuyR175qDnAJLiCo5fBBqPb3RiXgWlkOQ==", + "dev": true, + "dependencies": { + "semver": "^7.0.0" + } + }, + "node_modules/bunyan": { + "version": "1.8.15", + "integrity": "sha512-0tECWShh6wUysgucJcBAoYegf3JJoZWibxdqhTm7OHPeT42qdjkZ29QCMcKwbgU1kiH+auSIasNRXMLWXafXig==", + "engines": [ + "node >=0.10.0" + ], + "bin": { + "bunyan": "bin/bunyan" + }, + "optionalDependencies": { + "dtrace-provider": "~0.8", + "moment": "^2.19.3", + "mv": "~2", + "safe-json-stringify": "~1" + } + }, + "node_modules/cacache": { + "version": "16.1.3", + "integrity": "sha512-/+Emcj9DAXxX4cwlLmRI9c166RuL3w30zp4R7Joiv2cQTtTtA+jeuCAjH3ZlGnYS3tKENSrKhAzVVP9GVyzeYQ==", + "dev": true, + "dependencies": { + "@npmcli/fs": "^2.1.0", + "@npmcli/move-file": "^2.0.0", + "chownr": "^2.0.0", + "fs-minipass": "^2.1.0", + "glob": "^8.0.1", + "infer-owner": "^1.0.4", + "lru-cache": "^7.7.1", + "minipass": "^3.1.6", + "minipass-collect": "^1.0.2", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "mkdirp": "^1.0.4", + "p-map": "^4.0.0", + "promise-inflight": "^1.0.1", + "rimraf": "^3.0.2", + "ssri": "^9.0.0", + "tar": "^6.1.11", + "unique-filename": "^2.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/cacache/node_modules/brace-expansion": { + "version": "2.0.1", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/cacache/node_modules/glob": { + "version": "8.1.0", + "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^5.0.1", + "once": "^1.3.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/cacache/node_modules/lru-cache": { + "version": "7.14.1", + "integrity": "sha512-ysxwsnTKdAx96aTRdhDOCQfDgbHnt8SK0KY8SEjO0wHinhWOFTESbjVCMPbU1uGXg/ch4lifqx0wfjOawU2+WA==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/cacache/node_modules/minimatch": { + "version": "5.1.6", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/cacache/node_modules/mkdirp": { + "version": "1.0.4", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true, + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/cacache/node_modules/p-map": { + "version": "4.0.0", + "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", + "dev": true, + "dependencies": { + "aggregate-error": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cacheable-request": { + "version": "6.1.0", + "integrity": "sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg==", + "dev": true, + "dependencies": { + "clone-response": "^1.0.2", + "get-stream": "^5.1.0", + "http-cache-semantics": "^4.0.0", + "keyv": "^3.0.0", + "lowercase-keys": "^2.0.0", + "normalize-url": "^4.1.0", + "responselike": "^1.0.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cacheable-request/node_modules/get-stream": { + "version": "5.2.0", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "dev": true, + "dependencies": { + "pump": "^3.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cacheable-request/node_modules/lowercase-keys": { + "version": "2.0.0", + "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/caching-transform": { + "version": "4.0.0", + "integrity": "sha512-kpqOvwXnjjN44D89K5ccQC+RUrsy7jB/XLlRrx0D7/2HNcTPqzsb6XgYoErwko6QsV184CA2YgS1fxDiiDZMWA==", + "dev": true, + "dependencies": { + "hasha": "^5.0.0", + "make-dir": "^3.0.0", + "package-hash": "^4.0.0", + "write-file-atomic": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/caching-transform/node_modules/write-file-atomic": { + "version": "3.0.3", + "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", + "dev": true, + "dependencies": { + "imurmurhash": "^0.1.4", + "is-typedarray": "^1.0.0", + "signal-exit": "^3.0.2", + "typedarray-to-buffer": "^3.1.5" + } + }, + "node_modules/call-bind": { + "version": "1.0.2", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "dependencies": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/call-me-maybe": { + "version": "1.0.2", + "integrity": "sha512-HpX65o1Hnr9HH25ojC1YGs7HCQLq0GCOibSaWER0eNpgJ/Z1MZv2mTc7+xh6WOPxbRVcmgbv4hGU+uSQ/2xFZQ==", + "dev": true + }, + "node_modules/callsites": { + "version": "3.1.0", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/camelcase": { + "version": "5.3.1", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/camelcase-keys": { + "version": "6.2.2", + "integrity": "sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg==", + "dev": true, + "dependencies": { + "camelcase": "^5.3.1", + "map-obj": "^4.0.0", + "quick-lru": "^4.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001448", + "integrity": "sha512-tq2YI+MJnooG96XpbTRYkBxLxklZPOdLmNIOdIhvf7SNJan6u5vCKum8iT7ZfCt70m1GPkuC7P3TtX6UuhupuA==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + } + ] + }, + "node_modules/caseless": { + "version": "0.12.0", + "integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==" + }, + "node_modules/chai": { + "version": "4.3.7", + "integrity": "sha512-HLnAzZ2iupm25PlN0xFreAlBA5zaBSv3og0DdeGA4Ar6h6rJ3A0rolRUKJhSF2V10GZKDgWF/VmAEsNWjCRB+A==", + "dev": true, + "dependencies": { + "assertion-error": "^1.1.0", + "check-error": "^1.0.2", + "deep-eql": "^4.1.2", + "get-func-name": "^2.0.0", + "loupe": "^2.3.1", + "pathval": "^1.1.1", + "type-detect": "^4.0.5" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/chai-as-promised": { + "version": "7.1.1", + "integrity": "sha512-azL6xMoi+uxu6z4rhWQ1jbdUhOMhis2PvscD/xjLqNMkv3BPPp2JyyuTHOrf9BOosGpNQ11v6BKv/g57RXbiaA==", + "dev": true, + "dependencies": { + "check-error": "^1.0.2" + }, + "peerDependencies": { + "chai": ">= 2.1.2 < 5" + } + }, + "node_modules/chai-json-schema": { + "version": "1.5.1", + "integrity": "sha512-TR/xPDxRhqwFFCWg1HgL8nNWbpNfUwaib6pBN++QKpnd0t+o3+MBvAn5CM1mpdUMaM76oJAtUjGKdjGad01lIA==", + "dev": true, + "dependencies": { + "jsonpointer.js": "0.4.0", + "tv4": "^1.3.0" + }, + "engines": { + "node": ">= 6" + }, + "peerDependencies": { + "chai": ">= 1.6.1 < 5" + } + }, + "node_modules/chai-uuid": { + "version": "1.0.6", + "integrity": "sha512-CG0kRk6TqI16ifkoNGLvyb6/Dz8ChE7nsrKCEUXa98ES3nnF3lYDCqXystFXTkH+2233favzkqmCbQT5uW+8iQ==", + "dev": true + }, + "node_modules/chainsaw": { + "version": "0.1.0", + "integrity": "sha512-75kWfWt6MEKNC8xYXIdRpDehRYY/tNSgwKaJq+dbbDcxORuVrrQ+SEHoWsniVn9XPYfP4gmdWIeDk/4YNp1rNQ==", + "dev": true, + "dependencies": { + "traverse": ">=0.3.0 <0.4" + }, + "engines": { + "node": "*" + } + }, + "node_modules/chalk": { + "version": "4.0.0", + "integrity": "sha512-N9oWFcegS0sFr9oh1oz2d7Npos6vNoWW9HvtCg5N1KRFpUhaAhvTv5Y58g880fZaEYSNm3qDz8SU1UrGvp+n7A==", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/chardet": { + "version": "0.7.0", + "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==" + }, + "node_modules/charset": { + "version": "1.0.1", + "integrity": "sha512-6dVyOOYjpfFcL1Y4qChrAoQLRHvj2ziyhcm0QJlhOcAhykL/k1kTUPbeo+87MNRTRdk2OIIsIXbuF3x2wi5EXg==", + "dev": true, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/check-error": { + "version": "1.0.2", + "integrity": "sha512-BrgHpW9NURQgzoNyjfq0Wu6VFO6D7IZEmJNdtgNqpzGG8RuNFHt2jQxWlAs4HMe119chBnv+34syEZtc6IhLtA==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/chokidar": { + "version": "3.5.3", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/chownr": { + "version": "2.0.0", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/ci-info": { + "version": "3.7.1", + "integrity": "sha512-4jYS4MOAaCIStSRwiuxc4B8MYhIe676yO1sYGzARnjXkWpmzZMMYxY6zu8WYWDhSuth5zhrQ1rhNSibyyvv4/w==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "engines": { + "node": ">=8" + } + }, + "node_modules/cint": { + "version": "8.2.1", + "integrity": "sha512-gyWqJHXgDFPNx7PEyFJotutav+al92TTC3dWlMFyTETlOyKBQMZb7Cetqmj3GlrnSILHwSJRwf4mIGzc7C5lXw==", + "dev": true + }, + "node_modules/clean-stack": { + "version": "2.2.0", + "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", + "engines": { + "node": ">=6" + } + }, + "node_modules/cli-boxes": { + "version": "2.2.1", + "integrity": "sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw==", + "dev": true, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-cursor": { + "version": "3.1.0", + "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", + "dependencies": { + "restore-cursor": "^3.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cli-spinners": { + "version": "2.7.0", + "integrity": "sha512-qu3pN8Y3qHNgE2AFweciB1IfMnmZ/fsNTEE+NOFjmGB2F/7rLhnhzppvpCnN4FovtP26k8lHyy9ptEbNwWFLzw==", + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-table": { + "version": "0.3.11", + "integrity": "sha512-IqLQi4lO0nIB4tcdTpN4LCB9FI3uqrJZK7RC515EnhZ6qBaglkIgICb1wjeAqpdoOabm1+SuQtkXIPdYC93jhQ==", + "dev": true, + "dependencies": { + "colors": "1.0.3" + }, + "engines": { + "node": ">= 0.2.0" + } + }, + "node_modules/cli-truncate": { + "version": "3.1.0", + "integrity": "sha512-wfOBkjXteqSnI59oPcJkcPl/ZmwvMMOj340qUIY1SKZCv0B9Cf4D4fAucRkIKQmsIuYK3x1rrgU7MeGRruiuiA==", + "dependencies": { + "slice-ansi": "^5.0.0", + "string-width": "^5.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-truncate/node_modules/ansi-regex": { + "version": "6.0.1", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/cli-truncate/node_modules/emoji-regex": { + "version": "9.2.2", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==" + }, + "node_modules/cli-truncate/node_modules/string-width": { + "version": "5.1.2", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-truncate/node_modules/strip-ansi": { + "version": "7.0.1", + "integrity": "sha512-cXNxvT8dFNRVfhVME3JAe98mkXDYN2O1l7jmcwMnOslDeESg1rF/OZMtK0nRAhiari1unG5cD4jG3rapUAkLbw==", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/cli-width": { + "version": "3.0.0", + "integrity": "sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==", + "engines": { + "node": ">= 10" + } + }, + "node_modules/cliui": { + "version": "8.0.1", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/clone": { + "version": "1.0.4", + "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==", + "engines": { + "node": ">=0.8" + } + }, + "node_modules/clone-response": { + "version": "1.0.3", + "integrity": "sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA==", + "dev": true, + "dependencies": { + "mimic-response": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/code-point-at": { + "version": "1.1.0", + "integrity": "sha512-RpAVKQA5T63xEj6/giIbUEtZwJ4UFIc3ZtvEkiaUERylqe8xb5IvqcgOurZLahv93CLKfxcw5YI+DZcUBRyLXA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/collect-v8-coverage": { + "version": "1.0.1", + "integrity": "sha512-iBPtljfCNcTKNAto0KEtDfZ3qzjJvqE3aTGZsbhjSBlorqpXJlaWWtPO35D+ZImoC3KWejX64o+yPGxhWSTzfg==", + "dev": true + }, + "node_modules/color-convert": { + "version": "2.0.1", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/color-support": { + "version": "1.1.3", + "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", + "dev": true, + "bin": { + "color-support": "bin.js" + } + }, + "node_modules/colorette": { + "version": "2.0.19", + "integrity": "sha512-3tlv/dIP7FWvj3BsbHrGLJ6l/oKh1O3TcgBqMn+yyCagOxc23fyzDS6HypQbgxWbkpDnf52p1LuR4eWDQ/K9WQ==" + }, + "node_modules/colors": { + "version": "1.0.3", + "integrity": "sha512-pFGrxThWcWQ2MsAz6RtgeWe4NK2kUE1WfsrvvlctdII745EW9I0yflqhe7++M5LEc7bV2c/9/5zc8sFcpL0Drw==", + "dev": true, + "engines": { + "node": ">=0.1.90" + } + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/commander": { + "version": "4.1.1", + "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", + "engines": { + "node": ">= 6" + } + }, + "node_modules/commondir": { + "version": "1.0.1", + "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==", + "dev": true + }, + "node_modules/compare-func": { + "version": "2.0.0", + "integrity": "sha512-zHig5N+tPWARooBnb0Zx1MFcdfpyJrfTJ3Y5L+IFvUm8rM74hHz66z0gw0x4tijh5CorKkKUCnW82R2vmpeCRA==", + "dev": true, + "dependencies": { + "array-ify": "^1.0.0", + "dot-prop": "^5.1.0" + } + }, + "node_modules/compress-commons": { + "version": "4.1.1", + "integrity": "sha512-QLdDLCKNV2dtoTorqgxngQCMA+gWXkM/Nwu7FpeBhk/RdkzimqC3jueb/FDmaZeXh+uby1jkBqE3xArsLBE5wQ==", + "dependencies": { + "buffer-crc32": "^0.2.13", + "crc32-stream": "^4.0.2", + "normalize-path": "^3.0.0", + "readable-stream": "^3.6.0" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/compute-gcd": { + "version": "1.2.1", + "integrity": "sha512-TwMbxBNz0l71+8Sc4czv13h4kEqnchV9igQZBi6QUaz09dnz13juGnnaWWJTRsP3brxOoxeB4SA2WELLw1hCtg==", + "dev": true, + "dependencies": { + "validate.io-array": "^1.0.3", + "validate.io-function": "^1.0.2", + "validate.io-integer-array": "^1.0.0" + } + }, + "node_modules/compute-lcm": { + "version": "1.1.2", + "integrity": "sha512-OFNPdQAXnQhDSKioX8/XYT6sdUlXwpeMjfd6ApxMJfyZ4GxmLR1xvMERctlYhlHwIiz6CSpBc2+qYKjHGZw4TQ==", + "dev": true, + "dependencies": { + "compute-gcd": "^1.2.1", + "validate.io-array": "^1.0.3", + "validate.io-function": "^1.0.2", + "validate.io-integer-array": "^1.0.0" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + }, + "node_modules/concat-stream": { + "version": "2.0.0", + "integrity": "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==", + "dev": true, + "engines": [ + "node >= 6.0" + ], + "dependencies": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.0.2", + "typedarray": "^0.0.6" + } + }, + "node_modules/configstore": { + "version": "5.0.1", + "integrity": "sha512-aMKprgk5YhBNyH25hj8wGt2+D52Sw1DRRIzqBwLp2Ya9mFmY8KPvvtvmna8SxVR9JMZ4kzMD68N22vlaRpkeFA==", + "dev": true, + "dependencies": { + "dot-prop": "^5.2.0", + "graceful-fs": "^4.1.2", + "make-dir": "^3.0.0", + "unique-string": "^2.0.0", + "write-file-atomic": "^3.0.0", + "xdg-basedir": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/configstore/node_modules/write-file-atomic": { + "version": "3.0.3", + "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", + "dev": true, + "dependencies": { + "imurmurhash": "^0.1.4", + "is-typedarray": "^1.0.0", + "signal-exit": "^3.0.2", + "typedarray-to-buffer": "^3.1.5" + } + }, + "node_modules/console-control-strings": { + "version": "1.1.0", + "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==", + "dev": true + }, + "node_modules/content-type": { + "version": "1.0.4", + "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/conventional-changelog": { + "version": "3.1.25", + "integrity": "sha512-ryhi3fd1mKf3fSjbLXOfK2D06YwKNic1nC9mWqybBHdObPd8KJ2vjaXZfYj1U23t+V8T8n0d7gwnc9XbIdFbyQ==", + "dev": true, + "dependencies": { + "conventional-changelog-angular": "^5.0.12", + "conventional-changelog-atom": "^2.0.8", + "conventional-changelog-codemirror": "^2.0.8", + "conventional-changelog-conventionalcommits": "^4.5.0", + "conventional-changelog-core": "^4.2.1", + "conventional-changelog-ember": "^2.0.9", + "conventional-changelog-eslint": "^3.0.9", + "conventional-changelog-express": "^2.0.6", + "conventional-changelog-jquery": "^3.0.11", + "conventional-changelog-jshint": "^2.0.9", + "conventional-changelog-preset-loader": "^2.3.4" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/conventional-changelog-angular": { + "version": "5.0.13", + "integrity": "sha512-i/gipMxs7s8L/QeuavPF2hLnJgH6pEZAttySB6aiQLWcX3puWDL3ACVmvBhJGxnAy52Qc15ua26BufY6KpmrVA==", + "dev": true, + "dependencies": { + "compare-func": "^2.0.0", + "q": "^1.5.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/conventional-changelog-atom": { + "version": "2.0.8", + "integrity": "sha512-xo6v46icsFTK3bb7dY/8m2qvc8sZemRgdqLb/bjpBsH2UyOS8rKNTgcb5025Hri6IpANPApbXMg15QLb1LJpBw==", + "dev": true, + "dependencies": { + "q": "^1.5.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/conventional-changelog-codemirror": { + "version": "2.0.8", + "integrity": "sha512-z5DAsn3uj1Vfp7po3gpt2Boc+Bdwmw2++ZHa5Ak9k0UKsYAO5mH1UBTN0qSCuJZREIhX6WU4E1p3IW2oRCNzQw==", + "dev": true, + "dependencies": { + "q": "^1.5.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/conventional-changelog-config-spec": { + "version": "2.1.0", + "integrity": "sha512-IpVePh16EbbB02V+UA+HQnnPIohgXvJRxHcS5+Uwk4AT5LjzCZJm5sp/yqs5C6KZJ1jMsV4paEV13BN1pvDuxQ==", + "dev": true + }, + "node_modules/conventional-changelog-conventionalcommits": { + "version": "4.6.3", + "integrity": "sha512-LTTQV4fwOM4oLPad317V/QNQ1FY4Hju5qeBIM1uTHbrnCE+Eg4CdRZ3gO2pUeR+tzWdp80M2j3qFFEDWVqOV4g==", + "dev": true, + "dependencies": { + "compare-func": "^2.0.0", + "lodash": "^4.17.15", + "q": "^1.5.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/conventional-changelog-core": { + "version": "4.2.4", + "integrity": "sha512-gDVS+zVJHE2v4SLc6B0sLsPiloR0ygU7HaDW14aNJE1v4SlqJPILPl/aJC7YdtRE4CybBf8gDwObBvKha8Xlyg==", + "dev": true, + "dependencies": { + "add-stream": "^1.0.0", + "conventional-changelog-writer": "^5.0.0", + "conventional-commits-parser": "^3.2.0", + "dateformat": "^3.0.0", + "get-pkg-repo": "^4.0.0", + "git-raw-commits": "^2.0.8", + "git-remote-origin-url": "^2.0.0", + "git-semver-tags": "^4.1.1", + "lodash": "^4.17.15", + "normalize-package-data": "^3.0.0", + "q": "^1.5.1", + "read-pkg": "^3.0.0", + "read-pkg-up": "^3.0.0", + "through2": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/conventional-changelog-core/node_modules/find-up": { + "version": "2.1.0", + "integrity": "sha512-NWzkk0jSJtTt08+FBFMvXoeZnOJD+jTtsRmBYbAIzJdX6l7dLgR7CTubCM5/eDdPUBvLCeVasP1brfVR/9/EZQ==", + "dev": true, + "dependencies": { + "locate-path": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/conventional-changelog-core/node_modules/hosted-git-info": { + "version": "2.8.9", + "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", + "dev": true + }, + "node_modules/conventional-changelog-core/node_modules/locate-path": { + "version": "2.0.0", + "integrity": "sha512-NCI2kiDkyR7VeEKm27Kda/iQHyKJe1Bu0FlTbYp3CqJu+9IFe9bLyAjMxf5ZDDbEg+iMPzB5zYyUTSm8wVTKmA==", + "dev": true, + "dependencies": { + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/conventional-changelog-core/node_modules/p-limit": { + "version": "1.3.0", + "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", + "dev": true, + "dependencies": { + "p-try": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/conventional-changelog-core/node_modules/p-locate": { + "version": "2.0.0", + "integrity": "sha512-nQja7m7gSKuewoVRen45CtVfODR3crN3goVQ0DDZ9N3yHxgpkuBhZqsaiotSQRrADUrne346peY7kT3TSACykg==", + "dev": true, + "dependencies": { + "p-limit": "^1.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/conventional-changelog-core/node_modules/p-try": { + "version": "1.0.0", + "integrity": "sha512-U1etNYuMJoIz3ZXSrrySFjsXQTWOx2/jdi86L+2pRvph/qMKL6sbcCYdH23fqsbm8TH2Gn0OybpT4eSFlCVHww==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/conventional-changelog-core/node_modules/path-exists": { + "version": "3.0.0", + "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/conventional-changelog-core/node_modules/path-type": { + "version": "3.0.0", + "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", + "dev": true, + "dependencies": { + "pify": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/conventional-changelog-core/node_modules/read-pkg": { + "version": "3.0.0", + "integrity": "sha512-BLq/cCO9two+lBgiTYNqD6GdtK8s4NpaWrl6/rCO9w0TUS8oJl7cmToOZfRYllKTISY6nt1U7jQ53brmKqY6BA==", + "dev": true, + "dependencies": { + "load-json-file": "^4.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/conventional-changelog-core/node_modules/read-pkg-up": { + "version": "3.0.0", + "integrity": "sha512-YFzFrVvpC6frF1sz8psoHDBGF7fLPc+llq/8NB43oagqWkx8ar5zYtsTORtOjw9W2RHLpWP+zTWwBvf1bCmcSw==", + "dev": true, + "dependencies": { + "find-up": "^2.0.0", + "read-pkg": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/conventional-changelog-core/node_modules/read-pkg/node_modules/normalize-package-data": { + "version": "2.5.0", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "dev": true, + "dependencies": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "node_modules/conventional-changelog-core/node_modules/semver": { + "version": "5.7.1", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/conventional-changelog-ember": { + "version": "2.0.9", + "integrity": "sha512-ulzIReoZEvZCBDhcNYfDIsLTHzYHc7awh+eI44ZtV5cx6LVxLlVtEmcO+2/kGIHGtw+qVabJYjdI5cJOQgXh1A==", + "dev": true, + "dependencies": { + "q": "^1.5.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/conventional-changelog-eslint": { + "version": "3.0.9", + "integrity": "sha512-6NpUCMgU8qmWmyAMSZO5NrRd7rTgErjrm4VASam2u5jrZS0n38V7Y9CzTtLT2qwz5xEChDR4BduoWIr8TfwvXA==", + "dev": true, + "dependencies": { + "q": "^1.5.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/conventional-changelog-express": { + "version": "2.0.6", + "integrity": "sha512-SDez2f3iVJw6V563O3pRtNwXtQaSmEfTCaTBPCqn0oG0mfkq0rX4hHBq5P7De2MncoRixrALj3u3oQsNK+Q0pQ==", + "dev": true, + "dependencies": { + "q": "^1.5.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/conventional-changelog-jquery": { + "version": "3.0.11", + "integrity": "sha512-x8AWz5/Td55F7+o/9LQ6cQIPwrCjfJQ5Zmfqi8thwUEKHstEn4kTIofXub7plf1xvFA2TqhZlq7fy5OmV6BOMw==", + "dev": true, + "dependencies": { + "q": "^1.5.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/conventional-changelog-jshint": { + "version": "2.0.9", + "integrity": "sha512-wMLdaIzq6TNnMHMy31hql02OEQ8nCQfExw1SE0hYL5KvU+JCTuPaDO+7JiogGT2gJAxiUGATdtYYfh+nT+6riA==", + "dev": true, + "dependencies": { + "compare-func": "^2.0.0", + "q": "^1.5.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/conventional-changelog-preset-loader": { + "version": "2.3.4", + "integrity": "sha512-GEKRWkrSAZeTq5+YjUZOYxdHq+ci4dNwHvpaBC3+ENalzFWuCWa9EZXSuZBpkr72sMdKB+1fyDV4takK1Lf58g==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/conventional-changelog-writer": { + "version": "5.0.1", + "integrity": "sha512-5WsuKUfxW7suLblAbFnxAcrvf6r+0b7GvNaWUwUIk0bXMnENP/PEieGKVUQrjPqwPT4o3EPAASBXiY6iHooLOQ==", + "dev": true, + "dependencies": { + "conventional-commits-filter": "^2.0.7", + "dateformat": "^3.0.0", + "handlebars": "^4.7.7", + "json-stringify-safe": "^5.0.1", + "lodash": "^4.17.15", + "meow": "^8.0.0", + "semver": "^6.0.0", + "split": "^1.0.0", + "through2": "^4.0.0" + }, + "bin": { + "conventional-changelog-writer": "cli.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/conventional-changelog-writer/node_modules/semver": { + "version": "6.3.0", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/conventional-commits-filter": { + "version": "2.0.7", + "integrity": "sha512-ASS9SamOP4TbCClsRHxIHXRfcGCnIoQqkvAzCSbZzTFLfcTqJVugB0agRgsEELsqaeWgsXv513eS116wnlSSPA==", + "dev": true, + "dependencies": { + "lodash.ismatch": "^4.4.0", + "modify-values": "^1.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/conventional-commits-parser": { + "version": "3.2.4", + "integrity": "sha512-nK7sAtfi+QXbxHCYfhpZsfRtaitZLIA6889kFIouLvz6repszQDgxBu7wf2WbU+Dco7sAnNCJYERCwt54WPC2Q==", + "dev": true, + "dependencies": { + "is-text-path": "^1.0.1", + "JSONStream": "^1.0.4", + "lodash": "^4.17.15", + "meow": "^8.0.0", + "split2": "^3.0.0", + "through2": "^4.0.0" + }, + "bin": { + "conventional-commits-parser": "cli.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/conventional-recommended-bump": { + "version": "6.1.0", + "integrity": "sha512-uiApbSiNGM/kkdL9GTOLAqC4hbptObFo4wW2QRyHsKciGAfQuLU1ShZ1BIVI/+K2BE/W1AWYQMCXAsv4dyKPaw==", + "dev": true, + "dependencies": { + "concat-stream": "^2.0.0", + "conventional-changelog-preset-loader": "^2.3.4", + "conventional-commits-filter": "^2.0.7", + "conventional-commits-parser": "^3.2.0", + "git-raw-commits": "^2.0.8", + "git-semver-tags": "^4.1.1", + "meow": "^8.0.0", + "q": "^1.5.1" + }, + "bin": { + "conventional-recommended-bump": "cli.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/convert-source-map": { + "version": "1.9.0", + "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==", + "dev": true + }, + "node_modules/copyfiles": { + "version": "2.4.1", + "integrity": "sha512-fereAvAvxDrQDOXybk3Qu3dPbOoKoysFMWtkY3mv5BsL8//OSZVL5DCLYqgRfY5cWirgRzlC+WSrxp6Bo3eNZg==", + "dev": true, + "dependencies": { + "glob": "^7.0.5", + "minimatch": "^3.0.3", + "mkdirp": "^1.0.4", + "noms": "0.0.0", + "through2": "^2.0.1", + "untildify": "^4.0.0", + "yargs": "^16.1.0" + }, + "bin": { + "copyfiles": "copyfiles", + "copyup": "copyfiles" + } + }, + "node_modules/copyfiles/node_modules/cliui": { + "version": "7.0.4", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "dev": true, + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "node_modules/copyfiles/node_modules/mkdirp": { + "version": "1.0.4", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true, + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/copyfiles/node_modules/readable-stream": { + "version": "2.3.7", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/copyfiles/node_modules/safe-buffer": { + "version": "5.1.2", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/copyfiles/node_modules/string_decoder": { + "version": "1.1.1", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/copyfiles/node_modules/through2": { + "version": "2.0.5", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dev": true, + "dependencies": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + }, + "node_modules/copyfiles/node_modules/yargs": { + "version": "16.2.0", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "dev": true, + "dependencies": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/core-util-is": { + "version": "1.0.2", + "integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==" + }, + "node_modules/cosmiconfig": { + "version": "7.1.0", + "integrity": "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==", + "dev": true, + "dependencies": { + "@types/parse-json": "^4.0.0", + "import-fresh": "^3.2.1", + "parse-json": "^5.0.0", + "path-type": "^4.0.0", + "yaml": "^1.10.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/cosmiconfig-typescript-loader": { + "version": "2.0.2", + "integrity": "sha512-KmE+bMjWMXJbkWCeY4FJX/npHuZPNr9XF9q9CIQ/bpFwi1qHfCmSiKarrCcRa0LO4fWjk93pVoeRtJAkTGcYNw==", + "dev": true, + "dependencies": { + "cosmiconfig": "^7", + "ts-node": "^10.8.1" + }, + "engines": { + "node": ">=12", + "npm": ">=6" + }, + "peerDependencies": { + "@types/node": "*", + "cosmiconfig": ">=7", + "typescript": ">=3" + } + }, + "node_modules/crc-32": { + "version": "1.2.2", + "integrity": "sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==", + "bin": { + "crc32": "bin/crc32.njs" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/crc32-stream": { + "version": "4.0.2", + "integrity": "sha512-DxFZ/Hk473b/muq1VJ///PMNLj0ZMnzye9thBpmjpJKCc5eMgB95aK8zCGrGfQ90cWo561Te6HK9D+j4KPdM6w==", + "dependencies": { + "crc-32": "^1.2.0", + "readable-stream": "^3.4.0" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/create-require": { + "version": "1.1.1", + "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", + "dev": true + }, + "node_modules/cross-spawn": { + "version": "7.0.3", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/crypto-random-string": { + "version": "2.0.0", + "integrity": "sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/dargs": { + "version": "7.0.0", + "integrity": "sha512-2iy1EkLdlBzQGvbweYRFxmFath8+K7+AKB0TlhHWkNuH+TmovaMH/Wp7V7R4u7f4SnX3OgLsU9t1NI9ioDnUpg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/dashdash": { + "version": "1.14.1", + "integrity": "sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==", + "dependencies": { + "assert-plus": "^1.0.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/date-fns": { + "version": "2.29.3", + "integrity": "sha512-dDCnyH2WnnKusqvZZ6+jA1O51Ibt8ZMRNkDZdyAyK4YfbDwa/cEmuztzG5pk6hqlp9aSBPYcjOlktquahGwGeA==", + "engines": { + "node": ">=0.11" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/date-fns" + } + }, + "node_modules/dateformat": { + "version": "3.0.3", + "integrity": "sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/debug": { + "version": "4.3.4", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decamelize": { + "version": "1.2.0", + "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/decamelize-keys": { + "version": "1.1.1", + "integrity": "sha512-WiPxgEirIV0/eIOMcnFBA3/IJZAZqKnwAwWyvvdi4lsr1WCN22nhdf/3db3DoZcUjTV2SqfzIwNyp6y2xs3nmg==", + "dev": true, + "dependencies": { + "decamelize": "^1.1.0", + "map-obj": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/decamelize-keys/node_modules/map-obj": { + "version": "1.0.1", + "integrity": "sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/decompress-response": { + "version": "3.3.0", + "integrity": "sha512-BzRPQuY1ip+qDonAOz42gRm/pg9F768C+npV/4JOsxRC2sq+Rlk+Q4ZCAsOhnIaMrgarILY+RMUIvMmmX1qAEA==", + "dev": true, + "dependencies": { + "mimic-response": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/deep-eql": { + "version": "4.1.3", + "integrity": "sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw==", + "dev": true, + "dependencies": { + "type-detect": "^4.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/deep-extend": { + "version": "0.6.0", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "dev": true, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/default-require-extensions": { + "version": "3.0.1", + "integrity": "sha512-eXTJmRbm2TIt9MgWTsOH1wEuhew6XGZcMeGKCtLedIg/NCsg1iBePXkceTdK4Fii7pzmN9tGsZhKzZ4h7O/fxw==", + "dev": true, + "dependencies": { + "strip-bom": "^4.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/defaults": { + "version": "1.0.4", + "integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==", + "dependencies": { + "clone": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/defer-to-connect": { + "version": "1.1.3", + "integrity": "sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ==", + "dev": true + }, + "node_modules/define-lazy-prop": { + "version": "2.0.0", + "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==", + "engines": { + "node": ">=8" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/delegates": { + "version": "1.0.0", + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==", + "dev": true + }, + "node_modules/depd": { + "version": "1.1.2", + "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/detect-indent": { + "version": "6.1.0", + "integrity": "sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/detect-newline": { + "version": "3.1.0", + "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/diff": { + "version": "5.0.0", + "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", + "dev": true, + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/diff-sequences": { + "version": "28.1.1", + "integrity": "sha512-FU0iFaH/E23a+a718l8Qa/19bF9p06kgE0KipMOMadwa3SjnaElKzPaUC0vnibs6/B/9ni97s61mcejk8W1fQw==", + "dev": true, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/dir-glob": { + "version": "3.0.1", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "dependencies": { + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/dot-prop": { + "version": "5.3.0", + "integrity": "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==", + "dev": true, + "dependencies": { + "is-obj": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/dotgitignore": { + "version": "2.1.0", + "integrity": "sha512-sCm11ak2oY6DglEPpCB8TixLjWAxd3kJTs6UIcSasNYxXdFPV+YKlye92c8H4kKFqV5qYMIh7d+cYecEg0dIkA==", + "dev": true, + "dependencies": { + "find-up": "^3.0.0", + "minimatch": "^3.0.4" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/dotgitignore/node_modules/find-up": { + "version": "3.0.0", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "dependencies": { + "locate-path": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/dotgitignore/node_modules/locate-path": { + "version": "3.0.0", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "dependencies": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/dotgitignore/node_modules/p-limit": { + "version": "2.3.0", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/dotgitignore/node_modules/p-locate": { + "version": "3.0.0", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "dependencies": { + "p-limit": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/dotgitignore/node_modules/path-exists": { + "version": "3.0.0", + "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/dtrace-provider": { + "version": "0.8.8", + "integrity": "sha512-b7Z7cNtHPhH9EJhNNbbeqTcXB8LGFFZhq1PGgEvpeHlzd36bhbdTWoE/Ba/YguqpBSlAPKnARWhVlhunCMwfxg==", + "hasInstallScript": true, + "optional": true, + "dependencies": { + "nan": "^2.14.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/duplexer2": { + "version": "0.1.4", + "integrity": "sha512-asLFVfWWtJ90ZyOUHMqk7/S2w2guQKxUI2itj3d92ADHhxUSbCMGi1f1cBcJ7xM1To+pE/Khbwo1yuNbMEPKeA==", + "dev": true, + "dependencies": { + "readable-stream": "^2.0.2" + } + }, + "node_modules/duplexer2/node_modules/readable-stream": { + "version": "2.3.7", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/duplexer2/node_modules/safe-buffer": { + "version": "5.1.2", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/duplexer2/node_modules/string_decoder": { + "version": "1.1.1", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/duplexer3": { + "version": "0.1.5", + "integrity": "sha512-1A8za6ws41LQgv9HrE/66jyC5yuSjQ3L/KOpFtoBilsAK2iA2wuS5rTt1OCzIvtS2V7nVmedsUU+DGRcjBmOYA==", + "dev": true + }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==" + }, + "node_modules/ecc-jsbn": { + "version": "0.1.2", + "integrity": "sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==", + "dependencies": { + "jsbn": "~0.1.0", + "safer-buffer": "^2.1.0" + } + }, + "node_modules/electron-to-chromium": { + "version": "1.4.284", + "integrity": "sha512-M8WEXFuKXMYMVr45fo8mq0wUrrJHheiKZf6BArTKk9ZBYCKJEOU5H8cdWgDT+qCVZf7Na4lVUaZsA+h6uA9+PA==", + "dev": true + }, + "node_modules/elegant-spinner": { + "version": "1.0.1", + "integrity": "sha512-B+ZM+RXvRqQaAmkMlO/oSe5nMUOaUnyfGYCEHoR8wrXsZR2mA0XVibsxV1bvTwxdRWah1PkQqso2EzhILGHtEQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "node_modules/encoding": { + "version": "0.1.13", + "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", + "dev": true, + "optional": true, + "dependencies": { + "iconv-lite": "^0.6.2" + } + }, + "node_modules/encoding/node_modules/iconv-lite": { + "version": "0.6.3", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "dev": true, + "optional": true, + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/end-of-stream": { + "version": "1.4.4", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/env-paths": { + "version": "2.2.1", + "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/err-code": { + "version": "2.0.3", + "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==", + "dev": true + }, + "node_modules/error-ex": { + "version": "1.3.2", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/es6-error": { + "version": "4.1.1", + "integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==", + "dev": true + }, + "node_modules/escalade": { + "version": "3.1.1", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-goat": { + "version": "2.1.1", + "integrity": "sha512-8/uIhbG12Csjy2JEW7D9pHbreaVaS/OpN3ycnyvElTdwM5n6GY6W6e2IPemfvGZeUMqZ9A/3GqIZMgKnBhAw/Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/escape-string-regexp": { + "version": "1.0.5", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/esprima": { + "version": "4.0.1", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true, + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/event-target-shim": { + "version": "5.0.1", + "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/events": { + "version": "1.1.1", + "integrity": "sha512-kEcvvCBByWXGnZy6JUlgAp2gBIUjfCAV6P6TgT1/aaQKcmuAEC4OZTV1I4EWQLz2gxZw76atuVyvHhTxvi0Flw==", + "engines": { + "node": ">=0.4.x" + } + }, + "node_modules/execa": { + "version": "5.1.1", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/expect": { + "version": "28.1.3", + "integrity": "sha512-eEh0xn8HlsuOBxFgIss+2mX85VAS4Qy3OSkjV7rlBWljtA4oWH37glVGyOZSZvErDT/yBywZdPGwCXuTvSG85g==", + "dev": true, + "dependencies": { + "@jest/expect-utils": "^28.1.3", + "jest-get-type": "^28.0.2", + "jest-matcher-utils": "^28.1.3", + "jest-message-util": "^28.1.3", + "jest-util": "^28.1.3" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/extend": { + "version": "3.0.2", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" + }, + "node_modules/external-editor": { + "version": "3.1.0", + "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", + "dependencies": { + "chardet": "^0.7.0", + "iconv-lite": "^0.4.24", + "tmp": "^0.0.33" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/external-editor/node_modules/tmp": { + "version": "0.0.33", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "dependencies": { + "os-tmpdir": "~1.0.2" + }, + "engines": { + "node": ">=0.6.0" + } + }, + "node_modules/extsprintf": { + "version": "1.3.0", + "integrity": "sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==", + "engines": [ + "node >=0.6.0" + ] + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" + }, + "node_modules/fast-glob": { + "version": "3.2.12", + "integrity": "sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" + }, + "node_modules/fast-memoize": { + "version": "2.5.2", + "integrity": "sha512-Ue0LwpDYErFbmNnZSF0UH6eImUwDmogUO1jyE+JbN2gsQz/jICm1Ve7t9QT0rNSsfJt+Hs4/S3GnsDVjL4HVrw==", + "dev": true + }, + "node_modules/fast-redact": { + "version": "3.1.2", + "integrity": "sha512-+0em+Iya9fKGfEQGcd62Yv6onjBmmhV1uh86XVfOU8VwAe6kaFdQCWI9s0/Nnugx5Vd9tdbZ7e6gE2tR9dzXdw==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/fast-safe-stringify": { + "version": "2.1.1", + "integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==", + "dev": true + }, + "node_modules/fast-xml-parser": { + "version": "3.21.1", + "integrity": "sha512-FTFVjYoBOZTJekiUsawGsSYV9QL0A+zDYCRj7y34IO6Jg+2IMYEtQa+bbictpdpV8dHxXywqU7C0gRDEOFtBFg==", + "dev": true, + "dependencies": { + "strnum": "^1.0.4" + }, + "bin": { + "xml2js": "cli.js" + }, + "funding": { + "type": "paypal", + "url": "https://paypal.me/naturalintelligence" + } + }, + "node_modules/fastestsmallesttextencoderdecoder": { + "version": "1.0.22", + "integrity": "sha512-Pb8d48e+oIuY4MaM64Cd7OW1gt4nxCHs7/ddPPZ/Ic3sg8yVGM7O9wDvZ7us6ScaUupzM+pfBolwtYhN1IxBIw==", + "dev": true + }, + "node_modules/fastq": { + "version": "1.15.0", + "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==", + "dev": true, + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/fb-watchman": { + "version": "2.0.2", + "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==", + "dev": true, + "dependencies": { + "bser": "2.1.1" + } + }, + "node_modules/figgy-pudding": { + "version": "3.5.2", + "integrity": "sha512-0btnI/H8f2pavGMN8w40mlSKOfTK2SVJmBfBeVIj3kNw0swwgzyRq0d5TJVOwodFmtvpPeWPN/MCcfuWF0Ezbw==", + "dev": true + }, + "node_modules/figures": { + "version": "3.2.0", + "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", + "dependencies": { + "escape-string-regexp": "^1.0.5" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/file-type": { + "version": "3.9.0", + "integrity": "sha512-RLoqTXE8/vPmMuTI88DAzhMYC99I8BWv7zYP4A1puo5HIjEJ5EX48ighy4ZyKMG9EDXxBgW6e++cn7d1xuFghA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fill-keys": { + "version": "1.0.2", + "integrity": "sha512-tcgI872xXjwFF4xgQmLxi76GnwJG3g/3isB1l4/G5Z4zrbddGpBjqZCO9oEAcB5wX0Hj/5iQB3toxfO7in1hHA==", + "dev": true, + "dependencies": { + "is-object": "~1.0.1", + "merge-descriptors": "~1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fill-range": { + "version": "7.0.1", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-cache-dir": { + "version": "3.3.2", + "integrity": "sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==", + "dev": true, + "dependencies": { + "commondir": "^1.0.1", + "make-dir": "^3.0.2", + "pkg-dir": "^4.1.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/avajs/find-cache-dir?sponsor=1" + } + }, + "node_modules/find-package-json": { + "version": "1.2.0", + "integrity": "sha512-+SOGcLGYDJHtyqHd87ysBhmaeQ95oWspDKnMXBrnQ9Eq4OkLNqejgoaD8xVWu6GPa0B6roa6KinCMEMcVeqONw==", + "dev": true + }, + "node_modules/find-up": { + "version": "5.0.0", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat": { + "version": "5.0.2", + "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", + "dev": true, + "bin": { + "flat": "cli.js" + } + }, + "node_modules/flatstr": { + "version": "1.0.12", + "integrity": "sha512-4zPxDyhCyiN2wIAtSLI6gc82/EjqZc1onI4Mz/l0pWrAlsSfYH/2ZIcU+e3oA2wDwbzIWNKwa23F8rh6+DRWkw==", + "dev": true + }, + "node_modules/fnv-plus": { + "version": "1.3.1", + "integrity": "sha512-Gz1EvfOneuFfk4yG458dJ3TLJ7gV19q3OM/vVvvHf7eT02Hm1DleB4edsia6ahbKgAYxO9gvyQ1ioWZR+a00Yw==", + "dev": true + }, + "node_modules/folder-hash": { + "version": "4.0.4", + "integrity": "sha512-zEyYH+UsHEfJJcCRSf9ai5I4CTZwZ8ObONRuEI5hcEmJY5pS0FUWKruX9mMnYJrgC7MlPFDYnGsK1R+WFYjLlQ==", + "dependencies": { + "debug": "^4.3.3", + "minimatch": "~5.1.2" + }, + "bin": { + "folder-hash": "bin/folder-hash" + }, + "engines": { + "node": ">=10.10.0" + } + }, + "node_modules/folder-hash/node_modules/brace-expansion": { + "version": "2.0.1", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/folder-hash/node_modules/minimatch": { + "version": "5.1.6", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/follow-redirects": { + "version": "1.15.2", + "integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/for-each": { + "version": "0.3.3", + "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "dependencies": { + "is-callable": "^1.1.3" + } + }, + "node_modules/foreach": { + "version": "2.0.6", + "integrity": "sha512-k6GAGDyqLe9JaebCsFCoudPPWfihKu8pylYXRlqP1J7ms39iPoTtk2fviNglIeQEwdh0bQeKJ01ZPyuyQvKzwg==", + "dev": true + }, + "node_modules/foreground-child": { + "version": "2.0.0", + "integrity": "sha512-dCIq9FpEcyQyXKCkyzmlPTFNgrCzPudOe+mhvJU5zAtlBnGVy2yKxtfsxK2tQBThwq225jcvBjpw1Gr40uzZCA==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.0", + "signal-exit": "^3.0.2" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/forever-agent": { + "version": "0.6.1", + "integrity": "sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==", + "engines": { + "node": "*" + } + }, + "node_modules/form-data": { + "version": "2.3.3", + "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 0.12" + } + }, + "node_modules/format-util": { + "version": "1.0.5", + "integrity": "sha512-varLbTj0e0yVyRpqQhuWV+8hlePAgaoFRhNFj50BNjEIrw1/DphHSObtqwskVCPWNgzwPoQrZAbfa/SBiicNeg==", + "dev": true + }, + "node_modules/fp-and-or": { + "version": "0.1.3", + "integrity": "sha512-wJaE62fLaB3jCYvY2ZHjZvmKK2iiLiiehX38rz5QZxtdN8fVPJDeZUiVvJrHStdTc+23LHlyZuSEKgFc0pxi2g==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/fp-ts": { + "version": "2.13.1", + "integrity": "sha512-0eu5ULPS2c/jsa1lGFneEFFEdTbembJv8e4QKXeVJ3lm/5hyve06dlKZrpxmMwJt6rYen7sxmHHK2CLaXvWuWQ==", + "dev": true + }, + "node_modules/fromentries": { + "version": "1.3.2", + "integrity": "sha512-cHEpEQHUg0f8XdtZCc2ZAhrHzKzT0MrFUTcvx+hfxYu7rGMDc5SKoXFh+n4YigxsHXRzc6OrCshdR1bWH6HHyg==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/fs-constants": { + "version": "1.0.0", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" + }, + "node_modules/fs-extra": { + "version": "10.1.0", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/fs-minipass": { + "version": "2.1.0", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "dev": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" + }, + "node_modules/fsevents": { + "version": "2.3.2", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/fstream": { + "version": "1.0.12", + "integrity": "sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.2", + "inherits": "~2.0.0", + "mkdirp": ">=0.5 0", + "rimraf": "2" + }, + "engines": { + "node": ">=0.6" + } + }, + "node_modules/fstream/node_modules/rimraf": { + "version": "2.7.1", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + } + }, + "node_modules/function-bind": { + "version": "1.1.1", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + }, + "node_modules/gauge": { + "version": "4.0.4", + "integrity": "sha512-f9m+BEN5jkg6a0fZjleidjN51VE1X+mPFQ2DJ0uv1V39oCLCbsGe6yjbBnp7eK7z/+GAon99a3nHuqbuuthyPg==", + "dev": true, + "dependencies": { + "aproba": "^1.0.3 || ^2.0.0", + "color-support": "^1.1.3", + "console-control-strings": "^1.1.0", + "has-unicode": "^2.0.1", + "signal-exit": "^3.0.7", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "wide-align": "^1.1.5" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-func-name": { + "version": "2.0.0", + "integrity": "sha512-Hm0ixYtaSZ/V7C8FJrtZIuBBI+iSgL+1Aq82zSu8VQNB4S3Gk8e7Qs3VwBDJAhmRZcFqkl3tQu36g/Foh5I5ig==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/get-intrinsic": { + "version": "1.2.0", + "integrity": "sha512-L049y6nFOuom5wGyRc3/gdTLO94dySVKRACj1RmJZBQXlbTMhtNIgkWkUHq+jYmZvKf14EW1EoJnnjbmoHij0Q==", + "dependencies": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-package-type": { + "version": "0.1.0", + "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", + "dev": true, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/get-pkg-repo": { + "version": "4.2.1", + "integrity": "sha512-2+QbHjFRfGB74v/pYWjd5OhU3TDIC2Gv/YKUTk/tCvAz0pkn/Mz6P3uByuBimLOcPvN2jYdScl3xGFSrx0jEcA==", + "dev": true, + "dependencies": { + "@hutson/parse-repository-url": "^3.0.0", + "hosted-git-info": "^4.0.0", + "through2": "^2.0.0", + "yargs": "^16.2.0" + }, + "bin": { + "get-pkg-repo": "src/cli.js" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/get-pkg-repo/node_modules/cliui": { + "version": "7.0.4", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "dev": true, + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "node_modules/get-pkg-repo/node_modules/readable-stream": { + "version": "2.3.7", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/get-pkg-repo/node_modules/safe-buffer": { + "version": "5.1.2", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/get-pkg-repo/node_modules/string_decoder": { + "version": "1.1.1", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/get-pkg-repo/node_modules/through2": { + "version": "2.0.5", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dev": true, + "dependencies": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + }, + "node_modules/get-pkg-repo/node_modules/yargs": { + "version": "16.2.0", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "dev": true, + "dependencies": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/get-stdin": { + "version": "8.0.0", + "integrity": "sha512-sY22aA6xchAzprjyqmSEQv4UbAAzRN0L2dQB0NlN5acTTK9Don6nhoc3eAbUnpZiCANAMfd/+40kVdKfFygohg==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/get-stream": { + "version": "6.0.1", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/getpass": { + "version": "0.1.7", + "integrity": "sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==", + "dependencies": { + "assert-plus": "^1.0.0" + } + }, + "node_modules/git-raw-commits": { + "version": "2.0.11", + "integrity": "sha512-VnctFhw+xfj8Va1xtfEqCUD2XDrbAPSJx+hSrE5K7fGdjZruW7XV+QOrN7LF/RJyvspRiD2I0asWsxFp0ya26A==", + "dev": true, + "dependencies": { + "dargs": "^7.0.0", + "lodash": "^4.17.15", + "meow": "^8.0.0", + "split2": "^3.0.0", + "through2": "^4.0.0" + }, + "bin": { + "git-raw-commits": "cli.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/git-remote-origin-url": { + "version": "2.0.0", + "integrity": "sha512-eU+GGrZgccNJcsDH5LkXR3PB9M958hxc7sbA8DFJjrv9j4L2P/eZfKhM+QD6wyzpiv+b1BpK0XrYCxkovtjSLw==", + "dev": true, + "dependencies": { + "gitconfiglocal": "^1.0.0", + "pify": "^2.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/git-remote-origin-url/node_modules/pify": { + "version": "2.3.0", + "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/git-semver-tags": { + "version": "4.1.1", + "integrity": "sha512-OWyMt5zBe7xFs8vglMmhM9lRQzCWL3WjHtxNNfJTMngGym7pC1kh8sP6jevfydJ6LP3ZvGxfb6ABYgPUM0mtsA==", + "dev": true, + "dependencies": { + "meow": "^8.0.0", + "semver": "^6.0.0" + }, + "bin": { + "git-semver-tags": "cli.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/git-semver-tags/node_modules/semver": { + "version": "6.3.0", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/gitconfiglocal": { + "version": "1.0.0", + "integrity": "sha512-spLUXeTAVHxDtKsJc8FkFVgFtMdEN9qPGpL23VfSHx4fP4+Ds097IXLvymbnDH8FnmxX5Nr9bPw3A+AQ6mWEaQ==", + "dev": true, + "dependencies": { + "ini": "^1.3.2" + } + }, + "node_modules/glob": { + "version": "7.2.3", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "5.1.2", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/global-dirs": { + "version": "0.1.1", + "integrity": "sha512-NknMLn7F2J7aflwFOlGdNIuCDpN3VGoSoB+aap3KABFWbHVn1TCgFC+np23J8W2BiZbjfEw3BFBycSMv1AFblg==", + "dev": true, + "dependencies": { + "ini": "^1.3.4" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/globals": { + "version": "11.12.0", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/globby": { + "version": "11.1.0", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "dev": true, + "dependencies": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/gopd": { + "version": "1.0.1", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "dependencies": { + "get-intrinsic": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/got": { + "version": "9.6.0", + "integrity": "sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q==", + "dev": true, + "dependencies": { + "@sindresorhus/is": "^0.14.0", + "@szmarczak/http-timer": "^1.1.2", + "cacheable-request": "^6.0.0", + "decompress-response": "^3.3.0", + "duplexer3": "^0.1.4", + "get-stream": "^4.1.0", + "lowercase-keys": "^1.0.1", + "mimic-response": "^1.0.1", + "p-cancelable": "^1.0.0", + "to-readable-stream": "^1.0.0", + "url-parse-lax": "^3.0.0" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/got/node_modules/get-stream": { + "version": "4.1.0", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "dev": true, + "dependencies": { + "pump": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.10", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" + }, + "node_modules/growl": { + "version": "1.10.5", + "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", + "dev": true, + "engines": { + "node": ">=4.x" + } + }, + "node_modules/handlebars": { + "version": "4.7.7", + "integrity": "sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA==", + "dev": true, + "dependencies": { + "minimist": "^1.2.5", + "neo-async": "^2.6.0", + "source-map": "^0.6.1", + "wordwrap": "^1.0.0" + }, + "bin": { + "handlebars": "bin/handlebars" + }, + "engines": { + "node": ">=0.4.7" + }, + "optionalDependencies": { + "uglify-js": "^3.1.4" + } + }, + "node_modules/handler-agent": { + "version": "0.2.0", + "integrity": "sha512-cUduQxa5p3TFtGmb55mrRbkk/3EJCsLSeFrCIuTakQHQlYVWXeW2L9IUQUHyoHLI4UgpBNaN2JrZ0He1jPu+vg==", + "dev": true + }, + "node_modules/har-schema": { + "version": "2.0.0", + "integrity": "sha512-Oqluz6zhGX8cyRaTQlFMPw80bSJVG2x/cFb8ZPhUILGgHka9SsokCCOQgpveePerqidZOrT14ipqfJb7ILcW5Q==", + "engines": { + "node": ">=4" + } + }, + "node_modules/har-validator": { + "version": "5.1.5", + "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", + "deprecated": "this library is no longer supported", + "dependencies": { + "ajv": "^6.12.3", + "har-schema": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/har-validator/node_modules/ajv": { + "version": "6.12.6", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/har-validator/node_modules/json-schema-traverse": { + "version": "0.4.1", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" + }, + "node_modules/hard-rejection": { + "version": "2.1.0", + "integrity": "sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/has": { + "version": "1.0.3", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dependencies": { + "function-bind": "^1.1.1" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/has-ansi": { + "version": "2.0.0", + "integrity": "sha512-C8vBJ8DwUCx19vhm7urhTuUsr4/IyP6l4VzNQDv+ryHQObW3TTTp9yB68WpYgRe2bbaGuZ/se74IqFeVnMnLZg==", + "dependencies": { + "ansi-regex": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/has-ansi/node_modules/ansi-regex": { + "version": "2.1.1", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/has-flag": { + "version": "4.0.0", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/has-symbols": { + "version": "1.0.3", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.0", + "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", + "dependencies": { + "has-symbols": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-unicode": { + "version": "2.0.1", + "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==", + "dev": true + }, + "node_modules/has-yarn": { + "version": "2.1.0", + "integrity": "sha512-UqBRqi4ju7T+TqGNdqAO0PaSVGsDGJUBQvk9eUWNGRY1CFGDzYhLWoM7JQEemnlvVcv/YEmc2wNW8BC24EnUsw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/hasha": { + "version": "5.2.2", + "integrity": "sha512-Hrp5vIK/xr5SkeN2onO32H0MgNZ0f17HRNH39WfL0SYUNOTZ5Lz1TJ8Pajo/87dYGEFlLMm7mIc/k/s6Bvz9HQ==", + "dev": true, + "dependencies": { + "is-stream": "^2.0.0", + "type-fest": "^0.8.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/hasha/node_modules/type-fest": { + "version": "0.8.1", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/he": { + "version": "1.2.0", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "dev": true, + "bin": { + "he": "bin/he" + } + }, + "node_modules/hosted-git-info": { + "version": "4.1.0", + "integrity": "sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/hosted-git-info/node_modules/lru-cache": { + "version": "6.0.0", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/hosted-git-info/node_modules/yallist": { + "version": "4.0.0", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/html-escaper": { + "version": "2.0.2", + "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", + "dev": true + }, + "node_modules/http-cache-semantics": { + "version": "4.1.0", + "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==", + "dev": true + }, + "node_modules/http-proxy-agent": { + "version": "5.0.0", + "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", + "dev": true, + "dependencies": { + "@tootallnate/once": "2", + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/http-reasons": { + "version": "0.1.0", + "integrity": "sha512-P6kYh0lKZ+y29T2Gqz+RlC9WBLhKe8kDmcJ+A+611jFfxdPsbMRQ5aNmFRM3lENqFkK+HTTL+tlQviAiv0AbLQ==", + "dev": true + }, + "node_modules/http-signature": { + "version": "1.2.0", + "integrity": "sha512-CAbnr6Rz4CYQkLYUtSNXxQPUH2gK8f3iWexVlsnMeD+GjlsQ0Xsy1cOX+mN3dtxYomRy21CiOzU8Uhw6OwncEQ==", + "dependencies": { + "assert-plus": "^1.0.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" + }, + "engines": { + "node": ">=0.8", + "npm": ">=1.3.7" + } + }, + "node_modules/https-proxy-agent": { + "version": "5.0.1", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "dev": true, + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/human-signals": { + "version": "2.1.0", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "engines": { + "node": ">=10.17.0" + } + }, + "node_modules/humanize-ms": { + "version": "1.2.1", + "integrity": "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==", + "dev": true, + "dependencies": { + "ms": "^2.0.0" + } + }, + "node_modules/husky": { + "version": "7.0.4", + "integrity": "sha512-vbaCKN2QLtP/vD4yvs6iz6hBEo6wkSzs8HpRah1Z6aGmF2KW5PdYuAd7uX5a+OyBZHBhd+TFLqgjUgytQr4RvQ==", + "dev": true, + "bin": { + "husky": "lib/bin.js" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/typicode" + } + }, + "node_modules/iconv-lite": { + "version": "0.4.24", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ieee754": { + "version": "1.1.13", + "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==" + }, + "node_modules/ignore": { + "version": "5.2.4", + "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/ignore-by-default": { + "version": "1.0.1", + "integrity": "sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==" + }, + "node_modules/ignore-walk": { + "version": "5.0.1", + "integrity": "sha512-yemi4pMf51WKT7khInJqAvsIGzoqYXblnsz0ql8tM+yi1EKYTY1evX4NAbJrLL/Aanr2HyZeluqU+Oi7MGHokw==", + "dev": true, + "dependencies": { + "minimatch": "^5.0.1" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/ignore-walk/node_modules/brace-expansion": { + "version": "2.0.1", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/ignore-walk/node_modules/minimatch": { + "version": "5.1.6", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/immutable": { + "version": "4.0.0", + "integrity": "sha512-zIE9hX70qew5qTUjSS7wi1iwj/l7+m54KWU247nhM3v806UdGj1yDndXj+IOYxxtW9zyLI+xqFNZjTuDaLUqFw==" + }, + "node_modules/import-fresh": { + "version": "3.3.0", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/import-fresh/node_modules/resolve-from": { + "version": "4.0.0", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/import-lazy": { + "version": "2.1.0", + "integrity": "sha512-m7ZEHgtw69qOGw+jwxXkHlrlIPdTGkyh66zXZ1ajZbxkDBNjSY/LGbmjc7h0s2ELsUDTAhFr55TrPSSqJGPG0A==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/indent-string": { + "version": "3.2.0", + "integrity": "sha512-BYqTHXTGUIvg7t1r4sJNKcbDZkL92nkXA8YtRpbjFHRHGDL/NtUeiBJMeE60kIFN/Mg8ESaWQvftaYMGJzQZCQ==", + "engines": { + "node": ">=4" + } + }, + "node_modules/infer-owner": { + "version": "1.0.4", + "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==", + "dev": true + }, + "node_modules/inflight": { + "version": "1.0.6", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/ini": { + "version": "1.3.8", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "dev": true + }, + "node_modules/inquirer": { + "version": "8.2.5", + "integrity": "sha512-QAgPDQMEgrDssk1XiwwHoOGYF9BAbUcc1+j+FhEvaOt8/cKRqyLn0U5qA6F74fGhTMGxf92pOvPBeh29jQJDTQ==", + "dependencies": { + "ansi-escapes": "^4.2.1", + "chalk": "^4.1.1", + "cli-cursor": "^3.1.0", + "cli-width": "^3.0.0", + "external-editor": "^3.0.3", + "figures": "^3.0.0", + "lodash": "^4.17.21", + "mute-stream": "0.0.8", + "ora": "^5.4.1", + "run-async": "^2.4.0", + "rxjs": "^7.5.5", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0", + "through": "^2.3.6", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/inquirer/node_modules/chalk": { + "version": "4.1.2", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/inquirer/node_modules/log-symbols": { + "version": "4.1.0", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", + "dependencies": { + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/inquirer/node_modules/ora": { + "version": "5.4.1", + "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==", + "dependencies": { + "bl": "^4.1.0", + "chalk": "^4.1.0", + "cli-cursor": "^3.1.0", + "cli-spinners": "^2.5.0", + "is-interactive": "^1.0.0", + "is-unicode-supported": "^0.1.0", + "log-symbols": "^4.1.0", + "strip-ansi": "^6.0.0", + "wcwidth": "^1.0.1" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/insync": { + "version": "2.1.1", + "integrity": "sha512-UzUhOZFpCMM22Xlig9iUPqalf8n7c4eYScamce1C+jN3ad8FtmVm42ryMwVq0hAxHbwUhWFhPvTFQQpFdDUKkw==", + "dev": true + }, + "node_modules/io-ts": { + "version": "2.2.20", + "integrity": "sha512-Rq2BsYmtwS5vVttie4rqrOCIfHCS9TgpRLFpKQCM1wZBBRY9nWVGmEvm2FnDbSE2un1UE39DvFpTR5UL47YDcA==", + "dev": true, + "peerDependencies": { + "fp-ts": "^2.5.0" + } + }, + "node_modules/ip": { + "version": "2.0.0", + "integrity": "sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==", + "dev": true + }, + "node_modules/is-arguments": { + "version": "1.1.1", + "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "dev": true + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-callable": { + "version": "1.2.7", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-ci": { + "version": "2.0.0", + "integrity": "sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==", + "dev": true, + "dependencies": { + "ci-info": "^2.0.0" + }, + "bin": { + "is-ci": "bin.js" + } + }, + "node_modules/is-ci/node_modules/ci-info": { + "version": "2.0.0", + "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==", + "dev": true + }, + "node_modules/is-core-module": { + "version": "2.11.0", + "integrity": "sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==", + "dependencies": { + "has": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-docker": { + "version": "2.2.1", + "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", + "bin": { + "is-docker": "cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "4.0.0", + "integrity": "sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-generator-function": { + "version": "1.0.10", + "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-installed-globally": { + "version": "0.4.0", + "integrity": "sha512-iwGqO3J21aaSkC7jWnHP/difazwS7SFeIqxv6wEtLU8Y5KlzFTjyqcSIT0d8s4+dDhKytsk9PJZ2BkS5eZwQRQ==", + "dev": true, + "dependencies": { + "global-dirs": "^3.0.0", + "is-path-inside": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-installed-globally/node_modules/global-dirs": { + "version": "3.0.1", + "integrity": "sha512-NBcGGFbBA9s1VzD41QXDG+3++t9Mn5t1FpLdhESY6oKY4gYTFpX4wO3sqGUa0Srjtbfj3szX0RnemmrVRUdULA==", + "dev": true, + "dependencies": { + "ini": "2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-installed-globally/node_modules/ini": { + "version": "2.0.0", + "integrity": "sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/is-interactive": { + "version": "1.0.0", + "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-lambda": { + "version": "1.0.1", + "integrity": "sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==", + "dev": true + }, + "node_modules/is-npm": { + "version": "5.0.0", + "integrity": "sha512-WW/rQLOazUq+ST/bCAVBp/2oMERWLsR7OrKyt052dNDk4DHcDE0/7QSXITlmi+VBcV13DfIbysG3tZJm5RfdBA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-number-like": { + "version": "1.0.8", + "integrity": "sha512-6rZi3ezCyFcn5L71ywzz2bS5b2Igl1En3eTlZlvKjpz1n3IZLAYMbKYAIQgFmEu0GENg92ziU/faEOA/aixjbA==", + "dependencies": { + "lodash.isfinite": "^3.3.2" + } + }, + "node_modules/is-obj": { + "version": "2.0.0", + "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-object": { + "version": "1.0.2", + "integrity": "sha512-2rRIahhZr2UWb45fIOuvZGpFtz0TyOZLf32KxBbSoUCeZR495zCKlWUKKUByk3geS2eAs7ZAABt0Y/Rx0GiQGA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-observable": { + "version": "1.1.0", + "integrity": "sha512-NqCa4Sa2d+u7BWc6CukaObG3Fh+CU9bvixbpcXYhy2VvYS7vVGIdAgnIS5Ks3A/cqk4rebLJ9s8zBstT2aKnIA==", + "dependencies": { + "symbol-observable": "^1.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/is-path-inside": { + "version": "3.0.3", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-plain-obj": { + "version": "1.1.0", + "integrity": "sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-promise": { + "version": "2.2.2", + "integrity": "sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==" + }, + "node_modules/is-stream": { + "version": "2.0.1", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-text-path": { + "version": "1.0.1", + "integrity": "sha512-xFuJpne9oFz5qDaodwmmG08e3CawH/2ZV8Qqza1Ko7Sk8POWbkRdwIoAWVhqvq0XeUzANEhKo2n0IXUGBm7A/w==", + "dev": true, + "dependencies": { + "text-extensions": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-typed-array": { + "version": "1.1.10", + "integrity": "sha512-PJqgEHiWZvMpaFZ3uTc8kHPM4+4ADTlDniuQL7cU/UDA0Ql7F70yGfHph3cLNe+c9toaigv+DFzTJKhc2CtO6A==", + "dependencies": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-typedarray": { + "version": "1.0.0", + "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==" + }, + "node_modules/is-unicode-supported": { + "version": "0.1.0", + "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-windows": { + "version": "1.0.2", + "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-wsl": { + "version": "2.2.0", + "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "dependencies": { + "is-docker": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-yarn-global": { + "version": "0.3.0", + "integrity": "sha512-VjSeb/lHmkoyd8ryPVIKvOCn4D1koMqY+vqyjjUfc3xyKtP4dYOxM44sZrnqQSzSds3xyOrUTLTC9LVCVgLngw==", + "dev": true + }, + "node_modules/isarray": { + "version": "1.0.0", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" + }, + "node_modules/isexe": { + "version": "2.0.0", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" + }, + "node_modules/isomorphic-fetch": { + "version": "3.0.0", + "integrity": "sha512-qvUtwJ3j6qwsF3jLxkZ72qCgjMysPzDfeV240JHiGZsANBYd+EEuu35v7dfrJ9Up0Ak07D7GGSkGhCHTqg/5wA==", + "dev": true, + "dependencies": { + "node-fetch": "^2.6.1", + "whatwg-fetch": "^3.4.1" + } + }, + "node_modules/isstream": { + "version": "0.1.2", + "integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==" + }, + "node_modules/istanbul-lib-coverage": { + "version": "3.2.0", + "integrity": "sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-hook": { + "version": "3.0.0", + "integrity": "sha512-Pt/uge1Q9s+5VAZ+pCo16TYMWPBIl+oaNIjgLQxcX0itS6ueeaA+pEfThZpH8WxhFgCiEb8sAJY6MdUKgiIWaQ==", + "dev": true, + "dependencies": { + "append-transform": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-instrument": { + "version": "5.2.1", + "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", + "dev": true, + "dependencies": { + "@babel/core": "^7.12.3", + "@babel/parser": "^7.14.7", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-instrument/node_modules/semver": { + "version": "6.3.0", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/istanbul-lib-processinfo": { + "version": "2.0.3", + "integrity": "sha512-NkwHbo3E00oybX6NGJi6ar0B29vxyvNwoC7eJ4G4Yq28UfY758Hgn/heV8VRFhevPED4LXfFz0DQ8z/0kw9zMg==", + "dev": true, + "dependencies": { + "archy": "^1.0.0", + "cross-spawn": "^7.0.3", + "istanbul-lib-coverage": "^3.2.0", + "p-map": "^3.0.0", + "rimraf": "^3.0.0", + "uuid": "^8.3.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-processinfo/node_modules/p-map": { + "version": "3.0.0", + "integrity": "sha512-d3qXVTF/s+W+CdJ5A29wywV2n8CQQYahlgz2bFiA+4eVNJbHJodPZ+/gXwPGh0bOqA+j8S+6+ckmvLGPk1QpxQ==", + "dev": true, + "dependencies": { + "aggregate-error": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-report": { + "version": "3.0.0", + "integrity": "sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw==", + "dev": true, + "dependencies": { + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^3.0.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-source-maps": { + "version": "4.0.1", + "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", + "dev": true, + "dependencies": { + "debug": "^4.1.1", + "istanbul-lib-coverage": "^3.0.0", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-reports": { + "version": "3.1.5", + "integrity": "sha512-nUsEMa9pBt/NOHqbcbeJEgqIlY/K7rVWUX6Lql2orY5e9roQOthbR3vtY4zzf2orPELg80fnxxk9zUyPlgwD1w==", + "dev": true, + "dependencies": { + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-diff": { + "version": "28.1.3", + "integrity": "sha512-8RqP1B/OXzjjTWkqMX67iqgwBVJRgCyKD3L9nq+6ZqJMdvjE8RgHktqZ6jNrkdMT+dJuYNI3rhQpxaz7drJHfw==", + "dev": true, + "dependencies": { + "chalk": "^4.0.0", + "diff-sequences": "^28.1.1", + "jest-get-type": "^28.0.2", + "pretty-format": "^28.1.3" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/jest-get-type": { + "version": "28.0.2", + "integrity": "sha512-ioj2w9/DxSYHfOm5lJKCdcAmPJzQXmbM/Url3rhlghrPvT3tt+7a/+oXc9azkKmLvoiXjtV83bEWqi+vs5nlPA==", + "dev": true, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/jest-haste-map": { + "version": "28.1.3", + "integrity": "sha512-3S+RQWDXccXDKSWnkHa/dPwt+2qwA8CJzR61w3FoYCvoo3Pn8tvGcysmMF0Bj0EX5RYvAI2EIvC57OmotfdtKA==", + "dev": true, + "dependencies": { + "@jest/types": "^28.1.3", + "@types/graceful-fs": "^4.1.3", + "@types/node": "*", + "anymatch": "^3.0.3", + "fb-watchman": "^2.0.0", + "graceful-fs": "^4.2.9", + "jest-regex-util": "^28.0.2", + "jest-util": "^28.1.3", + "jest-worker": "^28.1.3", + "micromatch": "^4.0.4", + "walker": "^1.0.8" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + }, + "optionalDependencies": { + "fsevents": "^2.3.2" + } + }, + "node_modules/jest-matcher-utils": { + "version": "28.1.3", + "integrity": "sha512-kQeJ7qHemKfbzKoGjHHrRKH6atgxMk8Enkk2iPQ3XwO6oE/KYD8lMYOziCkeSB9G4adPM4nR1DE8Tf5JeWH6Bw==", + "dev": true, + "dependencies": { + "chalk": "^4.0.0", + "jest-diff": "^28.1.3", + "jest-get-type": "^28.0.2", + "pretty-format": "^28.1.3" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/jest-message-util": { + "version": "28.1.3", + "integrity": "sha512-PFdn9Iewbt575zKPf1286Ht9EPoJmYT7P0kY+RibeYZ2XtOr53pDLEFoTWXbd1h4JiGiWpTBC84fc8xMXQMb7g==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.12.13", + "@jest/types": "^28.1.3", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.4", + "pretty-format": "^28.1.3", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/jest-regex-util": { + "version": "28.0.2", + "integrity": "sha512-4s0IgyNIy0y9FK+cjoVYoxamT7Zeo7MhzqRGx7YDYmaQn1wucY9rotiGkBzzcMXTtjrCAP/f7f+E0F7+fxPNdw==", + "dev": true, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/jest-snapshot": { + "version": "28.1.3", + "integrity": "sha512-4lzMgtiNlc3DU/8lZfmqxN3AYD6GGLbl+72rdBpXvcV+whX7mDrREzkPdp2RnmfIiWBg1YbuFSkXduF2JcafJg==", + "dev": true, + "dependencies": { + "@babel/core": "^7.11.6", + "@babel/generator": "^7.7.2", + "@babel/plugin-syntax-typescript": "^7.7.2", + "@babel/traverse": "^7.7.2", + "@babel/types": "^7.3.3", + "@jest/expect-utils": "^28.1.3", + "@jest/transform": "^28.1.3", + "@jest/types": "^28.1.3", + "@types/babel__traverse": "^7.0.6", + "@types/prettier": "^2.1.5", + "babel-preset-current-node-syntax": "^1.0.0", + "chalk": "^4.0.0", + "expect": "^28.1.3", + "graceful-fs": "^4.2.9", + "jest-diff": "^28.1.3", + "jest-get-type": "^28.0.2", + "jest-haste-map": "^28.1.3", + "jest-matcher-utils": "^28.1.3", + "jest-message-util": "^28.1.3", + "jest-util": "^28.1.3", + "natural-compare": "^1.4.0", + "pretty-format": "^28.1.3", + "semver": "^7.3.5" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/jest-util": { + "version": "28.1.3", + "integrity": "sha512-XdqfpHwpcSRko/C35uLYFM2emRAltIIKZiJ9eAmhjsj0CqZMa0p1ib0R5fWIqGhn1a103DebTbpqIaP1qCQ6tQ==", + "dev": true, + "dependencies": { + "@jest/types": "^28.1.3", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/jest-worker": { + "version": "28.1.3", + "integrity": "sha512-CqRA220YV/6jCo8VWvAt1KKx6eek1VIHMPeLEbpcfSfkEeWyBNppynM/o6q+Wmw+sOhos2ml34wZbSX3G13//g==", + "dev": true, + "dependencies": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/jest-worker/node_modules/supports-color": { + "version": "8.1.1", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/jju": { + "version": "1.4.0", + "integrity": "sha512-8wb9Yw966OSxApiCt0K3yNJL8pnNeIv+OEq2YMidz4FKP6nonSRoOXc80iXY4JaN2FC11B9qsNmDsm+ZOfMROA==", + "dev": true + }, + "node_modules/jmespath": { + "version": "0.16.0", + "integrity": "sha512-9FzQjJ7MATs1tSpnco1K6ayiYE3figslrXA72G2HQ/n76RzvYlofyi5QM+iX4YRs/pu3yzxlVQSST23+dMDknw==", + "engines": { + "node": ">= 0.6.0" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "node_modules/js-yaml": { + "version": "4.1.0", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsbn": { + "version": "0.1.1", + "integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==" + }, + "node_modules/jsesc": { + "version": "2.5.2", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "dev": true, + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/json-buffer": { + "version": "3.0.0", + "integrity": "sha512-CuUqjv0FUZIdXkHPI8MezCnFCdaTAacej1TZYulLoAg1h/PhwkdXFN4V/gzY4g+fMBCOV2xF+rp7t2XD2ns/NQ==", + "dev": true + }, + "node_modules/json-parse-better-errors": { + "version": "1.0.2", + "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", + "dev": true + }, + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true + }, + "node_modules/json-parse-helpfulerror": { + "version": "1.0.3", + "integrity": "sha512-XgP0FGR77+QhUxjXkwOMkC94k3WtqEBfcnjWqhRd82qTat4SWKRE+9kUnynz/shm3I4ea2+qISvTIeGTNU7kJg==", + "dev": true, + "dependencies": { + "jju": "^1.1.0" + } + }, + "node_modules/json-pointer": { + "version": "0.6.2", + "integrity": "sha512-vLWcKbOaXlO+jvRy4qNd+TI1QUPZzfJj1tpJ3vAXDych5XJf93ftpUKe5pKCrzyIIwgBJcOcCVRUfqQP25afBw==", + "dev": true, + "dependencies": { + "foreach": "^2.0.4" + } + }, + "node_modules/json-promise": { + "version": "1.1.8", + "integrity": "sha512-rz31P/7VfYnjQFrF60zpPTT0egMPlc8ZvIQHWs4ZtNZNnAXRmXo6oS+6eyWr5sEMG03OVhklNrTXxiIRYzoUgQ==", + "dev": true, + "dependencies": { + "bluebird": "*" + } + }, + "node_modules/json-schema": { + "version": "0.4.0", + "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==" + }, + "node_modules/json-schema-compare": { + "version": "0.2.2", + "integrity": "sha512-c4WYmDKyJXhs7WWvAWm3uIYnfyWFoIp+JEoX34rctVvEkMYCPGhXtvmFFXiffBbxfZsvQ0RNnV5H7GvDF5HCqQ==", + "dev": true, + "dependencies": { + "lodash": "^4.17.4" + } + }, + "node_modules/json-schema-faker": { + "version": "0.5.0-rcv.40", + "integrity": "sha512-BczZvu03jKrGh3ovCWrHusiX6MwiaKK2WZeyomKBNA8Nm/n7aBYz0mub1CnONB6cgxOZTNxx4afNmLblbUmZbA==", + "dev": true, + "dependencies": { + "json-schema-ref-parser": "^6.1.0", + "jsonpath-plus": "^5.1.0" + }, + "bin": { + "jsf": "bin/gen.js" + } + }, + "node_modules/json-schema-ref-parser": { + "version": "6.1.0", + "integrity": "sha512-pXe9H1m6IgIpXmE5JSb8epilNTGsmTb2iPohAXpOdhqGFbQjNeHHsZxU+C8w6T81GZxSPFLeUoqDJmzxx5IGuw==", + "deprecated": "Please switch to @apidevtools/json-schema-ref-parser", + "dev": true, + "dependencies": { + "call-me-maybe": "^1.0.1", + "js-yaml": "^3.12.1", + "ono": "^4.0.11" + } + }, + "node_modules/json-schema-ref-parser/node_modules/argparse": { + "version": "1.0.10", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/json-schema-ref-parser/node_modules/js-yaml": { + "version": "3.14.1", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/json-schema-traverse": { + "version": "1.0.0", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" + }, + "node_modules/json-stringify-safe": { + "version": "5.0.1", + "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==" + }, + "node_modules/json5": { + "version": "2.2.3", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true, + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/jsonc-parser": { + "version": "2.2.1", + "integrity": "sha512-o6/yDBYccGvTz1+QFevz6l6OBZ2+fMVu2JZ9CIhzsYRX4mjaK5IyX9eldUdCmga16zlgQxyrj5pt9kzuj2C02w==", + "dev": true + }, + "node_modules/jsonfile": { + "version": "6.1.0", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/jsonlines": { + "version": "0.1.1", + "integrity": "sha512-ekDrAGso79Cvf+dtm+mL8OBI2bmAOt3gssYs833De/C9NmIpWDWyUO4zPgB5x2/OhY366dkhgfPMYfwZF7yOZA==", + "dev": true + }, + "node_modules/jsonparse": { + "version": "1.3.1", + "integrity": "sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==", + "dev": true, + "engines": [ + "node >= 0.2.0" + ] + }, + "node_modules/jsonpath-plus": { + "version": "5.1.0", + "integrity": "sha512-890w2Pjtj0iswAxalRlt2kHthi6HKrXEfZcn+ZNZptv7F3rUGIeDuZo+C+h4vXBHLEsVjJrHeCm35nYeZLzSBQ==", + "dev": true, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/jsonpointer.js": { + "version": "0.4.0", + "integrity": "sha512-2bf/1crAmPpsmj1I6rDT6W0SOErkrNBpb555xNWcMVWYrX6VnXpG0GRMQ2shvOHwafpfse8q0gnzPFYVH6Tqdg==", + "dev": true + }, + "node_modules/JSONStream": { + "version": "1.3.5", + "integrity": "sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==", + "dev": true, + "dependencies": { + "jsonparse": "^1.2.0", + "through": ">=2.2.7 <3" + }, + "bin": { + "JSONStream": "bin.js" + }, + "engines": { + "node": "*" + } + }, + "node_modules/jsprim": { + "version": "1.4.2", + "integrity": "sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==", + "dependencies": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.4.0", + "verror": "1.10.0" + }, + "engines": { + "node": ">=0.6.0" + } + }, + "node_modules/just-extend": { + "version": "4.2.1", + "integrity": "sha512-g3UB796vUFIY90VIv/WX3L2c8CS2MdWUww3CNrYmqza1Fg0DURc2K/O4YrnklBdQarSJ/y8JnJYDGc+1iumQjg==", + "dev": true + }, + "node_modules/keyv": { + "version": "3.1.0", + "integrity": "sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA==", + "dev": true, + "dependencies": { + "json-buffer": "3.0.0" + } + }, + "node_modules/kind-of": { + "version": "6.0.3", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/kleur": { + "version": "3.0.3", + "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/latest-version": { + "version": "5.1.0", + "integrity": "sha512-weT+r0kTkRQdCdYCNtkMwWXQTMEswKrFBkm4ckQOMVhhqhIMI1UT2hMj+1iigIhgSZm5gTmrRXBNoGUgaTY1xA==", + "dev": true, + "dependencies": { + "package-json": "^6.3.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/lazystream": { + "version": "1.0.1", + "integrity": "sha512-b94GiNHQNy6JNTrt5w6zNyffMrNkXZb3KTkCZJb2V1xaEGCk093vkZ2jk3tpaeP33/OiXC+WvK9AxUebnf5nbw==", + "dependencies": { + "readable-stream": "^2.0.5" + }, + "engines": { + "node": ">= 0.6.3" + } + }, + "node_modules/lazystream/node_modules/readable-stream": { + "version": "2.3.7", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/lazystream/node_modules/safe-buffer": { + "version": "5.1.2", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/lazystream/node_modules/string_decoder": { + "version": "1.1.1", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/libnpmconfig": { + "version": "1.2.1", + "integrity": "sha512-9esX8rTQAHqarx6qeZqmGQKBNZR5OIbl/Ayr0qQDy3oXja2iFVQQI81R6GZ2a02bSNZ9p3YOGX1O6HHCb1X7kA==", + "deprecated": "This module is not used anymore. npm config is parsed by npm itself and by @npmcli/config", + "dev": true, + "dependencies": { + "figgy-pudding": "^3.5.1", + "find-up": "^3.0.0", + "ini": "^1.3.5" + } + }, + "node_modules/libnpmconfig/node_modules/find-up": { + "version": "3.0.0", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "dependencies": { + "locate-path": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/libnpmconfig/node_modules/locate-path": { + "version": "3.0.0", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "dependencies": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/libnpmconfig/node_modules/p-limit": { + "version": "2.3.0", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/libnpmconfig/node_modules/p-locate": { + "version": "3.0.0", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "dependencies": { + "p-limit": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/libnpmconfig/node_modules/path-exists": { + "version": "3.0.0", + "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/lilconfig": { + "version": "2.0.5", + "integrity": "sha512-xaYmXZtTHPAw5m+xLN8ab9C+3a8YmV3asNSPOATITbtwrfbwaLJj8h66H1WMIpALCkqsIzK3h7oQ+PdX+LQ9Eg==", + "engines": { + "node": ">=10" + } + }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "dev": true + }, + "node_modules/lint-staged": { + "version": "12.5.0", + "integrity": "sha512-BKLUjWDsKquV/JuIcoQW4MSAI3ggwEImF1+sB4zaKvyVx1wBk3FsG7UK9bpnmBTN1pm7EH2BBcMwINJzCRv12g==", + "dependencies": { + "cli-truncate": "^3.1.0", + "colorette": "^2.0.16", + "commander": "^9.3.0", + "debug": "^4.3.4", + "execa": "^5.1.1", + "lilconfig": "2.0.5", + "listr2": "^4.0.5", + "micromatch": "^4.0.5", + "normalize-path": "^3.0.0", + "object-inspect": "^1.12.2", + "pidtree": "^0.5.0", + "string-argv": "^0.3.1", + "supports-color": "^9.2.2", + "yaml": "^1.10.2" + }, + "bin": { + "lint-staged": "bin/lint-staged.js" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/lint-staged" + } + }, + "node_modules/lint-staged/node_modules/commander": { + "version": "9.5.0", + "integrity": "sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==", + "engines": { + "node": "^12.20.0 || >=14" + } + }, + "node_modules/lint-staged/node_modules/supports-color": { + "version": "9.3.1", + "integrity": "sha512-knBY82pjmnIzK3NifMo3RxEIRD9E0kIzV4BKcyTZ9+9kWgLMxd4PrsTSMoFQUabgRBbF8KOLRDCyKgNV+iK44Q==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/liquid-json": { + "version": "0.3.1", + "integrity": "sha512-wUayTU8MS827Dam6MxgD72Ui+KOSF+u/eIqpatOtjnvgJ0+mnDq33uC2M7J0tPK+upe/DpUAuK4JUU89iBoNKQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/listenercount": { + "version": "1.0.1", + "integrity": "sha512-3mk/Zag0+IJxeDrxSgaDPy4zZ3w05PRZeJNnlWhzFz5OkX49J4krc+A8X2d2M69vGMBEX0uyl8M+W+8gH+kBqQ==", + "dev": true + }, + "node_modules/listr": { + "version": "0.14.3", + "integrity": "sha512-RmAl7su35BFd/xoMamRjpIE4j3v+L28o8CT5YhAXQJm1fD+1l9ngXY8JAQRJ+tFK2i5njvi0iRUKV09vPwA0iA==", + "dependencies": { + "@samverschueren/stream-to-observable": "^0.3.0", + "is-observable": "^1.1.0", + "is-promise": "^2.1.0", + "is-stream": "^1.1.0", + "listr-silent-renderer": "^1.1.1", + "listr-update-renderer": "^0.5.0", + "listr-verbose-renderer": "^0.5.0", + "p-map": "^2.0.0", + "rxjs": "^6.3.3" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/listr-silent-renderer": { + "version": "1.1.1", + "integrity": "sha512-L26cIFm7/oZeSNVhWB6faeorXhMg4HNlb/dS/7jHhr708jxlXrtrBWo4YUxZQkc6dGoxEAe6J/D3juTRBUzjtA==", + "engines": { + "node": ">=4" + } + }, + "node_modules/listr-update-renderer": { + "version": "0.5.0", + "integrity": "sha512-tKRsZpKz8GSGqoI/+caPmfrypiaq+OQCbd+CovEC24uk1h952lVj5sC7SqyFUm+OaJ5HN/a1YLt5cit2FMNsFA==", + "dependencies": { + "chalk": "^1.1.3", + "cli-truncate": "^0.2.1", + "elegant-spinner": "^1.0.1", + "figures": "^1.7.0", + "indent-string": "^3.0.0", + "log-symbols": "^1.0.2", + "log-update": "^2.3.0", + "strip-ansi": "^3.0.1" + }, + "engines": { + "node": ">=6" + }, + "peerDependencies": { + "listr": "^0.14.2" + } + }, + "node_modules/listr-update-renderer/node_modules/ansi-regex": { + "version": "2.1.1", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/listr-update-renderer/node_modules/ansi-styles": { + "version": "2.2.1", + "integrity": "sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/listr-update-renderer/node_modules/chalk": { + "version": "1.1.3", + "integrity": "sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A==", + "dependencies": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/listr-update-renderer/node_modules/cli-truncate": { + "version": "0.2.1", + "integrity": "sha512-f4r4yJnbT++qUPI9NR4XLDLq41gQ+uqnPItWG0F5ZkehuNiTTa3EY0S4AqTSUOeJ7/zU41oWPQSNkW5BqPL9bg==", + "dependencies": { + "slice-ansi": "0.0.4", + "string-width": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/listr-update-renderer/node_modules/figures": { + "version": "1.7.0", + "integrity": "sha512-UxKlfCRuCBxSXU4C6t9scbDyWZ4VlaFFdojKtzJuSkuOBQ5CNFum+zZXFwHjo+CxBC1t6zlYPgHIgFjL8ggoEQ==", + "dependencies": { + "escape-string-regexp": "^1.0.5", + "object-assign": "^4.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/listr-update-renderer/node_modules/is-fullwidth-code-point": { + "version": "1.0.0", + "integrity": "sha512-1pqUqRjkhPJ9miNq9SwMfdvi6lBJcd6eFxvfaivQhaH3SgisfiuudvFntdKOmxuee/77l+FPjKrQjWvmPjWrRw==", + "dependencies": { + "number-is-nan": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/listr-update-renderer/node_modules/slice-ansi": { + "version": "0.0.4", + "integrity": "sha512-up04hB2hR92PgjpyU3y/eg91yIBILyjVY26NvvciY3EVVPjybkMszMpXQ9QAkcS3I5rtJBDLoTxxg+qvW8c7rw==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/listr-update-renderer/node_modules/string-width": { + "version": "1.0.2", + "integrity": "sha512-0XsVpQLnVCXHJfyEs8tC0zpTVIr5PKKsQtkT29IwupnPTjtPmQ3xT/4yCREF9hYkV/3M3kzcUTSAZT6a6h81tw==", + "dependencies": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/listr-update-renderer/node_modules/strip-ansi": { + "version": "3.0.1", + "integrity": "sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==", + "dependencies": { + "ansi-regex": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/listr-update-renderer/node_modules/supports-color": { + "version": "2.0.0", + "integrity": "sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g==", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/listr-verbose-renderer": { + "version": "0.5.0", + "integrity": "sha512-04PDPqSlsqIOaaaGZ+41vq5FejI9auqTInicFRndCBgE3bXG8D6W1I+mWhk+1nqbHmyhla/6BUrd5OSiHwKRXw==", + "dependencies": { + "chalk": "^2.4.1", + "cli-cursor": "^2.1.0", + "date-fns": "^1.27.2", + "figures": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/listr-verbose-renderer/node_modules/ansi-styles": { + "version": "3.2.1", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/listr-verbose-renderer/node_modules/chalk": { + "version": "2.4.2", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/listr-verbose-renderer/node_modules/cli-cursor": { + "version": "2.1.0", + "integrity": "sha512-8lgKz8LmCRYZZQDpRyT2m5rKJ08TnU4tR9FFFW2rxpxR1FzWi4PQ/NfyODchAatHaUgnSPVcx/R5w6NuTBzFiw==", + "dependencies": { + "restore-cursor": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/listr-verbose-renderer/node_modules/color-convert": { + "version": "1.9.3", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/listr-verbose-renderer/node_modules/color-name": { + "version": "1.1.3", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" + }, + "node_modules/listr-verbose-renderer/node_modules/date-fns": { + "version": "1.30.1", + "integrity": "sha512-hBSVCvSmWC+QypYObzwGOd9wqdDpOt+0wl0KbU+R+uuZBS1jN8VsD1ss3irQDknRj5NvxiTF6oj/nDRnN/UQNw==" + }, + "node_modules/listr-verbose-renderer/node_modules/figures": { + "version": "2.0.0", + "integrity": "sha512-Oa2M9atig69ZkfwiApY8F2Yy+tzMbazyvqv21R0NsSC8floSOC09BbT1ITWAdoMGQvJ/aZnR1KMwdx9tvHnTNA==", + "dependencies": { + "escape-string-regexp": "^1.0.5" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/listr-verbose-renderer/node_modules/has-flag": { + "version": "3.0.0", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "engines": { + "node": ">=4" + } + }, + "node_modules/listr-verbose-renderer/node_modules/mimic-fn": { + "version": "1.2.0", + "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", + "engines": { + "node": ">=4" + } + }, + "node_modules/listr-verbose-renderer/node_modules/onetime": { + "version": "2.0.1", + "integrity": "sha512-oyyPpiMaKARvvcgip+JV+7zci5L8D1W9RZIz2l1o08AM3pfspitVWnPt3mzHcBPp12oYMTy0pqrFs/C+m3EwsQ==", + "dependencies": { + "mimic-fn": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/listr-verbose-renderer/node_modules/restore-cursor": { + "version": "2.0.0", + "integrity": "sha512-6IzJLuGi4+R14vwagDHX+JrXmPVtPpn4mffDJ1UdR7/Edm87fl6yi8mMBIVvFtJaNTUvjughmW4hwLhRG7gC1Q==", + "dependencies": { + "onetime": "^2.0.0", + "signal-exit": "^3.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/listr-verbose-renderer/node_modules/supports-color": { + "version": "5.5.0", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/listr/node_modules/is-stream": { + "version": "1.1.0", + "integrity": "sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/listr/node_modules/rxjs": { + "version": "6.6.7", + "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==", + "dependencies": { + "tslib": "^1.9.0" + }, + "engines": { + "npm": ">=2.0.0" + } + }, + "node_modules/listr/node_modules/tslib": { + "version": "1.14.1", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + }, + "node_modules/listr2": { + "version": "4.0.5", + "integrity": "sha512-juGHV1doQdpNT3GSTs9IUN43QJb7KHdF9uqg7Vufs/tG9VTzpFphqF4pm/ICdAABGQxsyNn9CiYA3StkI6jpwA==", + "dependencies": { + "cli-truncate": "^2.1.0", + "colorette": "^2.0.16", + "log-update": "^4.0.0", + "p-map": "^4.0.0", + "rfdc": "^1.3.0", + "rxjs": "^7.5.5", + "through": "^2.3.8", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + }, + "peerDependencies": { + "enquirer": ">= 2.3.0 < 3" + }, + "peerDependenciesMeta": { + "enquirer": { + "optional": true + } + } + }, + "node_modules/listr2/node_modules/cli-truncate": { + "version": "2.1.0", + "integrity": "sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg==", + "dependencies": { + "slice-ansi": "^3.0.0", + "string-width": "^4.2.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/listr2/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "engines": { + "node": ">=8" + } + }, + "node_modules/listr2/node_modules/log-update": { + "version": "4.0.0", + "integrity": "sha512-9fkkDevMefjg0mmzWFBW8YkFP91OrizzkW3diF7CpG+S2EYdy4+TVfGwz1zeF8x7hCx1ovSPTOE9Ngib74qqUg==", + "dependencies": { + "ansi-escapes": "^4.3.0", + "cli-cursor": "^3.1.0", + "slice-ansi": "^4.0.0", + "wrap-ansi": "^6.2.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/listr2/node_modules/log-update/node_modules/slice-ansi": { + "version": "4.0.0", + "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", + "dependencies": { + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" + } + }, + "node_modules/listr2/node_modules/log-update/node_modules/wrap-ansi": { + "version": "6.2.0", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/listr2/node_modules/p-map": { + "version": "4.0.0", + "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", + "dependencies": { + "aggregate-error": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/listr2/node_modules/slice-ansi": { + "version": "3.0.0", + "integrity": "sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ==", + "dependencies": { + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/load-json-file": { + "version": "4.0.0", + "integrity": "sha512-Kx8hMakjX03tiGTLAIdJ+lL0htKnXjEZN6hk/tozf/WOuYGdZBJrZ+rCJRbVCugsjB3jMLn9746NsQIf5VjBMw==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.2", + "parse-json": "^4.0.0", + "pify": "^3.0.0", + "strip-bom": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/load-json-file/node_modules/parse-json": { + "version": "4.0.0", + "integrity": "sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==", + "dev": true, + "dependencies": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/load-json-file/node_modules/strip-bom": { + "version": "3.0.0", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/locate-path": { + "version": "6.0.0", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, + "node_modules/lodash.camelcase": { + "version": "4.3.0", + "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==", + "dev": true + }, + "node_modules/lodash.defaults": { + "version": "4.2.0", + "integrity": "sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ==" + }, + "node_modules/lodash.difference": { + "version": "4.5.0", + "integrity": "sha512-dS2j+W26TQ7taQBGN8Lbbq04ssV3emRw4NY58WErlTO29pIqS0HmoT5aJ9+TUQ1N3G+JOZSji4eugsWwGp9yPA==" + }, + "node_modules/lodash.flatten": { + "version": "4.4.0", + "integrity": "sha512-C5N2Z3DgnnKr0LOpv/hKCgKdb7ZZwafIrsesve6lmzvZIRZRGaZ/l6Q8+2W7NaT+ZwO3fFlSCzCzrDCFdJfZ4g==" + }, + "node_modules/lodash.flattendeep": { + "version": "4.4.0", + "integrity": "sha512-uHaJFihxmJcEX3kT4I23ABqKKalJ/zDrDg0lsFtc1h+3uw49SIJ5beyhx5ExVRti3AvKoOJngIj7xz3oylPdWQ==", + "dev": true + }, + "node_modules/lodash.get": { + "version": "4.4.2", + "integrity": "sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==", + "dev": true + }, + "node_modules/lodash.isequalwith": { + "version": "4.4.0", + "integrity": "sha512-dcZON0IalGBpRmJBmMkaoV7d3I80R2O+FrzsZyHdNSFrANq/cgDqKQNmAHE8UEj4+QYWwwhkQOVdLHiAopzlsQ==", + "dev": true + }, + "node_modules/lodash.isfinite": { + "version": "3.3.2", + "integrity": "sha512-7FGG40uhC8Mm633uKW1r58aElFlBlxCrg9JfSi3P6aYiWmfiWF0PgMd86ZUsxE5GwWPdHoS2+48bwTh2VPkIQA==" + }, + "node_modules/lodash.ismatch": { + "version": "4.4.0", + "integrity": "sha512-fPMfXjGQEV9Xsq/8MTSgUf255gawYRbjwMyDbcvDhXgV7enSZA0hynz6vMPnpAb5iONEzBHBPsT+0zes5Z301g==", + "dev": true + }, + "node_modules/lodash.isplainobject": { + "version": "4.0.6", + "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==" + }, + "node_modules/lodash.pick": { + "version": "4.4.0", + "integrity": "sha512-hXt6Ul/5yWjfklSGvLQl8vM//l3FtyHZeuelpzK6mm99pNvN9yTDruNZPEJZD1oWrqo+izBmB7oUfWgcCX7s4Q==", + "dev": true + }, + "node_modules/lodash.pickby": { + "version": "4.6.0", + "integrity": "sha512-AZV+GsS/6ckvPOVQPXSiFFacKvKB4kOQu6ynt9wz0F3LO4R9Ij4K1ddYsIytDpSgLz88JHd9P+oaLeej5/Sl7Q==", + "dev": true + }, + "node_modules/lodash.union": { + "version": "4.6.0", + "integrity": "sha512-c4pB2CdGrGdjMKYLA+XiRDO7Y0PRQbm/Gzg8qMj+QH+pFVAoTp5sBpO0odL3FjoPCGjK96p6qsP+yQoiLoOBcw==" + }, + "node_modules/log-symbols": { + "version": "1.0.2", + "integrity": "sha512-mmPrW0Fh2fxOzdBbFv4g1m6pR72haFLPJ2G5SJEELf1y+iaQrDG6cWCPjy54RHYbZAt7X+ls690Kw62AdWXBzQ==", + "dependencies": { + "chalk": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/log-symbols/node_modules/ansi-regex": { + "version": "2.1.1", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/log-symbols/node_modules/ansi-styles": { + "version": "2.2.1", + "integrity": "sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/log-symbols/node_modules/chalk": { + "version": "1.1.3", + "integrity": "sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A==", + "dependencies": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/log-symbols/node_modules/strip-ansi": { + "version": "3.0.1", + "integrity": "sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==", + "dependencies": { + "ansi-regex": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/log-symbols/node_modules/supports-color": { + "version": "2.0.0", + "integrity": "sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g==", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/log-update": { + "version": "2.3.0", + "integrity": "sha512-vlP11XfFGyeNQlmEn9tJ66rEW1coA/79m5z6BCkudjbAGE83uhAcGYrBFwfs3AdLiLzGRusRPAbSPK9xZteCmg==", + "dependencies": { + "ansi-escapes": "^3.0.0", + "cli-cursor": "^2.0.0", + "wrap-ansi": "^3.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/log-update/node_modules/ansi-escapes": { + "version": "3.2.0", + "integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==", + "engines": { + "node": ">=4" + } + }, + "node_modules/log-update/node_modules/ansi-regex": { + "version": "3.0.1", + "integrity": "sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw==", + "engines": { + "node": ">=4" + } + }, + "node_modules/log-update/node_modules/cli-cursor": { + "version": "2.1.0", + "integrity": "sha512-8lgKz8LmCRYZZQDpRyT2m5rKJ08TnU4tR9FFFW2rxpxR1FzWi4PQ/NfyODchAatHaUgnSPVcx/R5w6NuTBzFiw==", + "dependencies": { + "restore-cursor": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/log-update/node_modules/is-fullwidth-code-point": { + "version": "2.0.0", + "integrity": "sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==", + "engines": { + "node": ">=4" + } + }, + "node_modules/log-update/node_modules/mimic-fn": { + "version": "1.2.0", + "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", + "engines": { + "node": ">=4" + } + }, + "node_modules/log-update/node_modules/onetime": { + "version": "2.0.1", + "integrity": "sha512-oyyPpiMaKARvvcgip+JV+7zci5L8D1W9RZIz2l1o08AM3pfspitVWnPt3mzHcBPp12oYMTy0pqrFs/C+m3EwsQ==", + "dependencies": { + "mimic-fn": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/log-update/node_modules/restore-cursor": { + "version": "2.0.0", + "integrity": "sha512-6IzJLuGi4+R14vwagDHX+JrXmPVtPpn4mffDJ1UdR7/Edm87fl6yi8mMBIVvFtJaNTUvjughmW4hwLhRG7gC1Q==", + "dependencies": { + "onetime": "^2.0.0", + "signal-exit": "^3.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/log-update/node_modules/string-width": { + "version": "2.1.1", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dependencies": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/log-update/node_modules/strip-ansi": { + "version": "4.0.0", + "integrity": "sha512-4XaJ2zQdCzROZDivEVIDPkcQn8LMFSa8kj8Gxb/Lnwzv9A8VctNZ+lfivC/sV3ivW8ElJTERXZoPBRrZKkNKow==", + "dependencies": { + "ansi-regex": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/log-update/node_modules/wrap-ansi": { + "version": "3.0.1", + "integrity": "sha512-iXR3tDXpbnTpzjKSylUJRkLuOrEC7hwEB221cgn6wtF8wpmz28puFXAEfPT5zrjM3wahygB//VuWEr1vTkDcNQ==", + "dependencies": { + "string-width": "^2.1.1", + "strip-ansi": "^4.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/loupe": { + "version": "2.3.6", + "integrity": "sha512-RaPMZKiMy8/JruncMU5Bt6na1eftNoo++R4Y+N2FrxkDVTrGvcyzFTsaGif4QTeKESheMGegbhw6iUAq+5A8zA==", + "dev": true, + "dependencies": { + "get-func-name": "^2.0.0" + } + }, + "node_modules/lowercase-keys": { + "version": "1.0.1", + "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/lru-cache": { + "version": "5.1.1", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/make-dir": { + "version": "3.1.0", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "dev": true, + "dependencies": { + "semver": "^6.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/make-dir/node_modules/semver": { + "version": "6.3.0", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/make-error": { + "version": "1.3.6", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", + "dev": true + }, + "node_modules/make-fetch-happen": { + "version": "10.2.1", + "integrity": "sha512-NgOPbRiaQM10DYXvN3/hhGVI2M5MtITFryzBGxHM5p4wnFxsVCbxkrBrDsk+EZ5OB4jEOT7AjDxtdF+KVEFT7w==", + "dev": true, + "dependencies": { + "agentkeepalive": "^4.2.1", + "cacache": "^16.1.0", + "http-cache-semantics": "^4.1.0", + "http-proxy-agent": "^5.0.0", + "https-proxy-agent": "^5.0.0", + "is-lambda": "^1.0.1", + "lru-cache": "^7.7.1", + "minipass": "^3.1.6", + "minipass-collect": "^1.0.2", + "minipass-fetch": "^2.0.3", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "negotiator": "^0.6.3", + "promise-retry": "^2.0.1", + "socks-proxy-agent": "^7.0.0", + "ssri": "^9.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/make-fetch-happen/node_modules/lru-cache": { + "version": "7.14.1", + "integrity": "sha512-ysxwsnTKdAx96aTRdhDOCQfDgbHnt8SK0KY8SEjO0wHinhWOFTESbjVCMPbU1uGXg/ch4lifqx0wfjOawU2+WA==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/makeerror": { + "version": "1.0.12", + "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", + "dev": true, + "dependencies": { + "tmpl": "1.0.5" + } + }, + "node_modules/map-obj": { + "version": "4.3.0", + "integrity": "sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/media-typer": { + "version": "0.3.0", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/meow": { + "version": "8.1.2", + "integrity": "sha512-r85E3NdZ+mpYk1C6RjPFEMSE+s1iZMuHtsHAqY0DT3jZczl0diWUZ8g6oU7h0M9cD2EL+PzaYghhCLzR0ZNn5Q==", + "dev": true, + "dependencies": { + "@types/minimist": "^1.2.0", + "camelcase-keys": "^6.2.2", + "decamelize-keys": "^1.1.0", + "hard-rejection": "^2.1.0", + "minimist-options": "4.1.0", + "normalize-package-data": "^3.0.0", + "read-pkg-up": "^7.0.1", + "redent": "^3.0.0", + "trim-newlines": "^3.0.0", + "type-fest": "^0.18.0", + "yargs-parser": "^20.2.3" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/meow/node_modules/type-fest": { + "version": "0.18.1", + "integrity": "sha512-OIAYXk8+ISY+qTOwkHtKqzAuxchoMiD9Udx+FSGQDuiRR+PJKJHc2NJAXlbhkGwTt/4/nKZxELY1w3ReWOL8mw==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/merge-descriptors": { + "version": "1.0.1", + "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==", + "dev": true + }, + "node_modules/merge-stream": { + "version": "2.0.0", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==" + }, + "node_modules/merge2": { + "version": "1.4.1", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/micri": { + "version": "4.5.1", + "integrity": "sha512-AtvnSBGFglNr+iqs5gufpHT9xRXUabgu9vYEnQYPXSBs+nLSBvmUS5Mzg+3LJ9eQBrNA1o5M49WeqiX1f+d2sg==", + "dev": true, + "dependencies": { + "handler-agent": "0.2.0" + }, + "engines": { + "node": ">= 12.0.0" + } + }, + "node_modules/micromatch": { + "version": "4.0.5", + "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "dependencies": { + "braces": "^3.0.2", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-format": { + "version": "2.0.1", + "integrity": "sha512-XxU3ngPbEnrYnNbIX+lYSaYg0M01v6p2ntd2YaFksTu0vayaw5OJvbdRyWs07EYRlLED5qadUZ+xo+XhOvFhwg==", + "dev": true, + "dependencies": { + "charset": "^1.0.0" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mimic-fn": { + "version": "2.1.0", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "engines": { + "node": ">=6" + } + }, + "node_modules/mimic-response": { + "version": "1.0.1", + "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/min-indent": { + "version": "1.0.1", + "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/minimatch": { + "version": "3.1.2", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.6", + "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==", + "devOptional": true + }, + "node_modules/minimist-options": { + "version": "4.1.0", + "integrity": "sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==", + "dev": true, + "dependencies": { + "arrify": "^1.0.1", + "is-plain-obj": "^1.1.0", + "kind-of": "^6.0.3" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/minipass": { + "version": "3.3.6", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-collect": { + "version": "1.0.2", + "integrity": "sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==", + "dev": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minipass-fetch": { + "version": "2.1.2", + "integrity": "sha512-LT49Zi2/WMROHYoqGgdlQIZh8mLPZmOrN2NdJjMXxYe4nkN6FUyuPuOAOedNJDrx0IRGg9+4guZewtp8hE6TxA==", + "dev": true, + "dependencies": { + "minipass": "^3.1.6", + "minipass-sized": "^1.0.3", + "minizlib": "^2.1.2" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + }, + "optionalDependencies": { + "encoding": "^0.1.13" + } + }, + "node_modules/minipass-flush": { + "version": "1.0.5", + "integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==", + "dev": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minipass-json-stream": { + "version": "1.0.1", + "integrity": "sha512-ODqY18UZt/I8k+b7rl2AENgbWE8IDYam+undIJONvigAz8KR5GWblsFTEfQs0WODsjbSXWlm+JHEv8Gr6Tfdbg==", + "dev": true, + "dependencies": { + "jsonparse": "^1.3.1", + "minipass": "^3.0.0" + } + }, + "node_modules/minipass-pipeline": { + "version": "1.2.4", + "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==", + "dev": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-sized": { + "version": "1.0.3", + "integrity": "sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==", + "dev": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass/node_modules/yallist": { + "version": "4.0.0", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/minizlib": { + "version": "2.1.2", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "dev": true, + "dependencies": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minizlib/node_modules/yallist": { + "version": "4.0.0", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/mkdirp": { + "version": "0.5.6", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "devOptional": true, + "dependencies": { + "minimist": "^1.2.6" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "node_modules/mocha": { + "version": "9.2.2", + "integrity": "sha512-L6XC3EdwT6YrIk0yXpavvLkn8h+EU+Y5UcCHKECyMbdUIxyMuZj4bX4U9e1nvnvUUvQVsV2VHQr5zLdcUkhW/g==", + "dev": true, + "dependencies": { + "@ungap/promise-all-settled": "1.1.2", + "ansi-colors": "4.1.1", + "browser-stdout": "1.3.1", + "chokidar": "3.5.3", + "debug": "4.3.3", + "diff": "5.0.0", + "escape-string-regexp": "4.0.0", + "find-up": "5.0.0", + "glob": "7.2.0", + "growl": "1.10.5", + "he": "1.2.0", + "js-yaml": "4.1.0", + "log-symbols": "4.1.0", + "minimatch": "4.2.1", + "ms": "2.1.3", + "nanoid": "3.3.1", + "serialize-javascript": "6.0.0", + "strip-json-comments": "3.1.1", + "supports-color": "8.1.1", + "which": "2.0.2", + "workerpool": "6.2.0", + "yargs": "16.2.0", + "yargs-parser": "20.2.4", + "yargs-unparser": "2.0.0" + }, + "bin": { + "_mocha": "bin/_mocha", + "mocha": "bin/mocha" + }, + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mochajs" + } + }, + "node_modules/mocha-chai-jest-snapshot": { + "version": "1.1.4", + "integrity": "sha512-ybwtS10P8BXDJQn9B3QyQA8Lxr/CcYxtuyWKk1PxD9vJorH8VL3edB7re4GcG9dRAdDPE/B0BsfwmCo6W43O7w==", + "dev": true, + "dependencies": { + "@jest/test-result": "^28.1.1", + "chalk": "^4.1.2", + "find-package-json": "^1.2.0", + "jest-snapshot": "^28.1.1", + "jest-util": "^28.1.1", + "slash": "^3.0.0", + "yargs": "^17.5.1" + }, + "peerDependencies": { + "chai": "^4.3.6" + } + }, + "node_modules/mocha-chai-jest-snapshot/node_modules/chalk": { + "version": "4.1.2", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/mocha.parallel": { + "version": "0.15.6", + "integrity": "sha512-pWph+QieKGjk7cHY2hB78wyKJDOQLyOMDuBLQLrFL7riJb8qbQBlCY3XztFHv0D1d4I1gCpiwFNjd4LhVOXPew==", + "dev": true, + "dependencies": { + "bluebird": "^2.9.34", + "semaphore": "^1.0.5" + }, + "peerDependencies": { + "mocha": ">=2.2.5" + } + }, + "node_modules/mocha.parallel/node_modules/bluebird": { + "version": "2.11.0", + "integrity": "sha512-UfFSr22dmHPQqPP9XWHRhq+gWnHCYguQGkXQlbyPtW5qTnhFWA8/iXg765tH0cAjy7l/zPJ1aBTO0g5XgA7kvQ==", + "dev": true + }, + "node_modules/mocha/node_modules/chalk": { + "version": "4.1.2", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/mocha/node_modules/chalk/node_modules/supports-color": { + "version": "7.2.0", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/mocha/node_modules/cliui": { + "version": "7.0.4", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "dev": true, + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "node_modules/mocha/node_modules/debug": { + "version": "4.3.3", + "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/mocha/node_modules/debug/node_modules/ms": { + "version": "2.1.2", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/mocha/node_modules/escape-string-regexp": { + "version": "4.0.0", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/mocha/node_modules/glob": { + "version": "7.2.0", + "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/mocha/node_modules/glob/node_modules/minimatch": { + "version": "3.1.2", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/mocha/node_modules/log-symbols": { + "version": "4.1.0", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", + "dev": true, + "dependencies": { + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/mocha/node_modules/minimatch": { + "version": "4.2.1", + "integrity": "sha512-9Uq1ChtSZO+Mxa/CL1eGizn2vRn3MlLgzhT0Iz8zaY8NdvxvB0d5QdPFmCKf7JKA9Lerx5vRrnwO03jsSfGG9g==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/mocha/node_modules/ms": { + "version": "2.1.3", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + }, + "node_modules/mocha/node_modules/supports-color": { + "version": "8.1.1", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/mocha/node_modules/yargs": { + "version": "16.2.0", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "dev": true, + "dependencies": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/mocha/node_modules/yargs-parser": { + "version": "20.2.4", + "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/modify-values": { + "version": "1.0.1", + "integrity": "sha512-xV2bxeN6F7oYjZWTe/YPAy6MN2M+sL4u/Rlm2AHCIVGfo2p1yGmBHQ6vHehl4bRTZBdHu3TSkWdYgkwpYzAGSw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/module-not-found-error": { + "version": "1.0.1", + "integrity": "sha512-pEk4ECWQXV6z2zjhRZUongnLJNUeGQJ3w6OQ5ctGwD+i5o93qjRQUk2Rt6VdNeu3sEP0AB4LcfvdebpxBRVr4g==", + "dev": true + }, + "node_modules/moment": { + "version": "2.29.4", + "integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==", + "optional": true, + "engines": { + "node": "*" + } + }, + "node_modules/ms": { + "version": "2.1.2", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/mustache": { + "version": "4.2.0", + "integrity": "sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ==", + "bin": { + "mustache": "bin/mustache" + } + }, + "node_modules/mute-stream": { + "version": "0.0.8", + "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==" + }, + "node_modules/mv": { + "version": "2.1.1", + "integrity": "sha512-at/ZndSy3xEGJ8i0ygALh8ru9qy7gWW1cmkaqBN29JmMlIvM//MEO9y1sk/avxuwnPcfhkejkLsuPxH81BrkSg==", + "optional": true, + "dependencies": { + "mkdirp": "~0.5.1", + "ncp": "~2.0.0", + "rimraf": "~2.4.0" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/mv/node_modules/glob": { + "version": "6.0.4", + "integrity": "sha512-MKZeRNyYZAVVVG1oZeLaWie1uweH40m9AZwIwxyPbTSX4hHrVYSzLg0Ro5Z5R7XKkIX+Cc6oD1rqeDJnwsB8/A==", + "optional": true, + "dependencies": { + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "2 || 3", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + } + }, + "node_modules/mv/node_modules/rimraf": { + "version": "2.4.5", + "integrity": "sha512-J5xnxTyqaiw06JjMftq7L9ouA448dw/E7dKghkP9WpKNuwmARNNg+Gk8/u5ryb9N/Yo2+z3MCwuqFK/+qPOPfQ==", + "optional": true, + "dependencies": { + "glob": "^6.0.1" + }, + "bin": { + "rimraf": "bin.js" + } + }, + "node_modules/nan": { + "version": "2.17.0", + "integrity": "sha512-2ZTgtl0nJsO0KQCjEpxcIr5D+Yv90plTitZt9JBfQvVJDS5seMl3FOvsh3+9CoYWXf/1l5OaZzzF6nDm4cagaQ==", + "optional": true + }, + "node_modules/nanoid": { + "version": "3.3.1", + "integrity": "sha512-n6Vs/3KGyxPQd6uO0eH4Bv0ojGSUvuLlIHtC3Y0kEO23YRge8H9x1GCzLn28YX0H66pMkxuaeESFq4tKISKwdw==", + "dev": true, + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true + }, + "node_modules/ncp": { + "version": "2.0.0", + "integrity": "sha512-zIdGUrPRFTUELUvr3Gmc7KZ2Sw/h1PiVM0Af/oHB6zgnV1ikqSfRk+TOufi79aHYCW3NiOXmr1BP5nWbzojLaA==", + "devOptional": true, + "bin": { + "ncp": "bin/ncp" + } + }, + "node_modules/negotiator": { + "version": "0.6.3", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/neo-async": { + "version": "2.6.2", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", + "dev": true + }, + "node_modules/nise": { + "version": "5.1.4", + "integrity": "sha512-8+Ib8rRJ4L0o3kfmyVCL7gzrohyDe0cMFTBa2d364yIrEGMEoetznKJx899YxjybU6bL9SQkYPSBBs1gyYs8Xg==", + "dev": true, + "dependencies": { + "@sinonjs/commons": "^2.0.0", + "@sinonjs/fake-timers": "^10.0.2", + "@sinonjs/text-encoding": "^0.7.1", + "just-extend": "^4.0.2", + "path-to-regexp": "^1.7.0" + } + }, + "node_modules/nise/node_modules/@sinonjs/commons": { + "version": "2.0.0", + "integrity": "sha512-uLa0j859mMrg2slwQYdO/AkrOfmH+X6LTVmNTS9CqexuE2IvVORIkSpJLqePAbEnKJ77aMmCwr1NUZ57120Xcg==", + "dev": true, + "dependencies": { + "type-detect": "4.0.8" + } + }, + "node_modules/nise/node_modules/@sinonjs/fake-timers": { + "version": "10.0.2", + "integrity": "sha512-SwUDyjWnah1AaNl7kxsa7cfLhlTYoiyhDAIgyh+El30YvXs/o7OLXpYH88Zdhyx9JExKrmHDJ+10bwIcY80Jmw==", + "dev": true, + "dependencies": { + "@sinonjs/commons": "^2.0.0" + } + }, + "node_modules/node-fetch": { + "version": "2.6.8", + "integrity": "sha512-RZ6dBYuj8dRSfxpUSu+NsdF1dpPpluJxwOp+6IoDp/sH2QNDSvurYsAa+F1WxY2RjA1iP93xhcsUoYbF2XBqVg==", + "dev": true, + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/node-gyp": { + "version": "9.3.1", + "integrity": "sha512-4Q16ZCqq3g8awk6UplT7AuxQ35XN4R/yf/+wSAwcBUAjg7l58RTactWaP8fIDTi0FzI7YcVLujwExakZlfWkXg==", + "dev": true, + "dependencies": { + "env-paths": "^2.2.0", + "glob": "^7.1.4", + "graceful-fs": "^4.2.6", + "make-fetch-happen": "^10.0.3", + "nopt": "^6.0.0", + "npmlog": "^6.0.0", + "rimraf": "^3.0.2", + "semver": "^7.3.5", + "tar": "^6.1.2", + "which": "^2.0.2" + }, + "bin": { + "node-gyp": "bin/node-gyp.js" + }, + "engines": { + "node": "^12.13 || ^14.13 || >=16" + } + }, + "node_modules/node-int64": { + "version": "0.4.0", + "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==", + "dev": true + }, + "node_modules/node-preload": { + "version": "0.2.1", + "integrity": "sha512-RM5oyBy45cLEoHqCeh+MNuFAxO0vTFBLskvQbOKnEE7YTTSN4tbN8QWDIPQ6L+WvKsB/qLEGpYe2ZZ9d4W9OIQ==", + "dev": true, + "dependencies": { + "process-on-spawn": "^1.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/node-releases": { + "version": "2.0.8", + "integrity": "sha512-dFSmB8fFHEH/s81Xi+Y/15DQY6VHW81nXRj86EMSL3lmuTmK1e+aT4wrFCkTbm+gSwkw4KpX+rT/pMM2c1mF+A==", + "dev": true + }, + "node_modules/nodemon": { + "version": "2.0.20", + "integrity": "sha512-Km2mWHKKY5GzRg6i1j5OxOHQtuvVsgskLfigG25yTtbyfRGn/GNvIbRyOf1PSCKJ2aT/58TiuUsuOU5UToVViw==", + "dependencies": { + "chokidar": "^3.5.2", + "debug": "^3.2.7", + "ignore-by-default": "^1.0.1", + "minimatch": "^3.1.2", + "pstree.remy": "^1.1.8", + "semver": "^5.7.1", + "simple-update-notifier": "^1.0.7", + "supports-color": "^5.5.0", + "touch": "^3.1.0", + "undefsafe": "^2.0.5" + }, + "bin": { + "nodemon": "bin/nodemon.js" + }, + "engines": { + "node": ">=8.10.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/nodemon" + } + }, + "node_modules/nodemon/node_modules/debug": { + "version": "3.2.7", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/nodemon/node_modules/has-flag": { + "version": "3.0.0", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "engines": { + "node": ">=4" + } + }, + "node_modules/nodemon/node_modules/semver": { + "version": "5.7.1", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/nodemon/node_modules/supports-color": { + "version": "5.5.0", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/noms": { + "version": "0.0.0", + "integrity": "sha512-lNDU9VJaOPxUmXcLb+HQFeUgQQPtMI24Gt6hgfuMHRJgMRHMF/qZ4HJD3GDru4sSw9IQl2jPjAYnQrdIeLbwow==", + "dev": true, + "dependencies": { + "inherits": "^2.0.1", + "readable-stream": "~1.0.31" + } + }, + "node_modules/noms/node_modules/isarray": { + "version": "0.0.1", + "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==", + "dev": true + }, + "node_modules/noms/node_modules/readable-stream": { + "version": "1.0.34", + "integrity": "sha512-ok1qVCJuRkNmvebYikljxJA/UEsKwLl2nI1OmaqAu4/UE+h0wKCHok4XkL/gvi39OacXvw59RJUOFUkDib2rHg==", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "node_modules/noms/node_modules/string_decoder": { + "version": "0.10.31", + "integrity": "sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ==", + "dev": true + }, + "node_modules/nopt": { + "version": "6.0.0", + "integrity": "sha512-ZwLpbTgdhuZUnZzjd7nb1ZV+4DoiC6/sfiVKok72ym/4Tlf+DFdlHYmT2JPmcNNWV6Pi3SDf1kT+A4r9RTuT9g==", + "dev": true, + "dependencies": { + "abbrev": "^1.0.0" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/normalize-package-data": { + "version": "3.0.3", + "integrity": "sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==", + "dev": true, + "dependencies": { + "hosted-git-info": "^4.0.1", + "is-core-module": "^2.5.0", + "semver": "^7.3.4", + "validate-npm-package-license": "^3.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/normalize-url": { + "version": "4.5.1", + "integrity": "sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/npm-bundle": { + "version": "3.0.3", + "integrity": "sha512-fHF7FR32YNgjqi0MQMLnE78Ff9/wYd4/7/Cke3dLLi2QzETKotIiWGCxwDoXAZDWVoTuVRYQa2ZdiZPuBL7QnA==", + "dev": true, + "dependencies": { + "glob": "^6.0.1", + "insync": "^2.1.1", + "mkdirp": "^0.5.1", + "ncp": "^2.0.0", + "rimraf": "^2.4.4" + }, + "bin": { + "npm-bundle": "bin/cli.js" + } + }, + "node_modules/npm-bundle/node_modules/glob": { + "version": "6.0.4", + "integrity": "sha512-MKZeRNyYZAVVVG1oZeLaWie1uweH40m9AZwIwxyPbTSX4hHrVYSzLg0Ro5Z5R7XKkIX+Cc6oD1rqeDJnwsB8/A==", + "dev": true, + "dependencies": { + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "2 || 3", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + } + }, + "node_modules/npm-bundle/node_modules/rimraf": { + "version": "2.7.1", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + } + }, + "node_modules/npm-bundle/node_modules/rimraf/node_modules/glob": { + "version": "7.2.3", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/npm-bundled": { + "version": "1.1.2", + "integrity": "sha512-x5DHup0SuyQcmL3s7Rx/YQ8sbw/Hzg0rj48eN0dV7hf5cmQq5PXIeioroH3raV1QC1yh3uTYuMThvEQF3iKgGQ==", + "dev": true, + "dependencies": { + "npm-normalize-package-bin": "^1.0.1" + } + }, + "node_modules/npm-check-updates": { + "version": "12.5.12", + "integrity": "sha512-JAFs+kKokZmYPRzhSHgIpKashX6vSGGXYo0VJXNaKV/nLnq3ZKI0nTVou9OwTix+PFfLAWTEJ6T/byGxkDlhWA==", + "dev": true, + "dependencies": { + "chalk": "^4.1.2", + "cint": "^8.2.1", + "cli-table": "^0.3.11", + "commander": "^9.1.0", + "fast-memoize": "^2.5.2", + "find-up": "5.0.0", + "fp-and-or": "^0.1.3", + "get-stdin": "^8.0.0", + "globby": "^11.0.4", + "hosted-git-info": "^5.0.0", + "json-parse-helpfulerror": "^1.0.3", + "jsonlines": "^0.1.1", + "libnpmconfig": "^1.2.1", + "lodash": "^4.17.21", + "minimatch": "^5.0.1", + "p-map": "^4.0.0", + "pacote": "^13.0.5", + "parse-github-url": "^1.0.2", + "progress": "^2.0.3", + "prompts": "^2.4.2", + "rc-config-loader": "^4.1.0", + "remote-git-tags": "^3.0.0", + "rimraf": "^3.0.2", + "semver": "^7.3.5", + "semver-utils": "^1.1.4", + "source-map-support": "^0.5.21", + "spawn-please": "^1.0.0", + "update-notifier": "^5.1.0", + "yaml": "^1.10.2" + }, + "bin": { + "ncu": "build/src/bin/cli.js", + "npm-check-updates": "build/src/bin/cli.js" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/npm-check-updates/node_modules/brace-expansion": { + "version": "2.0.1", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/npm-check-updates/node_modules/chalk": { + "version": "4.1.2", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/npm-check-updates/node_modules/commander": { + "version": "9.5.0", + "integrity": "sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==", + "dev": true, + "engines": { + "node": "^12.20.0 || >=14" + } + }, + "node_modules/npm-check-updates/node_modules/hosted-git-info": { + "version": "5.2.1", + "integrity": "sha512-xIcQYMnhcx2Nr4JTjsFmwwnr9vldugPy9uVm0o87bjqqWMv9GaqsTeT+i99wTl0mk1uLxJtHxLb8kymqTENQsw==", + "dev": true, + "dependencies": { + "lru-cache": "^7.5.1" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/npm-check-updates/node_modules/lru-cache": { + "version": "7.14.1", + "integrity": "sha512-ysxwsnTKdAx96aTRdhDOCQfDgbHnt8SK0KY8SEjO0wHinhWOFTESbjVCMPbU1uGXg/ch4lifqx0wfjOawU2+WA==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/npm-check-updates/node_modules/minimatch": { + "version": "5.1.6", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/npm-check-updates/node_modules/p-map": { + "version": "4.0.0", + "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", + "dev": true, + "dependencies": { + "aggregate-error": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/npm-install-checks": { + "version": "5.0.0", + "integrity": "sha512-65lUsMI8ztHCxFz5ckCEC44DRvEGdZX5usQFriauxHEwt7upv1FKaQEmAtU0YnOAdwuNWCmk64xYiQABNrEyLA==", + "dev": true, + "dependencies": { + "semver": "^7.1.1" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/npm-normalize-package-bin": { + "version": "1.0.1", + "integrity": "sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA==", + "dev": true + }, + "node_modules/npm-package-arg": { + "version": "9.1.2", + "integrity": "sha512-pzd9rLEx4TfNJkovvlBSLGhq31gGu2QDexFPWT19yCDh0JgnRhlBLNo5759N0AJmBk+kQ9Y/hXoLnlgFD+ukmg==", + "dev": true, + "dependencies": { + "hosted-git-info": "^5.0.0", + "proc-log": "^2.0.1", + "semver": "^7.3.5", + "validate-npm-package-name": "^4.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/npm-package-arg/node_modules/hosted-git-info": { + "version": "5.2.1", + "integrity": "sha512-xIcQYMnhcx2Nr4JTjsFmwwnr9vldugPy9uVm0o87bjqqWMv9GaqsTeT+i99wTl0mk1uLxJtHxLb8kymqTENQsw==", + "dev": true, + "dependencies": { + "lru-cache": "^7.5.1" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/npm-package-arg/node_modules/lru-cache": { + "version": "7.14.1", + "integrity": "sha512-ysxwsnTKdAx96aTRdhDOCQfDgbHnt8SK0KY8SEjO0wHinhWOFTESbjVCMPbU1uGXg/ch4lifqx0wfjOawU2+WA==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/npm-packlist": { + "version": "5.1.3", + "integrity": "sha512-263/0NGrn32YFYi4J533qzrQ/krmmrWwhKkzwTuM4f/07ug51odoaNjUexxO4vxlzURHcmYMH1QjvHjsNDKLVg==", + "dev": true, + "dependencies": { + "glob": "^8.0.1", + "ignore-walk": "^5.0.1", + "npm-bundled": "^2.0.0", + "npm-normalize-package-bin": "^2.0.0" + }, + "bin": { + "npm-packlist": "bin/index.js" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/npm-packlist/node_modules/brace-expansion": { + "version": "2.0.1", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/npm-packlist/node_modules/glob": { + "version": "8.1.0", + "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^5.0.1", + "once": "^1.3.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/npm-packlist/node_modules/minimatch": { + "version": "5.1.6", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/npm-packlist/node_modules/npm-bundled": { + "version": "2.0.1", + "integrity": "sha512-gZLxXdjEzE/+mOstGDqR6b0EkhJ+kM6fxM6vUuckuctuVPh80Q6pw/rSZj9s4Gex9GxWtIicO1pc8DB9KZWudw==", + "dev": true, + "dependencies": { + "npm-normalize-package-bin": "^2.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/npm-packlist/node_modules/npm-normalize-package-bin": { + "version": "2.0.0", + "integrity": "sha512-awzfKUO7v0FscrSpRoogyNm0sajikhBWpU0QMrW09AMi9n1PoKU6WaIqUzuJSQnpciZZmJ/jMZ2Egfmb/9LiWQ==", + "dev": true, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/npm-pick-manifest": { + "version": "7.0.2", + "integrity": "sha512-gk37SyRmlIjvTfcYl6RzDbSmS9Y4TOBXfsPnoYqTHARNgWbyDiCSMLUpmALDj4jjcTZpURiEfsSHJj9k7EV4Rw==", + "dev": true, + "dependencies": { + "npm-install-checks": "^5.0.0", + "npm-normalize-package-bin": "^2.0.0", + "npm-package-arg": "^9.0.0", + "semver": "^7.3.5" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/npm-pick-manifest/node_modules/npm-normalize-package-bin": { + "version": "2.0.0", + "integrity": "sha512-awzfKUO7v0FscrSpRoogyNm0sajikhBWpU0QMrW09AMi9n1PoKU6WaIqUzuJSQnpciZZmJ/jMZ2Egfmb/9LiWQ==", + "dev": true, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/npm-registry-fetch": { + "version": "13.3.1", + "integrity": "sha512-eukJPi++DKRTjSBRcDZSDDsGqRK3ehbxfFUcgaRd0Yp6kRwOwh2WVn0r+8rMB4nnuzvAk6rQVzl6K5CkYOmnvw==", + "dev": true, + "dependencies": { + "make-fetch-happen": "^10.0.6", + "minipass": "^3.1.6", + "minipass-fetch": "^2.0.3", + "minipass-json-stream": "^1.0.1", + "minizlib": "^2.1.2", + "npm-package-arg": "^9.0.1", + "proc-log": "^2.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/npm-run-path": { + "version": "4.0.1", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dependencies": { + "path-key": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/npmlog": { + "version": "6.0.2", + "integrity": "sha512-/vBvz5Jfr9dT/aFWd0FIRf+T/Q2WBsLENygUaFUqstqsycmZAP/t5BvFJTK0viFmSUxiUKTUplWy5vt+rvKIxg==", + "dev": true, + "dependencies": { + "are-we-there-yet": "^3.0.0", + "console-control-strings": "^1.1.0", + "gauge": "^4.0.3", + "set-blocking": "^2.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/number-is-nan": { + "version": "1.0.1", + "integrity": "sha512-4jbtZXNAsfZbAHiiqjLPBiCl16dES1zI4Hpzzxw61Tk+loF+sBDBKx1ICKKKwIqQ7M0mFn1TmkN7euSncWgHiQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/nyc": { + "version": "15.1.0", + "integrity": "sha512-jMW04n9SxKdKi1ZMGhvUTHBN0EICCRkHemEoE5jm6mTYcqcdas0ATzgUgejlQUHMvpnOZqGB5Xxsv9KxJW1j8A==", + "dev": true, + "dependencies": { + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.2", + "caching-transform": "^4.0.0", + "convert-source-map": "^1.7.0", + "decamelize": "^1.2.0", + "find-cache-dir": "^3.2.0", + "find-up": "^4.1.0", + "foreground-child": "^2.0.0", + "get-package-type": "^0.1.0", + "glob": "^7.1.6", + "istanbul-lib-coverage": "^3.0.0", + "istanbul-lib-hook": "^3.0.0", + "istanbul-lib-instrument": "^4.0.0", + "istanbul-lib-processinfo": "^2.0.2", + "istanbul-lib-report": "^3.0.0", + "istanbul-lib-source-maps": "^4.0.0", + "istanbul-reports": "^3.0.2", + "make-dir": "^3.0.0", + "node-preload": "^0.2.1", + "p-map": "^3.0.0", + "process-on-spawn": "^1.0.0", + "resolve-from": "^5.0.0", + "rimraf": "^3.0.0", + "signal-exit": "^3.0.2", + "spawn-wrap": "^2.0.0", + "test-exclude": "^6.0.0", + "yargs": "^15.0.2" + }, + "bin": { + "nyc": "bin/nyc.js" + }, + "engines": { + "node": ">=8.9" + } + }, + "node_modules/nyc/node_modules/cliui": { + "version": "6.0.0", + "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", + "dev": true, + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^6.2.0" + } + }, + "node_modules/nyc/node_modules/find-up": { + "version": "4.1.0", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/nyc/node_modules/istanbul-lib-instrument": { + "version": "4.0.3", + "integrity": "sha512-BXgQl9kf4WTCPCCpmFGoJkz/+uhvm7h7PFKUYxh7qarQd3ER33vHG//qaE8eN25l07YqZPpHXU9I09l/RD5aGQ==", + "dev": true, + "dependencies": { + "@babel/core": "^7.7.5", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.0.0", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/nyc/node_modules/locate-path": { + "version": "5.0.0", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/nyc/node_modules/p-limit": { + "version": "2.3.0", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/nyc/node_modules/p-locate": { + "version": "4.1.0", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/nyc/node_modules/p-map": { + "version": "3.0.0", + "integrity": "sha512-d3qXVTF/s+W+CdJ5A29wywV2n8CQQYahlgz2bFiA+4eVNJbHJodPZ+/gXwPGh0bOqA+j8S+6+ckmvLGPk1QpxQ==", + "dev": true, + "dependencies": { + "aggregate-error": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/nyc/node_modules/semver": { + "version": "6.3.0", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/nyc/node_modules/wrap-ansi": { + "version": "6.2.0", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/nyc/node_modules/y18n": { + "version": "4.0.3", + "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", + "dev": true + }, + "node_modules/nyc/node_modules/yargs": { + "version": "15.4.1", + "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", + "dev": true, + "dependencies": { + "cliui": "^6.0.0", + "decamelize": "^1.2.0", + "find-up": "^4.1.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^4.2.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^18.1.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/nyc/node_modules/yargs-parser": { + "version": "18.1.3", + "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", + "dev": true, + "dependencies": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/oauth-sign": { + "version": "0.9.0", + "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", + "engines": { + "node": "*" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-inspect": { + "version": "1.12.3", + "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/once": { + "version": "1.4.0", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/onetime": { + "version": "5.1.2", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ono": { + "version": "4.0.11", + "integrity": "sha512-jQ31cORBFE6td25deYeD80wxKBMj+zBmHTrVxnc6CKhx8gho6ipmWM5zj/oeoqioZ99yqBls9Z/9Nss7J26G2g==", + "dev": true, + "dependencies": { + "format-util": "^1.0.3" + } + }, + "node_modules/open": { + "version": "8.4.0", + "integrity": "sha512-XgFPPM+B28FtCCgSb9I+s9szOC1vZRSwgWsRUA5ylIxRTgKozqjOCrVOqGsYABPYK5qnfqClxZTFBa8PKt2v6Q==", + "dependencies": { + "define-lazy-prop": "^2.0.0", + "is-docker": "^2.1.1", + "is-wsl": "^2.2.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/openapi3-ts": { + "version": "2.0.2", + "integrity": "sha512-TxhYBMoqx9frXyOgnRHufjQfPXomTIHYKhSKJ6jHfj13kS8OEIhvmE8CTuQyKtjjWttAjX5DPxM1vmalEpo8Qw==", + "dev": true, + "dependencies": { + "yaml": "^1.10.2" + } + }, + "node_modules/ora": { + "version": "3.4.0", + "integrity": "sha512-eNwHudNbO1folBP3JsZ19v9azXWtQZjICdr3Q0TDPIaeBQ3mXLrh54wM+er0+hSp+dWKf+Z8KM58CYzEyIYxYg==", + "dependencies": { + "chalk": "^2.4.2", + "cli-cursor": "^2.1.0", + "cli-spinners": "^2.0.0", + "log-symbols": "^2.2.0", + "strip-ansi": "^5.2.0", + "wcwidth": "^1.0.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/ora/node_modules/ansi-regex": { + "version": "4.1.1", + "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==", + "engines": { + "node": ">=6" + } + }, + "node_modules/ora/node_modules/ansi-styles": { + "version": "3.2.1", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/ora/node_modules/chalk": { + "version": "2.4.2", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/ora/node_modules/cli-cursor": { + "version": "2.1.0", + "integrity": "sha512-8lgKz8LmCRYZZQDpRyT2m5rKJ08TnU4tR9FFFW2rxpxR1FzWi4PQ/NfyODchAatHaUgnSPVcx/R5w6NuTBzFiw==", + "dependencies": { + "restore-cursor": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/ora/node_modules/color-convert": { + "version": "1.9.3", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/ora/node_modules/color-name": { + "version": "1.1.3", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" + }, + "node_modules/ora/node_modules/has-flag": { + "version": "3.0.0", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "engines": { + "node": ">=4" + } + }, + "node_modules/ora/node_modules/log-symbols": { + "version": "2.2.0", + "integrity": "sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==", + "dependencies": { + "chalk": "^2.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/ora/node_modules/mimic-fn": { + "version": "1.2.0", + "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", + "engines": { + "node": ">=4" + } + }, + "node_modules/ora/node_modules/onetime": { + "version": "2.0.1", + "integrity": "sha512-oyyPpiMaKARvvcgip+JV+7zci5L8D1W9RZIz2l1o08AM3pfspitVWnPt3mzHcBPp12oYMTy0pqrFs/C+m3EwsQ==", + "dependencies": { + "mimic-fn": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/ora/node_modules/restore-cursor": { + "version": "2.0.0", + "integrity": "sha512-6IzJLuGi4+R14vwagDHX+JrXmPVtPpn4mffDJ1UdR7/Edm87fl6yi8mMBIVvFtJaNTUvjughmW4hwLhRG7gC1Q==", + "dependencies": { + "onetime": "^2.0.0", + "signal-exit": "^3.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/ora/node_modules/strip-ansi": { + "version": "5.2.0", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dependencies": { + "ansi-regex": "^4.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/ora/node_modules/supports-color": { + "version": "5.5.0", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/os-tmpdir": { + "version": "1.0.2", + "integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/p-cancelable": { + "version": "1.1.0", + "integrity": "sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-map": { + "version": "2.1.0", + "integrity": "sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==", + "engines": { + "node": ">=6" + } + }, + "node_modules/p-try": { + "version": "2.2.0", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/package-hash": { + "version": "4.0.0", + "integrity": "sha512-whdkPIooSu/bASggZ96BWVvZTRMOFxnyUG5PnTSGKoJE2gd5mbVNmR2Nj20QFzxYYgAXpoqC+AiXzl+UMRh7zQ==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.15", + "hasha": "^5.0.0", + "lodash.flattendeep": "^4.4.0", + "release-zalgo": "^1.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/package-json": { + "version": "6.5.0", + "integrity": "sha512-k3bdm2n25tkyxcjSKzB5x8kfVxlMdgsbPr0GkZcwHsLpba6cBjqCt1KlcChKEvxHIcTB1FVMuwoijZ26xex5MQ==", + "dev": true, + "dependencies": { + "got": "^9.6.0", + "registry-auth-token": "^4.0.0", + "registry-url": "^5.0.0", + "semver": "^6.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/package-json/node_modules/semver": { + "version": "6.3.0", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/pacote": { + "version": "13.6.2", + "integrity": "sha512-Gu8fU3GsvOPkak2CkbojR7vjs3k3P9cA6uazKTHdsdV0gpCEQq2opelnEv30KRQWgVzP5Vd/5umjcedma3MKtg==", + "dev": true, + "dependencies": { + "@npmcli/git": "^3.0.0", + "@npmcli/installed-package-contents": "^1.0.7", + "@npmcli/promise-spawn": "^3.0.0", + "@npmcli/run-script": "^4.1.0", + "cacache": "^16.0.0", + "chownr": "^2.0.0", + "fs-minipass": "^2.1.0", + "infer-owner": "^1.0.4", + "minipass": "^3.1.6", + "mkdirp": "^1.0.4", + "npm-package-arg": "^9.0.0", + "npm-packlist": "^5.1.0", + "npm-pick-manifest": "^7.0.0", + "npm-registry-fetch": "^13.0.1", + "proc-log": "^2.0.0", + "promise-retry": "^2.0.1", + "read-package-json": "^5.0.0", + "read-package-json-fast": "^2.0.3", + "rimraf": "^3.0.2", + "ssri": "^9.0.0", + "tar": "^6.1.11" + }, + "bin": { + "pacote": "lib/bin.js" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/pacote/node_modules/mkdirp": { + "version": "1.0.4", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true, + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/parent-module": { + "version": "1.0.1", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/parse-github-url": { + "version": "1.0.2", + "integrity": "sha512-kgBf6avCbO3Cn6+RnzRGLkUsv4ZVqv/VfAYkRsyBcgkshNvVBkRn1FEZcW0Jb+npXQWm2vHPnnOqFteZxRRGNw==", + "dev": true, + "bin": { + "parse-github-url": "cli.js" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/parse-json": { + "version": "5.2.0", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parse-prefer-header": { + "version": "1.0.0", + "integrity": "sha512-+WJ3ncCrKOExuxF06XyKWS8bLkLttnlm6YPMZIFIUXNd09Xy0N2JISudxCaY+luDm43yTnHMHVU3zte4G2gN4g==", + "dev": true, + "dependencies": { + "lodash.camelcase": "^4.3.0" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" + }, + "node_modules/path-to-regexp": { + "version": "1.8.0", + "integrity": "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==", + "dev": true, + "dependencies": { + "isarray": "0.0.1" + } + }, + "node_modules/path-to-regexp/node_modules/isarray": { + "version": "0.0.1", + "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==", + "dev": true + }, + "node_modules/path-type": { + "version": "4.0.0", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/pathval": { + "version": "1.1.1", + "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/performance-now": { + "version": "2.1.0", + "integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==" + }, + "node_modules/picocolors": { + "version": "1.0.0", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", + "dev": true + }, + "node_modules/picomatch": { + "version": "2.3.1", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pidtree": { + "version": "0.5.0", + "integrity": "sha512-9nxspIM7OpZuhBxPg73Zvyq7j1QMPMPsGKTqRc2XOaFQauDvoNz9fM1Wdkjmeo7l9GXOZiRs97sPkuayl39wjA==", + "bin": { + "pidtree": "bin/pidtree.js" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/pify": { + "version": "3.0.0", + "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/pino": { + "version": "6.14.0", + "integrity": "sha512-iuhEDel3Z3hF9Jfe44DPXR8l07bhjuFY3GMHIXbjnY9XcafbyDDwl2sN2vw2GjMPf5Nkoe+OFao7ffn9SXaKDg==", + "dev": true, + "dependencies": { + "fast-redact": "^3.0.0", + "fast-safe-stringify": "^2.0.8", + "flatstr": "^1.0.12", + "pino-std-serializers": "^3.1.0", + "process-warning": "^1.0.0", + "quick-format-unescaped": "^4.0.3", + "sonic-boom": "^1.0.2" + }, + "bin": { + "pino": "bin.js" + } + }, + "node_modules/pino-std-serializers": { + "version": "3.2.0", + "integrity": "sha512-EqX4pwDPrt3MuOAAUBMU0Tk5kR/YcCM5fNPEzgCO2zJ5HfX0vbiH9HbJglnyeQsN96Kznae6MWD47pZB5avTrg==", + "dev": true + }, + "node_modules/pirates": { + "version": "4.0.5", + "integrity": "sha512-8V9+HQPupnaXMA23c5hvl69zXvTwTzyAYasnkb0Tts4XvO4CliqONMOnvlq26rkhLC3nWDFBJf73LU1e1VZLaQ==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/pkg-conf": { + "version": "2.1.0", + "integrity": "sha512-C+VUP+8jis7EsQZIhDYmS5qlNtjv2yP4SNtjXK9AP1ZcTRlnSfuumaTnRfYZnYgUUYVIKqL0fRvmUGDV2fmp6g==", + "dev": true, + "dependencies": { + "find-up": "^2.0.0", + "load-json-file": "^4.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/pkg-conf/node_modules/find-up": { + "version": "2.1.0", + "integrity": "sha512-NWzkk0jSJtTt08+FBFMvXoeZnOJD+jTtsRmBYbAIzJdX6l7dLgR7CTubCM5/eDdPUBvLCeVasP1brfVR/9/EZQ==", + "dev": true, + "dependencies": { + "locate-path": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/pkg-conf/node_modules/locate-path": { + "version": "2.0.0", + "integrity": "sha512-NCI2kiDkyR7VeEKm27Kda/iQHyKJe1Bu0FlTbYp3CqJu+9IFe9bLyAjMxf5ZDDbEg+iMPzB5zYyUTSm8wVTKmA==", + "dev": true, + "dependencies": { + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/pkg-conf/node_modules/p-limit": { + "version": "1.3.0", + "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", + "dev": true, + "dependencies": { + "p-try": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/pkg-conf/node_modules/p-locate": { + "version": "2.0.0", + "integrity": "sha512-nQja7m7gSKuewoVRen45CtVfODR3crN3goVQ0DDZ9N3yHxgpkuBhZqsaiotSQRrADUrne346peY7kT3TSACykg==", + "dev": true, + "dependencies": { + "p-limit": "^1.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/pkg-conf/node_modules/p-try": { + "version": "1.0.0", + "integrity": "sha512-U1etNYuMJoIz3ZXSrrySFjsXQTWOx2/jdi86L+2pRvph/qMKL6sbcCYdH23fqsbm8TH2Gn0OybpT4eSFlCVHww==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/pkg-conf/node_modules/path-exists": { + "version": "3.0.0", + "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/pkg-dir": { + "version": "4.2.0", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "dev": true, + "dependencies": { + "find-up": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-dir/node_modules/find-up": { + "version": "4.1.0", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-dir/node_modules/locate-path": { + "version": "5.0.0", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-dir/node_modules/p-limit": { + "version": "2.3.0", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/pkg-dir/node_modules/p-locate": { + "version": "4.1.0", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/portscanner": { + "version": "2.2.0", + "integrity": "sha512-IFroCz/59Lqa2uBvzK3bKDbDDIEaAY8XJ1jFxcLWTqosrsc32//P4VuSB2vZXoHiHqOmx8B5L5hnKOxL/7FlPw==", + "dependencies": { + "async": "^2.6.0", + "is-number-like": "^1.0.3" + }, + "engines": { + "node": ">=0.4", + "npm": ">=1.0.0" + } + }, + "node_modules/postman-collection": { + "version": "4.1.3", + "integrity": "sha512-shoe2I/GGiigsdlU5+crS2frEJqQ6tgCck1+9aaPN9pQ3Kj7bt7NJdcqrn26ScciCfQymzSLG7TL9ZQZc6i05w==", + "dev": true, + "dependencies": { + "@faker-js/faker": "6.3.1", + "file-type": "3.9.0", + "http-reasons": "0.1.0", + "iconv-lite": "0.6.3", + "liquid-json": "0.3.1", + "lodash": "4.17.21", + "mime-format": "2.0.1", + "mime-types": "2.1.35", + "postman-url-encoder": "3.0.5", + "semver": "7.3.7", + "uuid": "8.3.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/postman-collection/node_modules/iconv-lite": { + "version": "0.6.3", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "dev": true, + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/postman-collection/node_modules/lru-cache": { + "version": "6.0.0", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/postman-collection/node_modules/semver": { + "version": "7.3.7", + "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/postman-collection/node_modules/yallist": { + "version": "4.0.0", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/postman-url-encoder": { + "version": "3.0.5", + "integrity": "sha512-jOrdVvzUXBC7C+9gkIkpDJ3HIxOHTIqjpQ4C1EMt1ZGeMvSEpbFCKq23DEfgsj46vMnDgyQf+1ZLp2Wm+bKSsA==", + "dev": true, + "dependencies": { + "punycode": "^2.1.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/prepend-http": { + "version": "2.0.0", + "integrity": "sha512-ravE6m9Atw9Z/jjttRUZ+clIXogdghyZAuWJ3qEzjT+jI/dL1ifAqhZeC5VHzQp1MSt1+jxKkFNemj/iO7tVUA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/prettier": { + "version": "2.8.3", + "integrity": "sha512-tJ/oJ4amDihPoufT5sM0Z1SKEuKay8LfVAMlbbhnnkvt6BUserZylqo2PN+p9KeljLr0OHa2rXHU1T8reeoTrw==", + "dev": true, + "bin": { + "prettier": "bin-prettier.js" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "node_modules/pretty-bytes": { + "version": "5.6.0", + "integrity": "sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg==", + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/pretty-data": { + "version": "0.40.0", + "integrity": "sha512-YFLnEdDEDnkt/GEhet5CYZHCvALw6+Elyb/tp8kQG03ZSIuzeaDWpZYndCXwgqu4NAjh1PI534dhDS1mHarRnQ==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/pretty-format": { + "version": "28.1.3", + "integrity": "sha512-8gFb/To0OmxHR9+ZTb14Df2vNxdGCX8g1xWGUTqUw5TiZvcQf5sHKObd5UcPyLLyowNwDAMTF3XWOG1B6mxl1Q==", + "dev": true, + "dependencies": { + "@jest/schemas": "^28.1.3", + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/pretty-format/node_modules/ansi-styles": { + "version": "5.2.0", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/proc-log": { + "version": "2.0.1", + "integrity": "sha512-Kcmo2FhfDTXdcbfDH76N7uBYHINxc/8GW7UAVuVP9I+Va3uHSerrnKV6dLooga/gh7GlgzuCCr/eoldnL1muGw==", + "dev": true, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, + "node_modules/process-on-spawn": { + "version": "1.0.0", + "integrity": "sha512-1WsPDsUSMmZH5LeMLegqkPDrsGgsWwk1Exipy2hvB0o/F0ASzbpIctSCcZIK1ykJvtTJULEH+20WOFjMvGnCTg==", + "dev": true, + "dependencies": { + "fromentries": "^1.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/process-warning": { + "version": "1.0.0", + "integrity": "sha512-du4wfLyj4yCZq1VupnVSZmRsPJsNuxoDQFdCFHLaYiEbFBD7QE0a+I4D7hOxrVnh78QE/YipFAj9lXHiXocV+Q==", + "dev": true + }, + "node_modules/progress": { + "version": "2.0.3", + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/promise-inflight": { + "version": "1.0.1", + "integrity": "sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==", + "dev": true + }, + "node_modules/promise-retry": { + "version": "2.0.1", + "integrity": "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==", + "dev": true, + "dependencies": { + "err-code": "^2.0.2", + "retry": "^0.12.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/prompts": { + "version": "2.4.2", + "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", + "dev": true, + "dependencies": { + "kleur": "^3.0.3", + "sisteransi": "^1.0.5" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/proxyquire": { + "version": "2.1.3", + "integrity": "sha512-BQWfCqYM+QINd+yawJz23tbBM40VIGXOdDw3X344KcclI/gtBbdWF6SlQ4nK/bYhF9d27KYug9WzljHC6B9Ysg==", + "dev": true, + "dependencies": { + "fill-keys": "^1.0.2", + "module-not-found-error": "^1.0.1", + "resolve": "^1.11.1" + } + }, + "node_modules/psl": { + "version": "1.9.0", + "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==" + }, + "node_modules/pstree.remy": { + "version": "1.1.8", + "integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==" + }, + "node_modules/pump": { + "version": "3.0.0", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dev": true, + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/punycode": { + "version": "2.3.0", + "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", + "engines": { + "node": ">=6" + } + }, + "node_modules/pupa": { + "version": "2.1.1", + "integrity": "sha512-l1jNAspIBSFqbT+y+5FosojNpVpF94nlI+wDUpqP9enwOTfHx9f0gh5nB96vl+6yTpsJsypeNrwfzPrKuHB41A==", + "dev": true, + "dependencies": { + "escape-goat": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/q": { + "version": "1.5.1", + "integrity": "sha512-kV/CThkXo6xyFEZUugw/+pIOywXcDbFYgSct5cT3gqlbkBE1SJdwy6UQoZvodiWF/ckQLZyDE/Bu1M6gVu5lVw==", + "dev": true, + "engines": { + "node": ">=0.6.0", + "teleport": ">=0.2.0" + } + }, + "node_modules/qs": { + "version": "6.5.3", + "integrity": "sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/querystring": { + "version": "0.2.0", + "integrity": "sha512-X/xY82scca2tau62i9mDyU9K+I+djTMUsvwf7xnUX5GLvVzgJybOJf4Y6o9Zx3oJK/LSXg5tTZBjwzqVPaPO2g==", + "deprecated": "The querystring API is considered Legacy. new code should use the URLSearchParams API instead.", + "engines": { + "node": ">=0.4.x" + } + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/quick-format-unescaped": { + "version": "4.0.4", + "integrity": "sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==", + "dev": true + }, + "node_modules/quick-lru": { + "version": "4.0.1", + "integrity": "sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/ramda": { + "version": "0.28.0", + "integrity": "sha512-9QnLuG/kPVgWvMQ4aODhsBUFKOUmnbUnsSXACv+NCQZcHbeb+v8Lodp8OVxtRULN1/xOyYLLaL6npE6dMq5QTA==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/ramda" + } + }, + "node_modules/randombytes": { + "version": "2.1.0", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, + "dependencies": { + "safe-buffer": "^5.1.0" + } + }, + "node_modules/rc": { + "version": "1.2.8", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "dev": true, + "dependencies": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "bin": { + "rc": "cli.js" + } + }, + "node_modules/rc-config-loader": { + "version": "4.1.2", + "integrity": "sha512-qKTnVWFl9OQYKATPzdfaZIbTxcHziQl92zYSxYC6umhOqyAsoj8H8Gq/+aFjAso68sBdjTz3A7omqeAkkF1MWg==", + "dev": true, + "dependencies": { + "debug": "^4.3.4", + "js-yaml": "^4.1.0", + "json5": "^2.2.2", + "require-from-string": "^2.0.2" + } + }, + "node_modules/rc/node_modules/strip-json-comments": { + "version": "2.0.1", + "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-is": { + "version": "18.2.0", + "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", + "dev": true + }, + "node_modules/read-package-json": { + "version": "5.0.2", + "integrity": "sha512-BSzugrt4kQ/Z0krro8zhTwV1Kd79ue25IhNN/VtHFy1mG/6Tluyi+msc0UpwaoQzxSHa28mntAjIZY6kEgfR9Q==", + "dev": true, + "dependencies": { + "glob": "^8.0.1", + "json-parse-even-better-errors": "^2.3.1", + "normalize-package-data": "^4.0.0", + "npm-normalize-package-bin": "^2.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/read-package-json-fast": { + "version": "2.0.3", + "integrity": "sha512-W/BKtbL+dUjTuRL2vziuYhp76s5HZ9qQhd/dKfWIZveD0O40453QNyZhC0e63lqZrAQ4jiOapVoeJ7JrszenQQ==", + "dev": true, + "dependencies": { + "json-parse-even-better-errors": "^2.3.0", + "npm-normalize-package-bin": "^1.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/read-package-json/node_modules/brace-expansion": { + "version": "2.0.1", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/read-package-json/node_modules/glob": { + "version": "8.1.0", + "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^5.0.1", + "once": "^1.3.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/read-package-json/node_modules/hosted-git-info": { + "version": "5.2.1", + "integrity": "sha512-xIcQYMnhcx2Nr4JTjsFmwwnr9vldugPy9uVm0o87bjqqWMv9GaqsTeT+i99wTl0mk1uLxJtHxLb8kymqTENQsw==", + "dev": true, + "dependencies": { + "lru-cache": "^7.5.1" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/read-package-json/node_modules/lru-cache": { + "version": "7.14.1", + "integrity": "sha512-ysxwsnTKdAx96aTRdhDOCQfDgbHnt8SK0KY8SEjO0wHinhWOFTESbjVCMPbU1uGXg/ch4lifqx0wfjOawU2+WA==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/read-package-json/node_modules/minimatch": { + "version": "5.1.6", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/read-package-json/node_modules/normalize-package-data": { + "version": "4.0.1", + "integrity": "sha512-EBk5QKKuocMJhB3BILuKhmaPjI8vNRSpIfO9woLC6NyHVkKKdVEdAO1mrT0ZfxNR1lKwCcTkuZfmGIFdizZ8Pg==", + "dev": true, + "dependencies": { + "hosted-git-info": "^5.0.0", + "is-core-module": "^2.8.1", + "semver": "^7.3.5", + "validate-npm-package-license": "^3.0.4" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/read-package-json/node_modules/npm-normalize-package-bin": { + "version": "2.0.0", + "integrity": "sha512-awzfKUO7v0FscrSpRoogyNm0sajikhBWpU0QMrW09AMi9n1PoKU6WaIqUzuJSQnpciZZmJ/jMZ2Egfmb/9LiWQ==", + "dev": true, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/read-pkg": { + "version": "5.2.0", + "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", + "dev": true, + "dependencies": { + "@types/normalize-package-data": "^2.4.0", + "normalize-package-data": "^2.5.0", + "parse-json": "^5.0.0", + "type-fest": "^0.6.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/read-pkg-up": { + "version": "7.0.1", + "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==", + "dev": true, + "dependencies": { + "find-up": "^4.1.0", + "read-pkg": "^5.2.0", + "type-fest": "^0.8.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/read-pkg-up/node_modules/find-up": { + "version": "4.1.0", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/read-pkg-up/node_modules/locate-path": { + "version": "5.0.0", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/read-pkg-up/node_modules/p-limit": { + "version": "2.3.0", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/read-pkg-up/node_modules/p-locate": { + "version": "4.1.0", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/read-pkg-up/node_modules/type-fest": { + "version": "0.8.1", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/read-pkg/node_modules/hosted-git-info": { + "version": "2.8.9", + "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", + "dev": true + }, + "node_modules/read-pkg/node_modules/normalize-package-data": { + "version": "2.5.0", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "dev": true, + "dependencies": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "node_modules/read-pkg/node_modules/semver": { + "version": "5.7.1", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/read-pkg/node_modules/type-fest": { + "version": "0.6.0", + "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/readable-stream": { + "version": "3.6.0", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/readdir-glob": { + "version": "1.1.2", + "integrity": "sha512-6RLVvwJtVwEDfPdn6X6Ille4/lxGl0ATOY4FN/B9nxQcgOazvvI0nodiD19ScKq0PvA/29VpaOQML36o5IzZWA==", + "dependencies": { + "minimatch": "^5.1.0" + } + }, + "node_modules/readdir-glob/node_modules/brace-expansion": { + "version": "2.0.1", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/readdir-glob/node_modules/minimatch": { + "version": "5.1.6", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/readdirp": { + "version": "3.6.0", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/redent": { + "version": "3.0.0", + "integrity": "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==", + "dev": true, + "dependencies": { + "indent-string": "^4.0.0", + "strip-indent": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/redent/node_modules/indent-string": { + "version": "4.0.0", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/registry-auth-token": { + "version": "4.2.2", + "integrity": "sha512-PC5ZysNb42zpFME6D/XlIgtNGdTl8bBOCw90xQLVMpzuuubJKYDWFAEuUNc+Cn8Z8724tg2SDhDRrkVEsqfDMg==", + "dev": true, + "dependencies": { + "rc": "1.2.8" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/registry-url": { + "version": "5.1.0", + "integrity": "sha512-8acYXXTI0AkQv6RAOjE3vOaIXZkT9wo4LOFbBKYQEEnnMNBpKqdUrI6S4NT0KPIo/WVvJ5tE/X5LF/TQUf0ekw==", + "dev": true, + "dependencies": { + "rc": "^1.2.8" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/release-zalgo": { + "version": "1.0.0", + "integrity": "sha512-gUAyHVHPPC5wdqX/LG4LWtRYtgjxyX78oanFNTMMyFEfOqdC54s3eE82imuWKbOeqYht2CrNf64Qb8vgmmtZGA==", + "dev": true, + "dependencies": { + "es6-error": "^4.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/remote-git-tags": { + "version": "3.0.0", + "integrity": "sha512-C9hAO4eoEsX+OXA4rla66pXZQ+TLQ8T9dttgQj18yuKlPMTVkIkdYXvlMC55IuUsIkV6DpmQYi10JKFLaU+l7w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/request": { + "version": "2.88.2", + "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", + "deprecated": "request has been deprecated, see https://github.com/request/request/issues/3142", + "dependencies": { + "aws-sign2": "~0.7.0", + "aws4": "^1.8.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", + "forever-agent": "~0.6.1", + "form-data": "~2.3.2", + "har-validator": "~5.1.3", + "http-signature": "~1.2.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.19", + "oauth-sign": "~0.9.0", + "performance-now": "^2.1.0", + "qs": "~6.5.2", + "safe-buffer": "^5.1.2", + "tough-cookie": "~2.5.0", + "tunnel-agent": "^0.6.0", + "uuid": "^3.3.2" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/request/node_modules/uuid": { + "version": "3.4.0", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", + "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", + "bin": { + "uuid": "bin/uuid" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/require-from-string": { + "version": "2.0.2", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/require-main-filename": { + "version": "2.0.0", + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", + "dev": true + }, + "node_modules/resolve": { + "version": "1.22.1", + "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", + "dependencies": { + "is-core-module": "^2.9.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-from": { + "version": "5.0.0", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/resolve-global": { + "version": "1.0.0", + "integrity": "sha512-zFa12V4OLtT5XUX/Q4VLvTfBf+Ok0SPc1FNGM/z9ctUdiU618qwKpWnd0CHs3+RqROfyEg/DhuHbMWYqcgljEw==", + "dev": true, + "dependencies": { + "global-dirs": "^0.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/responselike": { + "version": "1.0.2", + "integrity": "sha512-/Fpe5guzJk1gPqdJLJR5u7eG/gNY4nImjbRDaVWVMRhne55TCmj2i9Q+54PBRfatRC8v/rIiv9BN0pMd9OV5EQ==", + "dev": true, + "dependencies": { + "lowercase-keys": "^1.0.0" + } + }, + "node_modules/restore-cursor": { + "version": "3.1.0", + "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", + "dependencies": { + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/retry": { + "version": "0.12.0", + "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/reusify": { + "version": "1.0.4", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true, + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rfdc": { + "version": "1.3.0", + "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==" + }, + "node_modules/rimraf": { + "version": "3.0.2", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/run-async": { + "version": "2.4.1", + "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/rxjs": { + "version": "7.8.0", + "integrity": "sha512-F2+gxDshqmIub1KdvZkaEfGDwLNpPvk9Fs6LD/MyQxNgMds/WH9OdDDXOmxUZpME+iSK3rQCctkL0DYyytUqMg==", + "dependencies": { + "tslib": "^2.1.0" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/safe-json-stringify": { + "version": "1.2.0", + "integrity": "sha512-gH8eh2nZudPQO6TytOvbxnuhYBOvDBBLW52tz5q6X58lJcd/tkmqFR+5Z9adS8aJtURSXWThWy/xJtJwixErvg==", + "optional": true + }, + "node_modules/safe-stable-stringify": { + "version": "1.1.1", + "integrity": "sha512-ERq4hUjKDbJfE4+XtZLFPCDi8Vb1JqaxAPTxWFLBx8XcAlf9Bda/ZJdVezs/NAfsMQScyIlUMx+Yeu7P7rx5jw==", + "dev": true + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "node_modules/sax": { + "version": "1.2.1", + "integrity": "sha512-8I2a3LovHTOpm7NV5yOyO8IHqgVsfK4+UuySrXU8YXkSRX7k6hCV9b3HrkKCr3nMpgj+0bmocaJJWpvp1oc7ZA==" + }, + "node_modules/semaphore": { + "version": "1.1.0", + "integrity": "sha512-O4OZEaNtkMd/K0i6js9SL+gqy0ZCBMgUvlSqHKi4IBdjhe7wB8pwztUk1BbZ1fmrvpwFrPbHzqd2w5pTcJH6LA==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/semver": { + "version": "7.3.8", + "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/semver-diff": { + "version": "3.1.1", + "integrity": "sha512-GX0Ix/CJcHyB8c4ykpHGIAvLyOwOobtM/8d+TQkAd81/bEjgPHrfba41Vpesr7jX/t8Uh+R3EX9eAS5be+jQYg==", + "dev": true, + "dependencies": { + "semver": "^6.3.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/semver-diff/node_modules/semver": { + "version": "6.3.0", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/semver-utils": { + "version": "1.1.4", + "integrity": "sha512-EjnoLE5OGmDAVV/8YDoN5KiajNadjzIp9BAHOhYeQHt7j0UWxjmgsx4YD48wp4Ue1Qogq38F1GNUJNqF1kKKxA==", + "dev": true + }, + "node_modules/semver/node_modules/lru-cache": { + "version": "6.0.0", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/semver/node_modules/yallist": { + "version": "4.0.0", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, + "node_modules/serialize-javascript": { + "version": "6.0.0", + "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", + "dev": true, + "dependencies": { + "randombytes": "^2.1.0" + } + }, + "node_modules/set-blocking": { + "version": "2.0.0", + "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", + "dev": true + }, + "node_modules/setimmediate": { + "version": "1.0.5", + "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==", + "dev": true + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "engines": { + "node": ">=8" + } + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" + }, + "node_modules/signale": { + "version": "1.4.0", + "integrity": "sha512-iuh+gPf28RkltuJC7W5MRi6XAjTDCAPC/prJUpQoG4vIP3MJZ+GTydVnodXA7pwvTKb2cA0m9OFZW/cdWy/I/w==", + "dev": true, + "dependencies": { + "chalk": "^2.3.2", + "figures": "^2.0.0", + "pkg-conf": "^2.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/signale/node_modules/ansi-styles": { + "version": "3.2.1", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/signale/node_modules/chalk": { + "version": "2.4.2", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/signale/node_modules/color-convert": { + "version": "1.9.3", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/signale/node_modules/color-name": { + "version": "1.1.3", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true + }, + "node_modules/signale/node_modules/figures": { + "version": "2.0.0", + "integrity": "sha512-Oa2M9atig69ZkfwiApY8F2Yy+tzMbazyvqv21R0NsSC8floSOC09BbT1ITWAdoMGQvJ/aZnR1KMwdx9tvHnTNA==", + "dev": true, + "dependencies": { + "escape-string-regexp": "^1.0.5" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/signale/node_modules/has-flag": { + "version": "3.0.0", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/signale/node_modules/supports-color": { + "version": "5.5.0", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/simple-update-notifier": { + "version": "1.1.0", + "integrity": "sha512-VpsrsJSUcJEseSbMHkrsrAVSdvVS5I96Qo1QAQ4FxQ9wXFcB+pjj7FB7/us9+GcgfW4ziHtYMc1J0PLczb55mg==", + "dependencies": { + "semver": "~7.0.0" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/simple-update-notifier/node_modules/semver": { + "version": "7.0.0", + "integrity": "sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/sinon": { + "version": "13.0.2", + "integrity": "sha512-KvOrztAVqzSJWMDoxM4vM+GPys1df2VBoXm+YciyB/OLMamfS3VXh3oGh5WtrAGSzrgczNWFFY22oKb7Fi5eeA==", + "dev": true, + "dependencies": { + "@sinonjs/commons": "^1.8.3", + "@sinonjs/fake-timers": "^9.1.2", + "@sinonjs/samsam": "^6.1.1", + "diff": "^5.0.0", + "nise": "^5.1.1", + "supports-color": "^7.2.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/sinon" + } + }, + "node_modules/sinon-chai": { + "version": "3.7.0", + "integrity": "sha512-mf5NURdUaSdnatJx3uhoBOrY9dtL19fiOtAdT1Azxg3+lNJFiuN0uzaU3xX1LeAfL17kHQhTAJgpsfhbMJMY2g==", + "dev": true, + "peerDependencies": { + "chai": "^4.0.0", + "sinon": ">=4.0.0" + } + }, + "node_modules/sisteransi": { + "version": "1.0.5", + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", + "dev": true + }, + "node_modules/slash": { + "version": "3.0.0", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/slice-ansi": { + "version": "5.0.0", + "integrity": "sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==", + "dependencies": { + "ansi-styles": "^6.0.0", + "is-fullwidth-code-point": "^4.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" + } + }, + "node_modules/slice-ansi/node_modules/ansi-styles": { + "version": "6.2.1", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/smart-buffer": { + "version": "4.2.0", + "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", + "dev": true, + "engines": { + "node": ">= 6.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/socks": { + "version": "2.7.1", + "integrity": "sha512-7maUZy1N7uo6+WVEX6psASxtNlKaNVMlGQKkG/63nEDdLOWNbiUMoLK7X4uYoLhQstau72mLgfEWcXcwsaHbYQ==", + "dev": true, + "dependencies": { + "ip": "^2.0.0", + "smart-buffer": "^4.2.0" + }, + "engines": { + "node": ">= 10.13.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/socks-proxy-agent": { + "version": "7.0.0", + "integrity": "sha512-Fgl0YPZ902wEsAyiQ+idGd1A7rSFx/ayC1CQVMw5P+EQx2V0SgpGtf6OKFhVjPflPUl9YMmEOnmfjCdMUsygww==", + "dev": true, + "dependencies": { + "agent-base": "^6.0.2", + "debug": "^4.3.3", + "socks": "^2.6.2" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/sonic-boom": { + "version": "1.4.1", + "integrity": "sha512-LRHh/A8tpW7ru89lrlkU4AszXt1dbwSjVWguGrmlxE7tawVmDBlI1PILMkXAxJTwqhgsEeTHzj36D5CmHgQmNg==", + "dev": true, + "dependencies": { + "atomic-sleep": "^1.0.0", + "flatstr": "^1.0.12" + } + }, + "node_modules/source-map": { + "version": "0.6.1", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-support": { + "version": "0.5.21", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/spawn-please": { + "version": "1.0.0", + "integrity": "sha512-Kz33ip6NRNKuyTRo3aDWyWxeGeM0ORDO552Fs6E1nj4pLWPkl37SrRtTnq+MEopVaqgmaO6bAvVS+v64BJ5M/A==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/spawn-wrap": { + "version": "2.0.0", + "integrity": "sha512-EeajNjfN9zMnULLwhZZQU3GWBoFNkbngTUPfaawT4RkMiviTxcX0qfhVbGey39mfctfDHkWtuecgQ8NJcyQWHg==", + "dev": true, + "dependencies": { + "foreground-child": "^2.0.0", + "is-windows": "^1.0.2", + "make-dir": "^3.0.0", + "rimraf": "^3.0.0", + "signal-exit": "^3.0.2", + "which": "^2.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/spdx-correct": { + "version": "3.1.1", + "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", + "dev": true, + "dependencies": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-exceptions": { + "version": "2.3.0", + "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", + "dev": true + }, + "node_modules/spdx-expression-parse": { + "version": "3.0.1", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "dev": true, + "dependencies": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-license-ids": { + "version": "3.0.12", + "integrity": "sha512-rr+VVSXtRhO4OHbXUiAF7xW3Bo9DuuF6C5jH+q/x15j2jniycgKbxU09Hr0WqlSLUs4i4ltHGXqTe7VHclYWyA==", + "dev": true + }, + "node_modules/split": { + "version": "1.0.1", + "integrity": "sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg==", + "dev": true, + "dependencies": { + "through": "2" + }, + "engines": { + "node": "*" + } + }, + "node_modules/split2": { + "version": "3.2.2", + "integrity": "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==", + "dev": true, + "dependencies": { + "readable-stream": "^3.0.0" + } + }, + "node_modules/sprintf-js": { + "version": "1.0.3", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", + "dev": true + }, + "node_modules/sshpk": { + "version": "1.17.0", + "integrity": "sha512-/9HIEs1ZXGhSPE8X6Ccm7Nam1z8KcoCqPdI7ecm1N33EzAetWahvQWVqLZtaZQ+IDKX4IyA2o0gBzqIMkAagHQ==", + "dependencies": { + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", + "tweetnacl": "~0.14.0" + }, + "bin": { + "sshpk-conv": "bin/sshpk-conv", + "sshpk-sign": "bin/sshpk-sign", + "sshpk-verify": "bin/sshpk-verify" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ssri": { + "version": "9.0.1", + "integrity": "sha512-o57Wcn66jMQvfHG1FlYbWeZWW/dHZhJXjpIcTfXldXEk5nz5lStPo3mK0OJQfGR3RbZUlbISexbljkJzuEj/8Q==", + "dev": true, + "dependencies": { + "minipass": "^3.1.1" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/stack-utils": { + "version": "2.0.6", + "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==", + "dev": true, + "dependencies": { + "escape-string-regexp": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/stack-utils/node_modules/escape-string-regexp": { + "version": "2.0.0", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/standard-version": { + "version": "9.5.0", + "integrity": "sha512-3zWJ/mmZQsOaO+fOlsa0+QK90pwhNd042qEcw6hKFNoLFs7peGyvPffpEBbK/DSGPbyOvli0mUIFv5A4qTjh2Q==", + "dev": true, + "dependencies": { + "chalk": "^2.4.2", + "conventional-changelog": "3.1.25", + "conventional-changelog-config-spec": "2.1.0", + "conventional-changelog-conventionalcommits": "4.6.3", + "conventional-recommended-bump": "6.1.0", + "detect-indent": "^6.0.0", + "detect-newline": "^3.1.0", + "dotgitignore": "^2.1.0", + "figures": "^3.1.0", + "find-up": "^5.0.0", + "git-semver-tags": "^4.0.0", + "semver": "^7.1.1", + "stringify-package": "^1.0.1", + "yargs": "^16.0.0" + }, + "bin": { + "standard-version": "bin/cli.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/standard-version/node_modules/ansi-styles": { + "version": "3.2.1", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/standard-version/node_modules/chalk": { + "version": "2.4.2", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/standard-version/node_modules/cliui": { + "version": "7.0.4", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "dev": true, + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "node_modules/standard-version/node_modules/color-convert": { + "version": "1.9.3", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/standard-version/node_modules/color-name": { + "version": "1.1.3", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true + }, + "node_modules/standard-version/node_modules/has-flag": { + "version": "3.0.0", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/standard-version/node_modules/supports-color": { + "version": "5.5.0", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/standard-version/node_modules/yargs": { + "version": "16.2.0", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "dev": true, + "dependencies": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/string-argv": { + "version": "0.3.1", + "integrity": "sha512-a1uQGz7IyVy9YwhqjZIZu1c8JO8dNIe20xBmSS6qu9kv++k3JGzCVmprbNN5Kn+BgzD5E7YYwg1CcjuJMRNsvg==", + "engines": { + "node": ">=0.6.19" + } + }, + "node_modules/string-width": { + "version": "4.2.3", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "engines": { + "node": ">=8" + } + }, + "node_modules/stringify-package": { + "version": "1.0.1", + "integrity": "sha512-sa4DUQsYciMP1xhKWGuFM04fB0LG/9DlluZoSVywUMRNvzid6XucHK0/90xGxRoHrAaROrcHK1aPKaijCtSrhg==", + "deprecated": "This module is not used anymore, and has been replaced by @npmcli/package-json", + "dev": true + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-bom": { + "version": "4.0.0", + "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-final-newline": { + "version": "2.0.0", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "engines": { + "node": ">=6" + } + }, + "node_modules/strip-indent": { + "version": "3.0.0", + "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==", + "dev": true, + "dependencies": { + "min-indent": "^1.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/strnum": { + "version": "1.0.5", + "integrity": "sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA==", + "dev": true + }, + "node_modules/supports-color": { + "version": "7.2.0", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/symbol-observable": { + "version": "1.2.0", + "integrity": "sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/tar": { + "version": "6.1.13", + "integrity": "sha512-jdIBIN6LTIe2jqzay/2vtYLlBHa3JF42ot3h1dW8Q0PaAG4v8rm0cvpVePtau5C6OKXGGcgO9q2AMNSWxiLqKw==", + "dev": true, + "dependencies": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^4.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/tar-stream": { + "version": "2.2.0", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "dependencies": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/tar/node_modules/minipass": { + "version": "4.0.0", + "integrity": "sha512-g2Uuh2jEKoht+zvO6vJqXmYpflPqzRBT+Th2h01DKh5z7wbY/AZ2gCQ78cP70YoHPyFdY30YBV5WxgLOEwOykw==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/tar/node_modules/mkdirp": { + "version": "1.0.4", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true, + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/tar/node_modules/yallist": { + "version": "4.0.0", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/test-exclude": { + "version": "6.0.0", + "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", + "dev": true, + "dependencies": { + "@istanbuljs/schema": "^0.1.2", + "glob": "^7.1.4", + "minimatch": "^3.0.4" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/text-extensions": { + "version": "1.9.0", + "integrity": "sha512-wiBrwC1EhBelW12Zy26JeOUkQ5mRu+5o8rpsJk5+2t+Y5vE7e842qtZDQ2g1NpX/29HdyFeJ4nSIhI47ENSxlQ==", + "dev": true, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/through": { + "version": "2.3.8", + "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==" + }, + "node_modules/through2": { + "version": "4.0.2", + "integrity": "sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==", + "dev": true, + "dependencies": { + "readable-stream": "3" + } + }, + "node_modules/tmp": { + "version": "0.2.1", + "integrity": "sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==", + "dependencies": { + "rimraf": "^3.0.0" + }, + "engines": { + "node": ">=8.17.0" + } + }, + "node_modules/tmpl": { + "version": "1.0.5", + "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==", + "dev": true + }, + "node_modules/to-fast-properties": { + "version": "2.0.0", + "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/to-readable-stream": { + "version": "1.0.0", + "integrity": "sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/touch": { + "version": "3.1.0", + "integrity": "sha512-WBx8Uy5TLtOSRtIq+M03/sKDrXCLHxwDcquSP2c43Le03/9serjQBIztjRz6FkJez9D/hleyAXTBGLwwZUw9lA==", + "dependencies": { + "nopt": "~1.0.10" + }, + "bin": { + "nodetouch": "bin/nodetouch.js" + } + }, + "node_modules/touch/node_modules/nopt": { + "version": "1.0.10", + "integrity": "sha512-NWmpvLSqUrgrAC9HCuxEvb+PSloHpqVu+FqcO4eeF2h5qYRhA7ev6KvelyQAKtegUbC6RypJnlEOhd8vloNKYg==", + "dependencies": { + "abbrev": "1" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": "*" + } + }, + "node_modules/tough-cookie": { + "version": "2.5.0", + "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", + "dependencies": { + "psl": "^1.1.28", + "punycode": "^2.1.1" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/tr46": { + "version": "0.0.3", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", + "dev": true + }, + "node_modules/traverse": { + "version": "0.3.9", + "integrity": "sha512-iawgk0hLP3SxGKDfnDJf8wTz4p2qImnyihM5Hh/sGvQ3K37dPi/w8sRhdNIxYA1TwFwc5mDhIJq+O0RsvXBKdQ==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/trim-newlines": { + "version": "3.0.1", + "integrity": "sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/ts-node": { + "version": "10.9.1", + "integrity": "sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==", + "dev": true, + "dependencies": { + "@cspotcode/source-map-support": "^0.8.0", + "@tsconfig/node10": "^1.0.7", + "@tsconfig/node12": "^1.0.7", + "@tsconfig/node14": "^1.0.0", + "@tsconfig/node16": "^1.0.2", + "acorn": "^8.4.1", + "acorn-walk": "^8.1.1", + "arg": "^4.1.0", + "create-require": "^1.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "v8-compile-cache-lib": "^3.0.1", + "yn": "3.1.1" + }, + "bin": { + "ts-node": "dist/bin.js", + "ts-node-cwd": "dist/bin-cwd.js", + "ts-node-esm": "dist/bin-esm.js", + "ts-node-script": "dist/bin-script.js", + "ts-node-transpile-only": "dist/bin-transpile.js", + "ts-script": "dist/bin-script-deprecated.js" + }, + "peerDependencies": { + "@swc/core": ">=1.2.50", + "@swc/wasm": ">=1.2.50", + "@types/node": "*", + "typescript": ">=2.7" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "@swc/wasm": { + "optional": true + } + } + }, + "node_modules/ts-node/node_modules/diff": { + "version": "4.0.2", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "dev": true, + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/ts-toolbelt": { + "version": "6.15.5", + "integrity": "sha512-FZIXf1ksVyLcfr7M317jbB67XFJhOO1YqdTcuGaq9q5jLUoTikukZ+98TPjKiP2jC5CgmYdWWYs0s2nLSU0/1A==", + "dev": true + }, + "node_modules/tslib": { + "version": "2.5.0", + "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" + }, + "node_modules/tunnel-agent": { + "version": "0.6.0", + "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", + "dependencies": { + "safe-buffer": "^5.0.1" + }, + "engines": { + "node": "*" + } + }, + "node_modules/tv4": { + "version": "1.3.0", + "integrity": "sha512-afizzfpJgvPr+eDkREK4MxJ/+r8nEEHcmitwgnPUqpaP+FpwQyadnxNoSACbgc/b1LsZYtODGoPiFxQrgJgjvw==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/tweetnacl": { + "version": "0.14.5", + "integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==" + }, + "node_modules/type-detect": { + "version": "4.0.8", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/type-fest": { + "version": "0.21.3", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/type-is": { + "version": "1.6.18", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "dev": true, + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/typedarray": { + "version": "0.0.6", + "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==", + "dev": true + }, + "node_modules/typedarray-to-buffer": { + "version": "3.1.5", + "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", + "dev": true, + "dependencies": { + "is-typedarray": "^1.0.0" + } + }, + "node_modules/typescript": { + "version": "4.9.4", + "integrity": "sha512-Uz+dTXYzxXXbsFpM86Wh3dKCxrQqUcVMxwU54orwlJjOpO3ao8L7j5lH+dWfTwgCwIuM9GQ2kvVotzYJMXTBZg==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=4.2.0" + } + }, + "node_modules/uglify-js": { + "version": "3.17.4", + "integrity": "sha512-T9q82TJI9e/C1TAxYvfb16xO120tMVFZrGA3f9/P4424DNu6ypK103y0GPFVa17yotwSyZW5iYXgjYHkGrJW/g==", + "dev": true, + "optional": true, + "bin": { + "uglifyjs": "bin/uglifyjs" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/undefsafe": { + "version": "2.0.5", + "integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==" + }, + "node_modules/unique-filename": { + "version": "2.0.1", + "integrity": "sha512-ODWHtkkdx3IAR+veKxFV+VBkUMcN+FaqzUUd7IZzt+0zhDZFPFxhlqwPF3YQvMHx1TD0tdgYl+kuPnJ8E6ql7A==", + "dev": true, + "dependencies": { + "unique-slug": "^3.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/unique-slug": { + "version": "3.0.0", + "integrity": "sha512-8EyMynh679x/0gqE9fT9oilG+qEt+ibFyqjuVTsZn1+CMxH+XLlpvr2UZx4nVcCwTpx81nICr2JQFkM+HPLq4w==", + "dev": true, + "dependencies": { + "imurmurhash": "^0.1.4" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/unique-string": { + "version": "2.0.0", + "integrity": "sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==", + "dev": true, + "dependencies": { + "crypto-random-string": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/universalify": { + "version": "2.0.0", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/untildify": { + "version": "4.0.0", + "integrity": "sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/unzipper": { + "version": "0.10.11", + "integrity": "sha512-+BrAq2oFqWod5IESRjL3S8baohbevGcVA+teAIOYWM3pDVdseogqbzhhvvmiyQrUNKFUnDMtELW3X8ykbyDCJw==", + "dev": true, + "dependencies": { + "big-integer": "^1.6.17", + "binary": "~0.3.0", + "bluebird": "~3.4.1", + "buffer-indexof-polyfill": "~1.0.0", + "duplexer2": "~0.1.4", + "fstream": "^1.0.12", + "graceful-fs": "^4.2.2", + "listenercount": "~1.0.1", + "readable-stream": "~2.3.6", + "setimmediate": "~1.0.4" + } + }, + "node_modules/unzipper/node_modules/bluebird": { + "version": "3.4.7", + "integrity": "sha512-iD3898SR7sWVRHbiQv+sHUtHnMvC1o3nW5rAcqnq3uOn07DSAppZYUkIGslDz6gXC7HfunPe7YVBgoEJASPcHA==", + "dev": true + }, + "node_modules/unzipper/node_modules/readable-stream": { + "version": "2.3.7", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/unzipper/node_modules/safe-buffer": { + "version": "5.1.2", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/unzipper/node_modules/string_decoder": { + "version": "1.1.1", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.0.10", + "integrity": "sha512-OztqDenkfFkbSG+tRxBeAnCVPckDBcvibKd35yDONx6OU8N7sqgwc7rCbkJ/WcYtVRZ4ba68d6byhC21GFh7sQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + } + ], + "dependencies": { + "escalade": "^3.1.1", + "picocolors": "^1.0.0" + }, + "bin": { + "browserslist-lint": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/update-notifier": { + "version": "5.1.0", + "integrity": "sha512-ItnICHbeMh9GqUy31hFPrD1kcuZ3rpxDZbf4KUDavXwS0bW5m7SLbDQpGX3UYr072cbrF5hFUs3r5tUsPwjfHw==", + "dev": true, + "dependencies": { + "boxen": "^5.0.0", + "chalk": "^4.1.0", + "configstore": "^5.0.1", + "has-yarn": "^2.1.0", + "import-lazy": "^2.1.0", + "is-ci": "^2.0.0", + "is-installed-globally": "^0.4.0", + "is-npm": "^5.0.0", + "is-yarn-global": "^0.3.0", + "latest-version": "^5.1.0", + "pupa": "^2.1.1", + "semver": "^7.3.4", + "semver-diff": "^3.1.1", + "xdg-basedir": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/yeoman/update-notifier?sponsor=1" + } + }, + "node_modules/update-notifier/node_modules/chalk": { + "version": "4.1.2", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/uri-template-lite": { + "version": "22.9.0", + "integrity": "sha512-cmGZaykSWEQ5UXKaGKnUS8zFvfp8j1Jvn7dlq3P7tGd5XeybXcfo0xnVBRWiNEp80nO1GYgCLwoaRJ8WMmmk3Q==", + "dev": true + }, + "node_modules/urijs": { + "version": "1.19.11", + "integrity": "sha512-HXgFDgDommxn5/bIv0cnQZsPhHDA90NPHD6+c/v21U5+Sx5hoP8+dP9IZXBU1gIfvdRfhG8cel9QNPeionfcCQ==", + "dev": true + }, + "node_modules/url": { + "version": "0.10.3", + "integrity": "sha512-hzSUW2q06EqL1gKM/a+obYHLIO6ct2hwPuviqTTOcfFVc61UbfJ2Q32+uGL/HCPxKqrdGB5QUwIe7UqlDgwsOQ==", + "dependencies": { + "punycode": "1.3.2", + "querystring": "0.2.0" + } + }, + "node_modules/url-parse-lax": { + "version": "3.0.0", + "integrity": "sha512-NjFKA0DidqPa5ciFcSrXnAltTtzz84ogy+NebPvfEgAck0+TNg4UJ4IN+fB7zRZfbgUf0syOo9MDxFkDSMuFaQ==", + "dev": true, + "dependencies": { + "prepend-http": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/url/node_modules/punycode": { + "version": "1.3.2", + "integrity": "sha512-RofWgt/7fL5wP1Y7fxE7/EmTLzQVnB0ycyibJ0OOHIlJqTNzglYFxVwETOcIoJqJmpDXJ9xImDv+Fq34F/d4Dw==" + }, + "node_modules/util": { + "version": "0.12.5", + "integrity": "sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==", + "dependencies": { + "inherits": "^2.0.3", + "is-arguments": "^1.0.4", + "is-generator-function": "^1.0.7", + "is-typed-array": "^1.1.3", + "which-typed-array": "^1.1.2" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" + }, + "node_modules/utility-types": { + "version": "3.10.0", + "integrity": "sha512-O11mqxmi7wMKCo6HKFt5AhO4BwY3VV68YU07tgxfz8zJTIxr4BpsezN49Ffwy9j3ZpwwJp4fkRwjRzq3uWE6Rg==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/uuid": { + "version": "8.3.2", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/v8-compile-cache-lib": { + "version": "3.0.1", + "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", + "dev": true + }, + "node_modules/valid-url": { + "version": "1.0.9", + "integrity": "sha512-QQDsV8OnSf5Uc30CKSwG9lnhMPe6exHtTXLRYX8uMwKENy640pU+2BgBL0LRbDh/eYRahNCS7aewCx0wf3NYVA==" + }, + "node_modules/validate-npm-package-license": { + "version": "3.0.4", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "dev": true, + "dependencies": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "node_modules/validate-npm-package-name": { + "version": "4.0.0", + "integrity": "sha512-mzR0L8ZDktZjpX4OB46KT+56MAhl4EIazWP/+G/HPGuvfdaqg4YsCdtOm6U9+LOFyYDoh4dpnpxZRB9MQQns5Q==", + "dev": true, + "dependencies": { + "builtins": "^5.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/validate.io-array": { + "version": "1.0.6", + "integrity": "sha512-DeOy7CnPEziggrOO5CZhVKJw6S3Yi7e9e65R1Nl/RTN1vTQKnzjfvks0/8kQ40FP/dsjRAOd4hxmJ7uLa6vxkg==", + "dev": true + }, + "node_modules/validate.io-function": { + "version": "1.0.2", + "integrity": "sha512-LlFybRJEriSuBnUhQyG5bwglhh50EpTL2ul23MPIuR1odjO7XaMLFV8vHGwp7AZciFxtYOeiSCT5st+XSPONiQ==", + "dev": true + }, + "node_modules/validate.io-integer": { + "version": "1.0.5", + "integrity": "sha512-22izsYSLojN/P6bppBqhgUDjCkr5RY2jd+N2a3DCAUey8ydvrZ/OkGvFPR7qfOpwR2LC5p4Ngzxz36g5Vgr/hQ==", + "dev": true, + "dependencies": { + "validate.io-number": "^1.0.3" + } + }, + "node_modules/validate.io-integer-array": { + "version": "1.0.0", + "integrity": "sha512-mTrMk/1ytQHtCY0oNO3dztafHYyGU88KL+jRxWuzfOmQb+4qqnWmI+gykvGp8usKZOM0H7keJHEbRaFiYA0VrA==", + "dev": true, + "dependencies": { + "validate.io-array": "^1.0.3", + "validate.io-integer": "^1.0.4" + } + }, + "node_modules/validate.io-number": { + "version": "1.0.3", + "integrity": "sha512-kRAyotcbNaSYoDnXvb4MHg/0a1egJdLwS6oJ38TJY7aw9n93Fl/3blIXdyYvPOp55CNxywooG/3BcrwNrBpcSg==", + "dev": true + }, + "node_modules/verror": { + "version": "1.10.0", + "integrity": "sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==", + "engines": [ + "node >=0.6.0" + ], + "dependencies": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + } + }, + "node_modules/walker": { + "version": "1.0.8", + "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==", + "dev": true, + "dependencies": { + "makeerror": "1.0.12" + } + }, + "node_modules/wcwidth": { + "version": "1.0.1", + "integrity": "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==", + "dependencies": { + "defaults": "^1.0.3" + } + }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", + "dev": true + }, + "node_modules/whatwg-fetch": { + "version": "3.6.2", + "integrity": "sha512-bJlen0FcuU/0EMLrdbJ7zOnW6ITZLrZMIarMUVmdKtsGvZna8vxKYaexICWPfZ8qwf9fzNq+UEIZrnSaApt6RA==", + "dev": true + }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "dev": true, + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "node_modules/which": { + "version": "2.0.2", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/which-module": { + "version": "2.0.0", + "integrity": "sha512-B+enWhmw6cjfVC7kS8Pj9pCrKSc5txArRyaYGe088shv/FGWH+0Rjx/xPgtsWfsUtS27FkP697E4DDhgrgoc0Q==", + "dev": true + }, + "node_modules/which-typed-array": { + "version": "1.1.9", + "integrity": "sha512-w9c4xkx6mPidwp7180ckYWfMmvxpjlZuIudNtDf4N/tTAUB8VJbX25qZoAsrtGuYNnGw3pa0AXgbGKRB8/EceA==", + "dependencies": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-tostringtag": "^1.0.0", + "is-typed-array": "^1.1.10" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/wide-align": { + "version": "1.1.5", + "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", + "dev": true, + "dependencies": { + "string-width": "^1.0.2 || 2 || 3 || 4" + } + }, + "node_modules/widest-line": { + "version": "3.1.0", + "integrity": "sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==", + "dev": true, + "dependencies": { + "string-width": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wordwrap": { + "version": "1.0.0", + "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==", + "dev": true + }, + "node_modules/workerpool": { + "version": "6.2.0", + "integrity": "sha512-Rsk5qQHJ9eowMH28Jwhe8HEbmdYDX4lwoMWshiCXugjtHqMD9ZbiqSDLxcsfdqsETPzVUtX5s1Z5kStiIM6l4A==", + "dev": true + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" + }, + "node_modules/write-file-atomic": { + "version": "4.0.2", + "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==", + "dev": true, + "dependencies": { + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.7" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/xdg-basedir": { + "version": "4.0.0", + "integrity": "sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/xml2js": { + "version": "0.4.19", + "integrity": "sha512-esZnJZJOiJR9wWKMyuvSE1y6Dq5LCuJanqhxslH2bxM6duahNZ+HMpCLhBQGZkbX6xRf8x1Y2eJlgt2q3qo49Q==", + "dependencies": { + "sax": ">=0.6.0", + "xmlbuilder": "~9.0.1" + } + }, + "node_modules/xmlbuilder": { + "version": "9.0.7", + "integrity": "sha512-7YXTQc3P2l9+0rjaUbLwMKRhtmwg1M1eDf6nag7urC7pIPYLD9W/jmzQ4ptRSUbodw5S0jfoGTflLemQibSpeQ==", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/xtend": { + "version": "4.0.2", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dev": true, + "engines": { + "node": ">=0.4" + } + }, + "node_modules/y18n": { + "version": "5.0.8", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "engines": { + "node": ">=10" + } + }, + "node_modules/yallist": { + "version": "3.1.1", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true + }, + "node_modules/yaml": { + "version": "1.10.2", + "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", + "engines": { + "node": ">= 6" + } + }, + "node_modules/yargs": { + "version": "17.6.2", + "integrity": "sha512-1/9UrdHjDZc0eOU0HxOHoS78C69UD3JRMvzlJ7S79S2nTaWRA/whGCTV8o9e/N/1Va9YIV7Q4sOxD8VV4pCWOw==", + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "20.2.9", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/yargs-unparser": { + "version": "2.0.0", + "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", + "dev": true, + "dependencies": { + "camelcase": "^6.0.0", + "decamelize": "^4.0.0", + "flat": "^5.0.2", + "is-plain-obj": "^2.1.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/yargs-unparser/node_modules/camelcase": { + "version": "6.3.0", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/yargs-unparser/node_modules/decamelize": { + "version": "4.0.0", + "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/yargs-unparser/node_modules/is-plain-obj": { + "version": "2.1.0", + "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/yargs/node_modules/yargs-parser": { + "version": "21.1.1", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "engines": { + "node": ">=12" + } + }, + "node_modules/yn": { + "version": "3.1.1", + "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/zip-stream": { + "version": "4.1.0", + "integrity": "sha512-zshzwQW7gG7hjpBlgeQP9RuyPGNxvJdzR8SUM3QhxCnLjWN2E7j3dOvpeDcQoETfHx0urRS7EtmVToql7YpU4A==", + "dependencies": { + "archiver-utils": "^2.1.0", + "compress-commons": "^4.1.0", + "readable-stream": "^3.6.0" + }, + "engines": { + "node": ">= 10" + } + } + } +} diff --git a/package.json b/package.json index c624676b..7c693c82 100644 --- a/package.json +++ b/package.json @@ -1,18 +1,18 @@ { "name": "ask-cli", - "version": "2.28.0", + "version": "2.29.0", "description": "Alexa Skills Kit (ASK) Command Line Interfaces", "bin": { - "ask": "bin/ask.js" + "ask": "dist/bin/ask.js" }, "engines": { - "node": ">=8.3.0" + "node": ">=12" }, "license": "Apache 2.0", "repository": "alexa/ask-cli", "author": { - "name": "RonWang", - "email": "nongwang@amazon.com" + "name": "Alexa Skills Kit", + "email": "ask-tools@amazon.com" }, "keywords": [ "alexa", @@ -24,110 +24,133 @@ "deploy" ], "scripts": { - "test": "node ./node_modules/mocha/bin/_mocha -t 10000 -u exports -R spec test/unit/run-test.js", - "test:watch": "node ./node_modules/mocha/bin/_mocha test/unit/run-test.js -w", - "test:report": "nyc --cache npm test && nyc report --reporter=html", + "build": "npm run clean && tsc && npm run copy:assets", + "clean": "rm -rf ./dist && rm -rf ./package", + "copy:assets": "copyfiles -u 1 lib/**/*.yaml dist/lib", + "test": "mocha -t 10000 -u bdd --require ts-node/register --require test/unit/run-test.js -R spec 'test/unit/{,**/}!(*.d).{ts,js}'", + "test:single": "mocha -t 10000 -u bdd --require ts-node/register --require test/unit/run-test.js -R spec ", + "test:fast": "TS_NODE_TRANSPILE_ONLY=true npm run test", + "test:watch": "mocha --require ts-node/register test/unit/run-test.js -w", + "test:report": "nyc npm run test", "test:browser": "npm run test:report && open coverage/index.html", "integration-test": "mocha -t 180000 test/integration/run-test.js", - "functional-test": "mocha -t 600000 --retries 2 test/functional/run-test.js", + "functional-test": "mocha -t 600000 -u bdd --require ts-node/register test/functional/run-test.js -R spec 'test/functional/{,**/}!(*.d).{ts,js}'", "functional-test:clean-up": "node scripts/aws-clean-up.js; node scripts/ask-clean-up.js", - "lint": "eslint lib/builtins lib/clients lib/commands lib/controllers lib/model lib/view", - "prepublishOnly": "babel lib -d lib; babel bin -d bin", + "format": "prettier --write .", "pre-release": "standard-version", + "prepare": "husky install", "prism": "prism", - "postinstall": "node postinstall.js" + "postinstall": "node ./dist/lib/postinstall.js || true", + "watch": "tsc --watch" }, "dependencies": { - "@actions/core": "^1.10.0", - "adm-zip": "^0.4.13", - "archiver": "^1.1.0", + "@alexa/acdl": "^0.3.0", + "adm-zip": "^0.5.9", + "archiver": "^5.3.0", "ask-smapi-model": "~1.19.7", - "ask-smapi-sdk": "^1.2.0", - "async": "^2.1.5", + "ask-smapi-sdk": "^1.3.0", + "async": "^2.6.1", "aws-profile-handler": "2.0.3", - "aws-sdk": "^2.288.0", - "axios": "^0.21.1", - "bunyan": "^1.8.12", - "chalk": "2.4.2", + "aws-sdk": "^2.1111.0", + "axios": "^0.26.1", + "bunyan": "^1.8.15", + "chalk": "4.0.0", "commander": "^4.1.1", - "date-fns": "^2.7.0", - "folder-hash": "^3.0.0", - "fs-extra": "^2.1.0", - "inquirer": "^6.2.0", - "js-yaml": "^3.13.1", - "jsonfile": "^2.4.0", + "date-fns": "^2.28.0", + "folder-hash": "^4.0.2", + "fs-extra": "^10.0.1", + "inquirer": "^8.2.2", + "js-yaml": "^4.1.0", + "jsonfile": "^6.1.0", + "lint-staged": "^12.3.7", "listr": "^0.14.3", - "module-alias": "^2.1.0", - "mustache": "^4.0.1", - "nodemon": "^2.0.4", - "open": "^7.0.3", + "mustache": "^4.2.0", + "nodemon": "^2.0.15", + "open": "^8.4.0", "ora": "^3.4.0", - "portscanner": "^2.1.1", - "pretty-bytes": "^5.1.0", - "ramda": "^0.27.0", - "request": "^2.79.0", - "rxjs": "^6.5.2", - "semver": "^5.3.0", - "tmp": "^0.1.0", - "uuid": "^3.4.0", + "portscanner": "^2.2.0", + "pretty-bytes": "^5.6.0", + "ramda": "^0.28.0", + "request": "^2.88.2", + "rxjs": "^7.5.5", + "semver": "^7.3.6", + "tmp": "^0.2.1", + "uuid": "^8.3.2", "valid-url": "^1.0.9" }, + "dependenciesComments": { + "chalk": "v5 onwards pure ESM https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c", + "ora": "v6 onwards is pure ESM", + "pretty-bytes": "v6 is pure ESM" + }, "devDependencies": { - "@babel/cli": "^7.12.1", - "@babel/core": "^7.12.3", - "@commitlint/cli": "^8.2.0", - "@commitlint/config-conventional": "^8.2.0", - "@stoplight/prism-cli": "^3.3.3", - "babel-plugin-module-resolver": "^4.0.0", - "chai": "^3.5.0", + "@commitlint/cli": "^16.2.3", + "@commitlint/config-conventional": "^16.2.1", + "@istanbuljs/nyc-config-typescript": "^1.0.2", + "@stoplight/prism-cli": "^4.8.0", + "@types/chai": "^4.3.0", + "@types/chai-as-promised": "^7.1.5", + "@types/chai-json-schema": "^1.4.6", + "@types/chai-uuid": "^1.0.2", + "@types/fs-extra": "^9.0.13", + "@types/inquirer": "^8.2.1", + "@types/jsonfile": "^6.1.0", + "@types/mocha": "^9.1.1", + "@types/portscanner": "^2.1.1", + "@types/proxyquire": "^1.3.28", + "@types/ramda": "^0.28.7", + "@types/semver": "^7.3.9", + "@types/sinon": "^10.0.11", + "@types/sinon-chai": "^3.2.8", + "@types/uuid": "^8.3.4", + "@types/vscode": "^1.34.0", + "@types/listr": "0.14.4", + "@vscode/test-electron": "^1.6.1", + "chai": "^4.3.6", + "chai-as-promised": "^7.1.1", "chai-json-schema": "^1.5.1", "chai-uuid": "^1.0.6", - "coveralls": "^3.0.2", - "eslint": "^6.8.0", - "eslint-config-airbnb-base": "^14.0.0", - "eslint-plugin-import": "^2.20.1", - "gulp": "^3.9.1", - "husky": "^4.2.3", - "mocha": "^3.2.0", + "copyfiles": "^2.4.1", + "husky": "^7.0.4", + "mocha": "^9.2.2", + "mocha-chai-jest-snapshot": "^1.1.3", "mocha.parallel": "^0.15.6", - "nyc": "^13.3.0", - "proxyquire": "^1.7.11", - "sinon": "^6.0.0", - "standard-version": "^8.0.1" + "npm-bundle": "3.0.3", + "npm-check-updates": "^12.5.8", + "nyc": "^15.1.0", + "postman-collection": "4.1.3", + "prettier": "^2.6.2", + "proxyquire": "^2.1.3", + "sinon": "^13.0.1", + "sinon-chai": "^3.7.0", + "standard-version": "^9.3.2", + "ts-node": "^10.7.0", + "typescript": "^4.6.3" }, - "husky": { - "hooks": { - "pre-commit": "npm run lint", - "commit-msg": "commitlint -E HUSKY_GIT_PARAMS", - "pre-push": "npm run test:report" - } + "lint-staged": { + "lib/{,**/}*.{ts,js}": [ + "prettier --write" + ] }, "nyc": { + "extends": "@istanbuljs/nyc-config-typescript", "check-coverage": true, - "lines": 95, - "statements": 95, - "functions": 95, - "branches": 95, + "lines": 80, + "functions": 80, + "statements": 80, + "all": true, "include": [ - "lib/utils/string-utils.js", - "lib/utils/url-utils.js", - "lib/utils/zip-utils.js", - "lib/utils/hash-utils.js", - "lib/utils/retry-utility.js", - "lib/builtins/*", - "lib/clients/*", - "lib/model/*", - "lib/view/*", - "lib/controllers/*", - "lib/commands/*" + "lib/**/!(*.test.*).[tj]s?(x)" ], "exclude": [ - "lib/clients/aws-client/aws-util.js" - ] - }, - "_moduleAliases": { - "@root": ".", - "@src": "./lib", - "@test": "./test" + "test/**/*.*" + ], + "reporter": [ + "html", + "lcov", + "text", + "text-summary" + ], + "report-dir": "coverage" } } diff --git a/scripts/ask-clean-up.js b/scripts/ask-clean-up.js index f622e610..ede9baea 100644 --- a/scripts/ask-clean-up.js +++ b/scripts/ask-clean-up.js @@ -1,17 +1,25 @@ /* eslint-disable no-await-in-loop */ -require('module-alias/register'); const { CustomSmapiClientBuilder } = require('ask-smapi-sdk'); -const AppConfig = require('@src/model/app-config'); -const AuthorizationController = require('@src/controllers/authorization-controller'); -const CONSTANTS = require('@src/utils/constants'); -const DynamicConfig = require('@src/utils/dynamic-config'); +const AppConfig = require('../lib/model/app-config'); +const AuthorizationController = require('../lib/controllers/authorization-controller'); +const CONSTANTS = require('../lib/utils/constants'); +const DynamicConfig = require('../lib/utils/dynamic-config'); +const profileHelper = require("../lib/utils/profile-helper"); new AppConfig(); const authorizationController = new AuthorizationController({ auth_client_type: 'LWA' }); -const profile = CONSTANTS.PLACEHOLDER.ENVIRONMENT_VAR.PROFILE_NAME; +const profile = _findEnvProfile() || process.env.ASK_DEFAULT_PROFILE || "default";; + +function _findEnvProfile() { + if (profileHelper.isEnvProfile()) { + // Only when user set every required parameter in ENV, we will treat profile as ENV + return CONSTANTS.PLACEHOLDER.ENVIRONMENT_VAR.PROFILE_NAME; + } + return null; + } const refreshTokenConfig = { clientId: authorizationController.oauthClient.config.clientId, @@ -33,7 +41,8 @@ const cleanUp = async () => { let nextToken; const skills = []; do { - const res = await client.listSkillsForVendorV1(process.env.ASK_VENDOR_ID, nextToken); + vendorId = profileHelper.resolveVendorId(profile); + const res = await client.listSkillsForVendorV1(vendorId, nextToken); skills.push(...res.skills); nextToken = res.nextToken; diff --git a/scripts/aws-clean-up.js b/scripts/aws-clean-up.js index d5416d5d..3fe06cf6 100644 --- a/scripts/aws-clean-up.js +++ b/scripts/aws-clean-up.js @@ -51,7 +51,7 @@ const cleanUp = async () => { console.error(r.reason); }); } - console.log('done'); }; + cleanUp(); diff --git a/scripts/smapi-docs.js b/scripts/smapi-docs.js index 8a06e19e..3b066f95 100644 --- a/scripts/smapi-docs.js +++ b/scripts/smapi-docs.js @@ -1,10 +1,9 @@ -require('module-alias/register'); const { join } = require('path'); const { readFileSync } = require('fs-extra'); const Mustache = require('mustache'); -const { makeSmapiCommander } = require('@src/commands/smapi/smapi-commander'); -const { SmapiDocs } = require('@src/commands/smapi/smapi-docs'); +const { makeSmapiCommander } = require('../lib/commands/smapi/smapi-commander'); +const { SmapiDocs } = require('../lib/commands/smapi/smapi-docs'); const templateName = process.argv[2] || 'github'; const templatePath = join('lib', 'commands', 'smapi', 'docs-templates', `${templateName}.mustache`); diff --git a/test/fixture/ask-devtools-metrics.schema.json b/test/fixture/ask-devtools-metrics.schema.json index dc6b4314..e0d5cc99 100644 --- a/test/fixture/ask-devtools-metrics.schema.json +++ b/test/fixture/ask-devtools-metrics.schema.json @@ -1,102 +1,102 @@ { - "type" : "object", - "required" : [ "payload" ], - "properties" : { - "payload" : { - "type" : "object", - "title" : "The payload Schema", - "properties" : { - "time_uploaded" : { - "type" : "string", - "title" : "The time_uploaded Schema", - "pattern" : "^(.*)$", - "default" : "" + "type": "object", + "required": ["payload"], + "properties": { + "payload": { + "type": "object", + "title": "The payload Schema", + "properties": { + "time_uploaded": { + "type": "string", + "title": "The time_uploaded Schema", + "pattern": "^(.*)$", + "default": "" }, - "new_user" : { - "type" : "boolean", - "title" : "The new_user Schema", - "default" : false + "new_user": { + "type": "boolean", + "title": "The new_user Schema", + "default": false }, - "time_started" : { - "type" : "string", - "title" : "The time_started Schema", - "pattern" : "^(.*)$", - "default" : "" + "time_started": { + "type": "string", + "title": "The time_started Schema", + "pattern": "^(.*)$", + "default": "" }, - "machine_id" : { - "type" : "string", - "title" : "The machine_id Schema", - "pattern" : "^(.*)$", - "default" : "" + "machine_id": { + "type": "string", + "title": "The machine_id Schema", + "pattern": "^(.*)$", + "default": "" }, - "actions" : { - "type" : "array", - "title" : "The actions Schema", - "items" : { - "type" : "object", - "title" : "The items Schema", - "properties" : { - "result" : { - "type" : "string", - "title" : "The result Schema", - "pattern" : "^(.*)$", - "default" : "" + "actions": { + "type": "array", + "title": "The actions Schema", + "items": { + "type": "object", + "title": "The items Schema", + "properties": { + "result": { + "type": "string", + "title": "The result Schema", + "pattern": "^(.*)$", + "default": "" }, - "start_time" : { - "type" : "string", - "title" : "The start_time Schema", - "pattern" : "^(.*)$", - "default" : "" + "start_time": { + "type": "string", + "title": "The start_time Schema", + "pattern": "^(.*)$", + "default": "" }, - "name" : { - "type" : "string", - "title" : "The name Schema", - "pattern" : "^(.*)$", - "default" : "" + "name": { + "type": "string", + "title": "The name Schema", + "pattern": "^(.*)$", + "default": "" }, - "end_time" : { - "type" : "string", - "title" : "The end_time Schema", - "pattern" : "^(.*)$", - "default" : "" + "end_time": { + "type": "string", + "title": "The end_time Schema", + "pattern": "^(.*)$", + "default": "" }, - "failure_message" : { - "type" : "string", - "title" : "The failure_message schema", - "pattern" : "^(.*)$", - "default" : "" + "failure_message": { + "type": "string", + "title": "The failure_message schema", + "pattern": "^(.*)$", + "default": "" }, - "id" : { - "type" : "string", - "title" : "The id Schema", - "pattern" : "^(.*)$", - "default" : "" + "id": { + "type": "string", + "title": "The id Schema", + "pattern": "^(.*)$", + "default": "" }, - "type" : { - "type" : "string", - "title" : "The type Schema", - "pattern" : "^(.*)$", - "default" : "" + "type": { + "type": "string", + "title": "The type Schema", + "pattern": "^(.*)$", + "default": "" } }, - "required" : [ "id", "name", "result", "start_time", "type" ] + "required": ["id", "name", "result", "start_time", "type"] } }, - "version" : { - "type" : "string", - "title" : "The version Schema", - "pattern" : "^(.*)$", - "default" : "" + "version": { + "type": "string", + "title": "The version Schema", + "pattern": "^(.*)$", + "default": "" }, - "client_id" : { - "type" : "string", - "title" : "The client_id Schema", - "pattern" : "^(.*)$", - "default" : "" + "client_id": { + "type": "string", + "title": "The client_id Schema", + "pattern": "^(.*)$", + "default": "" } }, - "required" : [ "actions", "client_id", "machine_id", "new_user", "time_started", "time_uploaded", "version" ] + "required": ["actions", "client_id", "machine_id", "new_user", "time_started", "time_uploaded", "version"] } }, - "title" : "The Root Schema" -} \ No newline at end of file + "title": "The Root Schema" +} diff --git a/test/fixture/dialog-evaluate/test-project-1/.ask/ask-states.json b/test/fixture/dialog-evaluate/test-project-1/.ask/ask-states.json new file mode 100644 index 00000000..18048d0e --- /dev/null +++ b/test/fixture/dialog-evaluate/test-project-1/.ask/ask-states.json @@ -0,0 +1,8 @@ +{ + "askcliStatesVersion": "2020-03-31", + "profiles": { + "TEST_PROFILE": { + "skillId": "TEST_SKILL_ID" + } + } +} diff --git a/test/fixture/dialog-evaluate/test-project-1/ask-resources.json b/test/fixture/dialog-evaluate/test-project-1/ask-resources.json new file mode 100644 index 00000000..649c901b --- /dev/null +++ b/test/fixture/dialog-evaluate/test-project-1/ask-resources.json @@ -0,0 +1,10 @@ +{ + "askcliResourcesVersion": "2020-03-31", + "profiles": { + "TEST_PROFILE": { + "skillMetadata": { + "src": "./skill-package" + } + } + } +} diff --git a/test/fixture/dialog-evaluate/test-project-1/skill-package/conversations/dialogEight.acdl b/test/fixture/dialog-evaluate/test-project-1/skill-package/conversations/dialogEight.acdl new file mode 100644 index 00000000..a32c092a --- /dev/null +++ b/test/fixture/dialog-evaluate/test-project-1/skill-package/conversations/dialogEight.acdl @@ -0,0 +1,71 @@ +namespace com.dialogEight + +import com.amazon.alexa.ask.conversations.* +import com.amazon.alexa.schema.* +import com.amazon.ask.types.builtins.AMAZON.* +import prompts.* +import slotTypes.* + +// API Action + +action colorFruitNameResponseType colorFruitName(Color colorName, Food fruitName = nothing) + +action fruitNameResultType fruitNameAPI(Food fruitName) + +// UtteraceSets + +InvokeEvent = utterances( + samples = [ + "i want to buy a fruit" + ] +) + +informColorEvent = utterances( + samples = [ + "{colorName}", + "color is {colorName}", + "color {colorName}" + ] +) + +affirmEvent = utterances( + samples = [ + "do it" + ] +) + +// Type + +type colorNameType { + Color colorName +} + +type colorFruitNameResponseType { + Food fruitName + Color colorName +} + +type fruitNameResultType { + Food fruitName + NUMBER price +} + +type responsePayloadType { + fruitNameResultType fruitNameResult +} + +dialog Nothing dialogEight() { + sample { + expect(act = Invoke, event = InvokeEvent) + response( response = request_colorName_apla, + act = Request {arguments = [colorFruitName.arguments.colorName]}) + colorEvent = expect(act = Inform, event = informColorEvent) + response(response = confirm_colorName_apla, act = ConfirmArgs {arguments = [colorFruitName.arguments.colorName]}, + payload = colorNameType { colorName = colorEvent.colorName}) + expect(act = Affirm, event = affirmEvent) + apiResponseOne = colorFruitName(colorName = colorEvent.colorName) + apiResponseTwo = fruitNameAPI(fruitName = apiResponseOne.fruitName) + response(response = success_fruitNameAPI_apla, act = Notify { actionName = fruitNameAPI}, + payload = responsePayloadType { fruitNameResult = apiResponseTwo}) + } +} diff --git a/test/fixture/dialog-evaluate/test-project-1/skill-package/conversations/dialogEleven.acdl b/test/fixture/dialog-evaluate/test-project-1/skill-package/conversations/dialogEleven.acdl new file mode 100644 index 00000000..f3ed4ba6 --- /dev/null +++ b/test/fixture/dialog-evaluate/test-project-1/skill-package/conversations/dialogEleven.acdl @@ -0,0 +1,109 @@ +namespace com.dialogEleven + +import com.amazon.alexa.ask.conversations.* +import com.amazon.alexa.schema.* +import com.amazon.ask.types.builtins.AMAZON.* +import prompts.* +import slotTypes.* + +// API Action + +action fruitNameApiResponseType fruitNameAPI(Color color = nothing, Food fruitName = nothing) + +action colorFruitNameResponseType colorFruitName(Color color) + +// UtteraceSets + +InvokeEventOne = utterances( + samples = [ + "i want to buy a fruit" + ] +) + +InvokeEventTwo = utterances( + samples = [ + "what is the price of the fruit", + "what is the price of fruit" + ] +) + +informColorEvent = utterances( + samples = [ + "color {colorName}", + "color is {colorName}", + "{colorName}" + ] +) + +affirmMultipleColorEvent = utterances( + samples = [ + "do it" + ] +) + +informfruitNameEvent = utterances( + samples = [ + "{fruitName}", + "fruit name is {fruitName}", + "fruit is {fruitName}" + ] +) + +// Type + +type fruitNameApiResponseType { + NUMBER price + Food fruitName +} + +type colorFruitNameResponseType { + Color colorName + Food fruitName +} + +type colorNameType { + Color colorName +} + +type fruitNameType { + Food fruitName +} + +type responsePayloadTypeOne { + colorFruitNameResponseType colorFruitNameResponse +} +type responsePayloadTypeTwo { + fruitNameApiResponseType fruitNameApiResponse +} + + +dialog Nothing dialogEleven() { + + sample { + expect(act = Invoke, event = InvokeEventOne) + response(act = Request { arguments = [ colorFruitName.arguments.color ]}, + response = MultiModalResponse { apla = request_colorName_apla}) + informColorMultipleEventRequest = expect(act = Inform,event = informColorEvent) + response(act = ConfirmAction { actionName = colorFruitName}, + payload = colorNameType { colorName = informColorMultipleEventRequest.colorName}, + response = MultiModalResponse { apla = confirm_colorName_apla}) + expect(act = Affirm, event = affirmMultipleColorEvent) + apiResponseOne = fruitNameAPI(color = informColorMultipleEventRequest.colorName) + ensure(requestArgs = [ RequestArguments {response = MultiModalResponse {apla = request_colorName_apla}, arguments = [fruitNameAPI.arguments.color]}]) + apiResponseTwo = colorFruitName(color = informColorMultipleEventRequest.colorName) + response(act = Notify { success = true, actionName = colorFruitName}, + payload = responsePayloadTypeOne { colorFruitNameResponse = apiResponseTwo}, + response = MultiModalResponse { apla = success_fruitNameAPI_apla}) + } + + sample { + expect(act = Invoke, event = InvokeEventTwo) + response(response = request_fruitName_apla, + act = Request { arguments = [ fruitNameAPI.arguments.fruitName ]}) + fruitNameEvent = expect(act = Inform, event = informfruitNameEvent) + apiResponse = fruitNameAPI(fruitName = fruitNameEvent.fruitName) + response(response = success_fruitNameAPI_apla, act = Notify { actionName = fruitNameAPI}, + payload = responsePayloadTypeTwo { fruitNameApiResponse = apiResponse}) + } + +} diff --git a/test/fixture/dialog-evaluate/test-project-1/skill-package/conversations/dialogFive.acdl b/test/fixture/dialog-evaluate/test-project-1/skill-package/conversations/dialogFive.acdl new file mode 100644 index 00000000..3fc5dbd0 --- /dev/null +++ b/test/fixture/dialog-evaluate/test-project-1/skill-package/conversations/dialogFive.acdl @@ -0,0 +1,87 @@ +namespace com.dialogFive + +import com.amazon.alexa.ask.conversations.* +import com.amazon.alexa.schema.* +import com.amazon.ask.types.builtins.AMAZON.* +import prompts.* +import slotTypes.* + +// API Action + +action favColorSignNameResponseType favColorSign_Name(complexNames name) + +// UtteraceSets + +InvokeEventOne = utterances( + samples = [ + "what is my favourite color" + ] + ) + +InvokeEventTwo = utterances( + samples = [ + "guess the color" + ] +) + +informComplexNameEvent = utterances( + samples = [ + "{name}", + "name is {name}", + "i am {name}" + ] + ) + +affirmFavColorEvent = utterances( + samples = [ + "correct" + ] +) + +// Type + +type favColorSignNameResponseType { + Color colorName + complexNames name + signs sign + } + +type customNameType { + complexNames name +} + +type responsePayloadType { + favColorSignNameResponseType favColorSignNameResponse +} + + dialog Nothing dialogFive() { + + sample { + expect(act = Invoke, event = InvokeEventOne) + response(act = Request {arguments = [favColorSign_Name.arguments.name]}, + response = MultiModalResponse { apla = request_name_apla}) + ComplexNameEvent = expect(act = Inform, event = informComplexNameEvent) + response(response = confirmArgs_complexNames_apla, act = ConfirmArgs {arguments = [ favColorSign_Name.arguments.name ]}, + payload = customNameType {name = ComplexNameEvent.name}) + expect(act = Affirm, event = affirmFavColorEvent) + apiResponse = favColorSign_Name(name = ComplexNameEvent.name) + response(response = success_favColorSign_Name_apla,act = Notify { actionName = favColorSign_Name}, + payload = responsePayloadType { favColorSignNameResponse = apiResponse}) + } + + sample { + expect(act = Invoke,event = InvokeEventTwo) + response(act = Request { arguments = [ favColorSign_Name.arguments.name ]}, + response = MultiModalResponse { apla = request_name_apla}) + ComplexNameEvent = expect(act = Inform,event = informComplexNameEvent) + response(response = confirmAction_complexNames_apla, act = ConfirmAction {actionName = favColorSign_Name}, + payload = customNameType { name = ComplexNameEvent.name}) + expect(act = Affirm,event = affirmFavColorEvent) + apiResponse = favColorSign_Name(name = ComplexNameEvent.name) + response(response = success_favColorSign_Name_apla, act = Notify { actionName = favColorSign_Name}, + payload = responsePayloadType { favColorSignNameResponse = apiResponse}) + } + + } + + diff --git a/test/fixture/dialog-evaluate/test-project-1/skill-package/conversations/dialogFour.acdl b/test/fixture/dialog-evaluate/test-project-1/skill-package/conversations/dialogFour.acdl new file mode 100644 index 00000000..b2c61682 --- /dev/null +++ b/test/fixture/dialog-evaluate/test-project-1/skill-package/conversations/dialogFour.acdl @@ -0,0 +1,84 @@ +namespace com.dialogFour + +import com.amazon.alexa.ask.conversations.* +import com.amazon.alexa.schema.* +import com.amazon.ask.types.builtins.AMAZON.* +import prompts.* +import slotTypes.* + +// API Action + +action fruitNameResultType fruitNameAPI(Food fruitName) + +action fruitNameResultType colorFruitNameAAA(Food fruitName) + +// UtteraceSets + +InvokeEventOne = utterances( + samples = [ + "what is the price of the fruit" + ] +) + +InvokeEventTwo = utterances( + samples = [ + "take me to market place" + ] +) + +informfruitNameEvent = utterances( + samples = [ + "{fruitName}", + "fruit name is {fruitName}", + "fruit is {fruitName}" + ] +) + +informMarketPlaceNameEvent = utterances( + samples = [ + "{fruitName}", + "marketplace name is {fruitName}", + "marketplace is {fruitName}", + "market place is {fruitName}", + "market place name is {fruitName}" + ] +) + +// Type + +type fruitNameType { + Food fruitName +} + +type fruitNameResultType { + Food fruitName + NUMBER price +} + +type responsePayloadType { + fruitNameResultType fruitNameResult +} + +dialog Nothing dialogFour() { + + sample { + expect(act = Invoke, event = InvokeEventOne) + response(response = request_fruitName_apla, + act = Request { arguments = [fruitNameAPI.arguments.fruitName]}) + fruitNameEvent = expect(act = Inform, event = informfruitNameEvent) + apiResponse = fruitNameAPI(fruitName = fruitNameEvent.fruitName) + response(response = success_fruitNameAPI_apla, act = Notify {actionName = fruitNameAPI}, + payload = responsePayloadType {fruitNameResult = apiResponse}) + } + + sample { + expect(act = Invoke,event = InvokeEventTwo) + response(response = request_fruitName_apla, + act = Request {arguments = [colorFruitNameAAA.arguments.fruitName]}) + MarketPlaceInformResponseEvent = expect(act = Inform,event = informMarketPlaceNameEvent) + apiResponse = colorFruitNameAAA(fruitName = MarketPlaceInformResponseEvent.fruitName) + response(response = success_fruitNameAPI_apla, act = Notify { actionName = colorFruitNameAAA}, + payload = responsePayloadType { fruitNameResult = apiResponse}) + } + +} diff --git a/test/fixture/dialog-evaluate/test-project-1/skill-package/conversations/dialogNine.acdl b/test/fixture/dialog-evaluate/test-project-1/skill-package/conversations/dialogNine.acdl new file mode 100644 index 00000000..12bc5e37 --- /dev/null +++ b/test/fixture/dialog-evaluate/test-project-1/skill-package/conversations/dialogNine.acdl @@ -0,0 +1,38 @@ +namespace com.dialogNine + +import com.amazon.alexa.ask.conversations.* +import com.amazon.alexa.schema.* +import com.amazon.ask.types.builtins.AMAZON.* +import prompts.* +import slotTypes.* + +// API Action + +action Nothing delegateToSkill() + +action fruitNameResultType fruitNameAPI(Food fruitName = nothing) + +// UtteraceSets + +InvokeEvent = utterances( + samples = [ + "switch to skill focus dialog manager" + ] +) + +// type + +type fruitNameResultType { + Food fruitName + NUMBER price +} + +dialog Nothing dialogNine() { + + sample { + expect(act = Invoke, event = InvokeEvent) + delegateToSkill() + response(response = notused_apla, act = Notify {actionName = delegateToSkill}, nextAct = nothing) + } + +} \ No newline at end of file diff --git a/test/fixture/dialog-evaluate/test-project-1/skill-package/conversations/dialogOne.acdl b/test/fixture/dialog-evaluate/test-project-1/skill-package/conversations/dialogOne.acdl new file mode 100644 index 00000000..5f116397 --- /dev/null +++ b/test/fixture/dialog-evaluate/test-project-1/skill-package/conversations/dialogOne.acdl @@ -0,0 +1,72 @@ +namespace com.dialogOne + +import com.amazon.alexa.ask.conversations.* +import com.amazon.alexa.schema.* +import com.amazon.ask.types.builtins.AMAZON.* +import prompts.* +import slotTypes.* + +// API Action + +action weatherResultType getWeather(DATE date, US_CITY cityName = nothing, + myCustomCities cityNameChanged = nothing) + +// UtteraceSets + +InvokeEvent = utterances( + samples = [ + "What's the weather {date} in {cityNameChanged}", + "What's the weather {date} in {cityName}", + "what is the weather {date}", + "how is weather" + ] +) + +// Type + +type cityAndDateType { + optional myCustomCities cityNameChanged + optional US_CITY cityName + optional DATE date +} + +type weatherResultType { + optional myCustomCities cityNameChanged + optional US_CITY cityName + NUMBER highTemp + NUMBER lowTemp +} + +type responsePayloadType { + weatherResultType weatherResult +} + +dialog Nothing dialogOne() { + + sample { + weatherRequest = expect(act = Invoke, event = InvokeEvent) + ensure(requestArgs = [ + RequestArguments {arguments = [getWeather.arguments.cityNameChanged], response = request_city_apla}, + RequestArguments {arguments = [getWeather.arguments.cityName], response = request_city_apla}, + RequestArguments {arguments = [getWeather.arguments.date], response = request_date_apla} + ] + ) + apiResponse = getWeather(date = weatherRequest.date, cityName = weatherRequest.cityName) + response(response = success_weather_apla, act = Notify {actionName = getWeather}, + payload = responsePayloadType {weatherResult = apiResponse}) + } + + sample { + weatherRequest = expect(act = Invoke, event = InvokeEvent) + ensure(requestArgs = [ + RequestArguments {arguments = [getWeather.arguments.cityNameChanged], response = request_city_apla}, + RequestArguments {arguments = [getWeather.arguments.cityName], response = request_city_apla}, + RequestArguments {arguments = [getWeather.arguments.date], response = request_date_apla} + ] + ) + apiResponse = getWeather(date = weatherRequest.date, cityNameChanged = weatherRequest.cityNameChanged) + response(response = success_weather_apla, act = Notify {actionName = getWeather}, + payload = responsePayloadType {weatherResult = apiResponse}) + } + +} \ No newline at end of file diff --git a/test/fixture/dialog-evaluate/test-project-1/skill-package/conversations/dialogSeven.acdl b/test/fixture/dialog-evaluate/test-project-1/skill-package/conversations/dialogSeven.acdl new file mode 100644 index 00000000..3646a304 --- /dev/null +++ b/test/fixture/dialog-evaluate/test-project-1/skill-package/conversations/dialogSeven.acdl @@ -0,0 +1,56 @@ +namespace com.dialogSeven + +import com.amazon.alexa.ask.conversations.* +import com.amazon.alexa.schema.* +import com.amazon.ask.types.builtins.AMAZON.* +import prompts.* +import slotTypes.* + +// API Action + +action colorFruitNameResponseType colorFruitName(myColors colorName, Food fruitName = nothing) + +// UtteraceSets + +InvokeEvent = utterances( + samples = [ + "i want to buy a fruit" + ] +) + +informColorEvent = utterances( + samples = [ + "{colorName}", + "color is {colorName}", + "color {colorName}" + ] +) + +// Type + +type colorNameType { + myColors colorName +} + +type colorFruitNameResponseType { + Food fruitName + myColors colorName +} + +type responsePayloadType { + colorFruitNameResponseType colorFruitNameResponse +} + +dialog Nothing dialogSeven() { + + sample { + expect(act = Invoke, event = InvokeEvent) + response( response = request_colorName_apla, + act = Request {arguments = [colorFruitName.arguments.colorName]}) + colorEvent = expect(act = Inform, event = informColorEvent) + apiResponse = colorFruitName(colorName = colorEvent.colorName) + response(response = success_colorFruitAPI_apla, act = Notify {actionName = colorFruitName}, + payload = responsePayloadType {colorFruitNameResponse = apiResponse}) + } + +} \ No newline at end of file diff --git a/test/fixture/dialog-evaluate/test-project-1/skill-package/conversations/dialogSix.acdl b/test/fixture/dialog-evaluate/test-project-1/skill-package/conversations/dialogSix.acdl new file mode 100644 index 00000000..a2252f90 --- /dev/null +++ b/test/fixture/dialog-evaluate/test-project-1/skill-package/conversations/dialogSix.acdl @@ -0,0 +1,64 @@ +namespace com.dialogSix + +import com.amazon.alexa.ask.conversations.* +import com.amazon.alexa.schema.* +import com.amazon.ask.types.builtins.AMAZON.* +import prompts.* +import slotTypes.* + +// API Action + +action colorFruitNameResponseType colorFruitName(Color colorName, Food fruitName = nothing) + +// UtteraceSets + +InvokeEvent = utterances( + samples = [ + "i want to buy a fruit" + ] +) + +informColorEvent = utterances( + samples = [ + "{colorName}", + "color is {colorName}", + "color {colorName}" + ] +) + +affirmEvent = utterances( + samples = [ + "do it" + ] +) +// Type + +type colorNameType { + Color colorName +} + +type colorFruitNameResponseType { + Food fruitName + Color colorName +} + +type responsePayloadType { + colorFruitNameResponseType colorFruitNameResponse +} + +dialog Nothing dialogSix() { + + sample { + expect(act = Invoke, event = InvokeEvent) + response( response = request_colorName_apla, + act = Request {arguments = [colorFruitName.arguments.colorName]}) + colorEvent = expect(act = Inform, event = informColorEvent) + response(response = confirm_colorName_apla, act = ConfirmArgs {arguments = [colorFruitName.arguments.colorName]}, + payload = colorNameType { colorName = colorEvent.colorName}) + expect(act = Affirm, event = affirmEvent) + apiResponse = colorFruitName(colorName = colorEvent.colorName) + response(response = success_colorFruitAPI_apla, act = Notify {actionName = colorFruitName}, + payload = responsePayloadType {colorFruitNameResponse = apiResponse}) + } + +} \ No newline at end of file diff --git a/test/fixture/dialog-evaluate/test-project-1/skill-package/conversations/dialogTen.acdl b/test/fixture/dialog-evaluate/test-project-1/skill-package/conversations/dialogTen.acdl new file mode 100644 index 00000000..f820d47f --- /dev/null +++ b/test/fixture/dialog-evaluate/test-project-1/skill-package/conversations/dialogTen.acdl @@ -0,0 +1,59 @@ +namespace com.dialogTen + +import com.amazon.alexa.ask.conversations.* +import com.amazon.alexa.schema.* +import com.amazon.ask.types.builtins.AMAZON.* +import prompts.* +import slotTypes.* + +// API Action + +action Nothing saveRating(Number rating) + +action Number getNumber() + +// UtteraceSets + +InformRatingEvent = utterances( + samples = [ + "my score is {rating}", + "that was a {rating} conversation", + "i rate you a {rating}", + "{rating}" + ] +) + +getStart = utterances( + samples = [ + "give me a number please" + ] +) + +// Type + +type NumPayload { + Number num +} + +type RatingRequest { + NUMBER rating +} + + +dialog Nothing dialogTen() { + + sample { + expect(act = Invoke, event = getStart) + num = getNumber() + response(response = numericfeedback_apla, act = Notify {actionName = getNumber, success = true}, + nextAct = Offer { actionName = saveRating, arguments = [saveRating.arguments.rating]}, + payload = NumPayload {num = num}) + myRating = expect( act = Invoke,event = InformRatingEvent) + ensure(requestArgs = [RequestArguments {arguments = [saveRating.arguments.rating], + response = rating_apla}]) + saveRating(rating = myRating.rating) + response(response = AlexaConversationsBye, act = Notify { actionName = saveRating,success = true}, + nextAct = Bye {}) + } + +} diff --git a/test/fixture/dialog-evaluate/test-project-1/skill-package/conversations/dialogThree.acdl b/test/fixture/dialog-evaluate/test-project-1/skill-package/conversations/dialogThree.acdl new file mode 100644 index 00000000..5a3ddbb8 --- /dev/null +++ b/test/fixture/dialog-evaluate/test-project-1/skill-package/conversations/dialogThree.acdl @@ -0,0 +1,56 @@ +namespace com.dialogThree + +import com.amazon.alexa.ask.conversations.* +import com.amazon.alexa.schema.* +import com.amazon.ask.types.builtins.AMAZON.* +import prompts.* +import slotTypes.* + +// API Action + +action colorFruitNameResponseType colorFruitName(Color colorName, Food fruitName = nothing) + +// UtteraceSets + +InvokeEvent = utterances( + samples = [ + "i want to buy a fruit" + ] +) + +informColorEvent = utterances( + samples = [ + "{colorName}", + "color is {colorName}", + "color {colorName}" + ] +) + +// Type + +type colorNameType { + Color colorName +} + +type colorFruitNameResponseType { + Food fruitName + Color colorName +} + +type responsePayloadType { + colorFruitNameResponseType colorFruitNameResponse +} + +dialog Nothing dialogThree() { + + sample { + expect(act = Invoke, event = InvokeEvent) + response( response = request_colorName_apla, + act = Request {arguments = [colorFruitName.arguments.colorName]}) + colorEvent = expect(act = Inform, event = informColorEvent) + apiResponse = colorFruitName(colorName = colorEvent.colorName) + response(response = success_colorFruitAPI_apla, act = Notify {actionName = colorFruitName}, + payload = responsePayloadType {colorFruitNameResponse = apiResponse}) + } + +} \ No newline at end of file diff --git a/test/fixture/dialog-evaluate/test-project-1/skill-package/conversations/dialogTwo.acdl b/test/fixture/dialog-evaluate/test-project-1/skill-package/conversations/dialogTwo.acdl new file mode 100644 index 00000000..92bdcd06 --- /dev/null +++ b/test/fixture/dialog-evaluate/test-project-1/skill-package/conversations/dialogTwo.acdl @@ -0,0 +1,80 @@ +namespace com.dialogTwo + +import com.amazon.alexa.ask.conversations.* +import com.amazon.alexa.schema.* +import com.amazon.ask.types.builtins.AMAZON.* +import prompts.* +import slotTypes.* + +// API Action + +action orderStatus cookingAPI(Food foodName, List addOn) + +// UtteraceSets + +InvokeEvent = utterances( + samples = [ + "let us cook" + ] +) + +informlistAddOnsEvent = utterances( + samples = [ + "{addOn}", + "add {addOn}", + "mix {addOn}" + ] +) + +informFoodNameEvent = utterances( + samples = [ + "{foodName}", + "food is {foodName}", + "let us make {foodName}" + ] +) + +affirmCookAPIEvent = utterances( + samples = [ + "ok", + "that is ok", + "ok for sure" + ] +) + +// Type + +type foodNameType { + Food foodName +} + +type addOnType { + List addOn +} + +type responsePayloadType { + orderStatus status +} + +type payloadConfirmActionType { + optional Food foodName + List addOn +} + +dialog Nothing dialogTwo() { + + sample { + expect(act = Invoke, event = InvokeEvent) + response(response = request_listAddOns_apla, act = Request {arguments = [cookingAPI.arguments.addOn]}) + listAddOnsEvent = expect(act = Inform, event = informlistAddOnsEvent) + response(response = request_mainFoodName_apla, act = Request {arguments = [cookingAPI.arguments.foodName]}) + FoodNameEvent = expect(act = Inform, event = informFoodNameEvent) + response(response = confirm_main_addon_list_apla, act = ConfirmAction {actionName = cookingAPI}, + payload = payloadConfirmActionType {foodName = FoodNameEvent.foodName, addOn = listAddOnsEvent.addOn}) + expect(act = Affirm, event = affirmCookAPIEvent) + apiResponse = cookingAPI(foodName = FoodNameEvent.foodName, addOn = listAddOnsEvent.addOn) + response(response = success_cookingAPI_apla, act = Notify {actionName = cookingAPI}, + payload = responsePayloadType {status = apiResponse}) + } + +} \ No newline at end of file diff --git a/test/fixture/dialog-evaluate/test-project-1/skill-package/interactionModels/custom/en-US.json b/test/fixture/dialog-evaluate/test-project-1/skill-package/interactionModels/custom/en-US.json new file mode 100644 index 00000000..f6ddb35d --- /dev/null +++ b/test/fixture/dialog-evaluate/test-project-1/skill-package/interactionModels/custom/en-US.json @@ -0,0 +1,180 @@ +{ + "interactionModel": { + "languageModel": { + "invocationName": "test skill", + "intents": [ + { + "name": "AMAZON.CancelIntent", + "samples": [] + }, + { + "name": "AMAZON.HelpIntent", + "samples": [] + }, + { + "name": "AMAZON.StopIntent", + "samples": [] + }, + { + "name": "GetWeatherIntent", + "samples": ["what is the weather", "how is the weather", "tell me the weather"] + }, + { + "name": "AMAZON.NavigateHomeIntent", + "samples": [] + }, + { + "name": "AMAZON.FallbackIntent", + "samples": [] + } + ], + "types": [ + { + "values": [ + { + "name": { + "value": "flower city" + } + }, + { + "name": { + "value": "temple city" + } + }, + { + "name": { + "value": "ramapuram" + } + }, + { + "name": { + "value": "guindy" + } + }, + { + "name": { + "value": "porur" + } + } + ], + "name": "myCustomCities" + }, + { + "values": [ + { + "name": { + "value": "almonds" + } + }, + { + "name": { + "value": "bread" + } + }, + { + "name": { + "value": "egg" + } + }, + { + "name": { + "value": "sauce" + } + }, + { + "name": { + "value": "jam" + } + }, + { + "name": { + "value": "cheese" + } + } + ], + "name": "Mix" + }, + { + "values": [ + { + "name": { + "value": "failure" + } + }, + { + "name": { + "value": "failed" + } + }, + { + "name": { + "value": "success" + } + } + ], + "name": "orderStatus" + }, + { + "values": [ + { + "name": { + "value": "blue" + } + }, + { + "name": { + "value": "red" + } + }, + { + "name": { + "value": "rocket" + } + } + ], + "name": "myColors" + }, + { + "values": [ + { + "name": { + "value": "satheesh" + } + }, + { + "name": { + "value": "raman" + } + }, + { + "name": { + "value": "yadhu" + } + } + ], + "name": "complexNames" + }, + { + "values": [ + { + "name": { + "value": "cancer" + } + }, + { + "name": { + "value": "scorpio" + } + }, + { + "name": { + "value": "scorpion" + } + } + ], + "name": "signs" + } + ] + } + } +} diff --git a/test/fixture/dialog-evaluate/test-project-1/skill-package/response/display/confirm_city_apl_display/document.json b/test/fixture/dialog-evaluate/test-project-1/skill-package/response/display/confirm_city_apl_display/document.json new file mode 100644 index 00000000..6fea1ff7 --- /dev/null +++ b/test/fixture/dialog-evaluate/test-project-1/skill-package/response/display/confirm_city_apl_display/document.json @@ -0,0 +1,331 @@ +{ + "type": "APL", + "version": "1.1", + "settings": {}, + "theme": "dark", + "import": [ + { + "name": "alexa-layouts", + "version": "1.0.0" + } + ], + "resources": [ + { + "description": "Stock color for the light theme", + "colors": { + "colorTextPrimary": "#151920" + } + }, + { + "description": "Stock color for the dark theme", + "when": "${viewport.theme == 'dark'}", + "colors": { + "colorTextPrimary": "#f0f1ef" + } + }, + { + "description": "Standard font sizes", + "dimensions": { + "textSizeBody": 48, + "textSizePrimary": 27, + "textSizeSecondary": 23, + "textSizeDetails": 20, + "textSizeSecondaryHint": 25 + } + }, + { + "description": "Common spacing values", + "dimensions": { + "spacingThin": 6, + "spacingSmall": 12, + "spacingMedium": 24, + "spacingLarge": 48, + "spacingExtraLarge": 72 + } + }, + { + "description": "Common margins and padding", + "dimensions": { + "marginTop": 40, + "marginLeft": 60, + "marginRight": 60, + "marginBottom": 40 + } + } + ], + "styles": { + "textStyleBase": { + "description": "Base font description; set color", + "values": [ + { + "color": "@colorTextPrimary" + } + ] + }, + "textStyleBase0": { + "description": "Thin version of basic font", + "extend": "textStyleBase", + "values": { + "fontWeight": "100" + } + }, + "textStyleBase1": { + "description": "Light version of basic font", + "extend": "textStyleBase", + "values": { + "fontWeight": "300" + } + }, + "textStyleBase2": { + "description": "Regular version of basic font", + "extend": "textStyleBase", + "values": { + "fontWeight": "500" + } + }, + "mixinBody": { + "values": { + "fontSize": "@textSizeBody" + } + }, + "mixinPrimary": { + "values": { + "fontSize": "@textSizePrimary" + } + }, + "mixinDetails": { + "values": { + "fontSize": "@textSizeDetails" + } + }, + "mixinSecondary": { + "values": { + "fontSize": "@textSizeSecondary" + } + }, + "textStylePrimary": { + "extend": ["textStyleBase1", "mixinPrimary"] + }, + "textStyleSecondary": { + "extend": ["textStyleBase0", "mixinSecondary"] + }, + "textStyleBody": { + "extend": ["textStyleBase1", "mixinBody"] + }, + "textStyleSecondaryHint": { + "values": { + "fontFamily": "Bookerly", + "fontStyle": "italic", + "fontSize": "@textSizeSecondaryHint", + "color": "@colorTextPrimary" + } + }, + "textStyleDetails": { + "extend": ["textStyleBase2", "mixinDetails"] + } + }, + "onMount": [], + "graphics": {}, + "commands": {}, + "layouts": { + "ListTemplate1": { + "parameters": ["backgroundImage", "title", "logo", "hintText", "listData"], + "item": [ + { + "type": "Container", + "width": "100vw", + "height": "100vh", + "direction": "column", + "items": [ + { + "type": "Image", + "source": "${backgroundImage}", + "scale": "best-fill", + "width": "100vw", + "height": "100vh", + "position": "absolute" + }, + { + "type": "AlexaHeader", + "headerTitle": "${title}", + "headerAttributionImage": "${logo}" + }, + { + "type": "Sequence", + "grow": 1, + "height": "80vh", + "scrollDirection": "vertical", + "paddingLeft": "@marginLeft", + "paddingRight": "@marginRight", + "data": "${listData}", + "numbered": true, + "items": [ + { + "type": "VerticalListItem", + "image": "${data.image.sources[0].url}", + "primaryText": "${data.textContent.primaryText.text}", + "secondaryText": "${data.textContent.secondaryText.text}", + "tertiaryText": "${data.textContent.tertiaryText.text}" + } + ] + } + ] + } + ] + }, + "VerticalListItem": { + "parameters": ["primaryText", "secondaryText", "tertiaryText", "image"], + "item": [ + { + "when": "${viewport.shape == 'round'}", + "type": "Container", + "direction": "row", + "height": 200, + "width": 500, + "alignItems": "center", + "items": [ + { + "type": "Text", + "text": "${ordinal}", + "paddingBottom": "20dp", + "color": "white", + "spacing": "5dp" + }, + { + "type": "Image", + "when": "${image}", + "source": "${image}", + "height": 150, + "width": 150, + "spacing": 15, + "scale": "best-fit", + "align": "top" + }, + { + "type": "Container", + "direction": "column", + "spacing": 25, + "items": [ + { + "type": "Text", + "text": "${primaryText}", + "style": "textStyleDetail", + "grow": 1, + "shrink": 1, + "fontWeight": "300", + "maxLines": 1 + }, + { + "type": "Text", + "text": "${secondaryText}", + "style": "textStyleCaption", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + }, + { + "type": "Text", + "text": "${tertiaryText}", + "style": "textStyleDetails", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + } + ] + } + ] + }, + { + "type": "Container", + "direction": "row", + "height": 125, + "width": 800, + "alignItems": "center", + "items": [ + { + "type": "Text", + "text": "${ordinal}", + "paddingBottom": "20dp", + "color": "white", + "spacing": "5dp" + }, + { + "type": "Image", + "when": "${image}", + "source": "${image}", + "height": 100, + "width": 100, + "align": "top", + "spacing": 50, + "scale": "best-fit" + }, + { + "type": "Container", + "spacing": 30, + "direction": "column", + "items": [ + { + "type": "Text", + "text": "${primaryText}", + "style": "textStyleBody", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + }, + { + "type": "Text", + "text": "${secondaryText}", + "style": "textStyleDetails", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + } + ] + }, + { + "type": "Text", + "text": "${tertiaryText}", + "style": "textStyleBody", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "textAlign": "right", + "maxLines": 1 + } + ] + } + ] + } + }, + "mainTemplate": { + "parameters": ["payload"], + "item": [ + { + "type": "Container", + "id": "BookCabSimpleDialogAPL", + "items": [ + { + "type": "TouchWrapper", + "onPress": { + "type": "SendEvent", + "arguments": ["delegateToColtraneOld"] + }, + "item": { + "type": "Text", + "id": "BookCabSimpleDialogAPL", + "paddingTop": "100", + "paddingLeft": "100", + "color": "green", + "size": 50, + "text": "which city ?" + } + } + ] + } + ] + } +} diff --git a/test/fixture/dialog-evaluate/test-project-1/skill-package/response/display/confirm_date_apl_display/document.json b/test/fixture/dialog-evaluate/test-project-1/skill-package/response/display/confirm_date_apl_display/document.json new file mode 100644 index 00000000..d41ea236 --- /dev/null +++ b/test/fixture/dialog-evaluate/test-project-1/skill-package/response/display/confirm_date_apl_display/document.json @@ -0,0 +1,331 @@ +{ + "type": "APL", + "version": "1.1", + "settings": {}, + "theme": "dark", + "import": [ + { + "name": "alexa-layouts", + "version": "1.0.0" + } + ], + "resources": [ + { + "description": "Stock color for the light theme", + "colors": { + "colorTextPrimary": "#151920" + } + }, + { + "description": "Stock color for the dark theme", + "when": "${viewport.theme == 'dark'}", + "colors": { + "colorTextPrimary": "#f0f1ef" + } + }, + { + "description": "Standard font sizes", + "dimensions": { + "textSizeBody": 48, + "textSizePrimary": 27, + "textSizeSecondary": 23, + "textSizeDetails": 20, + "textSizeSecondaryHint": 25 + } + }, + { + "description": "Common spacing values", + "dimensions": { + "spacingThin": 6, + "spacingSmall": 12, + "spacingMedium": 24, + "spacingLarge": 48, + "spacingExtraLarge": 72 + } + }, + { + "description": "Common margins and padding", + "dimensions": { + "marginTop": 40, + "marginLeft": 60, + "marginRight": 60, + "marginBottom": 40 + } + } + ], + "styles": { + "textStyleBase": { + "description": "Base font description; set color", + "values": [ + { + "color": "@colorTextPrimary" + } + ] + }, + "textStyleBase0": { + "description": "Thin version of basic font", + "extend": "textStyleBase", + "values": { + "fontWeight": "100" + } + }, + "textStyleBase1": { + "description": "Light version of basic font", + "extend": "textStyleBase", + "values": { + "fontWeight": "300" + } + }, + "textStyleBase2": { + "description": "Regular version of basic font", + "extend": "textStyleBase", + "values": { + "fontWeight": "500" + } + }, + "mixinBody": { + "values": { + "fontSize": "@textSizeBody" + } + }, + "mixinPrimary": { + "values": { + "fontSize": "@textSizePrimary" + } + }, + "mixinDetails": { + "values": { + "fontSize": "@textSizeDetails" + } + }, + "mixinSecondary": { + "values": { + "fontSize": "@textSizeSecondary" + } + }, + "textStylePrimary": { + "extend": ["textStyleBase1", "mixinPrimary"] + }, + "textStyleSecondary": { + "extend": ["textStyleBase0", "mixinSecondary"] + }, + "textStyleBody": { + "extend": ["textStyleBase1", "mixinBody"] + }, + "textStyleSecondaryHint": { + "values": { + "fontFamily": "Bookerly", + "fontStyle": "italic", + "fontSize": "@textSizeSecondaryHint", + "color": "@colorTextPrimary" + } + }, + "textStyleDetails": { + "extend": ["textStyleBase2", "mixinDetails"] + } + }, + "onMount": [], + "graphics": {}, + "commands": {}, + "layouts": { + "ListTemplate1": { + "parameters": ["backgroundImage", "title", "logo", "hintText", "listData"], + "item": [ + { + "type": "Container", + "width": "100vw", + "height": "100vh", + "direction": "column", + "items": [ + { + "type": "Image", + "source": "${backgroundImage}", + "scale": "best-fill", + "width": "100vw", + "height": "100vh", + "position": "absolute" + }, + { + "type": "AlexaHeader", + "headerTitle": "${title}", + "headerAttributionImage": "${logo}" + }, + { + "type": "Sequence", + "grow": 1, + "height": "80vh", + "scrollDirection": "vertical", + "paddingLeft": "@marginLeft", + "paddingRight": "@marginRight", + "data": "${listData}", + "numbered": true, + "items": [ + { + "type": "VerticalListItem", + "image": "${data.image.sources[0].url}", + "primaryText": "${data.textContent.primaryText.text}", + "secondaryText": "${data.textContent.secondaryText.text}", + "tertiaryText": "${data.textContent.tertiaryText.text}" + } + ] + } + ] + } + ] + }, + "VerticalListItem": { + "parameters": ["primaryText", "secondaryText", "tertiaryText", "image"], + "item": [ + { + "when": "${viewport.shape == 'round'}", + "type": "Container", + "direction": "row", + "height": 200, + "width": 500, + "alignItems": "center", + "items": [ + { + "type": "Text", + "text": "${ordinal}", + "paddingBottom": "20dp", + "color": "white", + "spacing": "5dp" + }, + { + "type": "Image", + "when": "${image}", + "source": "${image}", + "height": 150, + "width": 150, + "spacing": 15, + "scale": "best-fit", + "align": "top" + }, + { + "type": "Container", + "direction": "column", + "spacing": 25, + "items": [ + { + "type": "Text", + "text": "${primaryText}", + "style": "textStyleDetail", + "grow": 1, + "shrink": 1, + "fontWeight": "300", + "maxLines": 1 + }, + { + "type": "Text", + "text": "${secondaryText}", + "style": "textStyleCaption", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + }, + { + "type": "Text", + "text": "${tertiaryText}", + "style": "textStyleDetails", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + } + ] + } + ] + }, + { + "type": "Container", + "direction": "row", + "height": 125, + "width": 800, + "alignItems": "center", + "items": [ + { + "type": "Text", + "text": "${ordinal}", + "paddingBottom": "20dp", + "color": "white", + "spacing": "5dp" + }, + { + "type": "Image", + "when": "${image}", + "source": "${image}", + "height": 100, + "width": 100, + "align": "top", + "spacing": 50, + "scale": "best-fit" + }, + { + "type": "Container", + "spacing": 30, + "direction": "column", + "items": [ + { + "type": "Text", + "text": "${primaryText}", + "style": "textStyleBody", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + }, + { + "type": "Text", + "text": "${secondaryText}", + "style": "textStyleDetails", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + } + ] + }, + { + "type": "Text", + "text": "${tertiaryText}", + "style": "textStyleBody", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "textAlign": "right", + "maxLines": 1 + } + ] + } + ] + } + }, + "mainTemplate": { + "parameters": ["payload"], + "item": [ + { + "type": "Container", + "id": "BookCabSimpleDialogAPL", + "items": [ + { + "type": "TouchWrapper", + "onPress": { + "type": "SendEvent", + "arguments": ["delegateToColtraneOld"] + }, + "item": { + "type": "Text", + "id": "BookCabSimpleDialogAPL", + "paddingTop": "100", + "paddingLeft": "100", + "color": "green", + "size": 50, + "text": "which date ?" + } + } + ] + } + ] + } +} diff --git a/test/fixture/dialog-evaluate/test-project-1/skill-package/response/display/confirm_weather_apla_display/document.json b/test/fixture/dialog-evaluate/test-project-1/skill-package/response/display/confirm_weather_apla_display/document.json new file mode 100644 index 00000000..3bcc0e4a --- /dev/null +++ b/test/fixture/dialog-evaluate/test-project-1/skill-package/response/display/confirm_weather_apla_display/document.json @@ -0,0 +1,379 @@ +{ + "type": "APL", + "version": "1.1", + "settings": {}, + "theme": "dark", + "import": [ + { + "name": "alexa-layouts", + "version": "1.0.0" + } + ], + "resources": [ + { + "description": "Stock color for the light theme", + "colors": { + "colorTextPrimary": "#151920" + } + }, + { + "description": "Stock color for the dark theme", + "when": "${viewport.theme == 'dark'}", + "colors": { + "colorTextPrimary": "#f0f1ef" + } + }, + { + "description": "Standard font sizes", + "dimensions": { + "textSizeBody": 48, + "textSizePrimary": 27, + "textSizeSecondary": 23, + "textSizeDetails": 20, + "textSizeSecondaryHint": 25 + } + }, + { + "description": "Common spacing values", + "dimensions": { + "spacingThin": 6, + "spacingSmall": 12, + "spacingMedium": 24, + "spacingLarge": 48, + "spacingExtraLarge": 72 + } + }, + { + "description": "Common margins and padding", + "dimensions": { + "marginTop": 40, + "marginLeft": 60, + "marginRight": 60, + "marginBottom": 40 + } + } + ], + "styles": { + "textStyleBase": { + "description": "Base font description; set color", + "values": [ + { + "color": "@colorTextPrimary" + } + ] + }, + "textStyleBase0": { + "description": "Thin version of basic font", + "extend": "textStyleBase", + "values": { + "fontWeight": "100" + } + }, + "textStyleBase1": { + "description": "Light version of basic font", + "extend": "textStyleBase", + "values": { + "fontWeight": "300" + } + }, + "textStyleBase2": { + "description": "Regular version of basic font", + "extend": "textStyleBase", + "values": { + "fontWeight": "500" + } + }, + "mixinBody": { + "values": { + "fontSize": "@textSizeBody" + } + }, + "mixinPrimary": { + "values": { + "fontSize": "@textSizePrimary" + } + }, + "mixinDetails": { + "values": { + "fontSize": "@textSizeDetails" + } + }, + "mixinSecondary": { + "values": { + "fontSize": "@textSizeSecondary" + } + }, + "textStylePrimary": { + "extend": ["textStyleBase1", "mixinPrimary"] + }, + "textStyleSecondary": { + "extend": ["textStyleBase0", "mixinSecondary"] + }, + "textStyleBody": { + "extend": ["textStyleBase1", "mixinBody"] + }, + "textStyleSecondaryHint": { + "values": { + "fontFamily": "Bookerly", + "fontStyle": "italic", + "fontSize": "@textSizeSecondaryHint", + "color": "@colorTextPrimary" + } + }, + "textStyleDetails": { + "extend": ["textStyleBase2", "mixinDetails"] + } + }, + "onMount": [], + "graphics": {}, + "commands": {}, + "layouts": { + "ListTemplate1": { + "parameters": ["backgroundImage", "title", "logo", "hintText", "listData"], + "item": [ + { + "type": "Container", + "width": "100vw", + "height": "100vh", + "direction": "column", + "items": [ + { + "type": "Image", + "source": "${backgroundImage}", + "scale": "best-fill", + "width": "100vw", + "height": "100vh", + "position": "absolute" + }, + { + "type": "AlexaHeader", + "headerTitle": "${title}", + "headerAttributionImage": "${logo}" + }, + { + "type": "Sequence", + "grow": 1, + "height": "80vh", + "scrollDirection": "vertical", + "paddingLeft": "@marginLeft", + "paddingRight": "@marginRight", + "data": "${listData}", + "numbered": true, + "items": [ + { + "type": "VerticalListItem", + "image": "${data.image.sources[0].url}", + "primaryText": "${data.textContent.primaryText.text}", + "secondaryText": "${data.textContent.secondaryText.text}", + "tertiaryText": "${data.textContent.tertiaryText.text}" + } + ] + } + ] + } + ] + }, + "VerticalListItem": { + "parameters": ["primaryText", "secondaryText", "tertiaryText", "image"], + "item": [ + { + "when": "${viewport.shape == 'round'}", + "type": "Container", + "direction": "row", + "height": 200, + "width": 500, + "alignItems": "center", + "items": [ + { + "type": "Text", + "text": "${ordinal}", + "paddingBottom": "20dp", + "color": "white", + "spacing": "5dp" + }, + { + "type": "Image", + "when": "${image}", + "source": "${image}", + "height": 150, + "width": 150, + "spacing": 15, + "scale": "best-fit", + "align": "top" + }, + { + "type": "Container", + "direction": "column", + "spacing": 25, + "items": [ + { + "type": "Text", + "text": "${primaryText}", + "style": "textStyleDetail", + "grow": 1, + "shrink": 1, + "fontWeight": "300", + "maxLines": 1 + }, + { + "type": "Text", + "text": "${secondaryText}", + "style": "textStyleCaption", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + }, + { + "type": "Text", + "text": "${tertiaryText}", + "style": "textStyleDetails", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + } + ] + } + ] + }, + { + "type": "Container", + "direction": "row", + "height": 125, + "width": 800, + "alignItems": "center", + "items": [ + { + "type": "Text", + "text": "${ordinal}", + "paddingBottom": "20dp", + "color": "white", + "spacing": "5dp" + }, + { + "type": "Image", + "when": "${image}", + "source": "${image}", + "height": 100, + "width": 100, + "align": "top", + "spacing": 50, + "scale": "best-fit" + }, + { + "type": "Container", + "spacing": 30, + "direction": "column", + "items": [ + { + "type": "Text", + "text": "${primaryText}", + "style": "textStyleBody", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + }, + { + "type": "Text", + "text": "${secondaryText}", + "style": "textStyleDetails", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + } + ] + }, + { + "type": "Text", + "text": "${tertiaryText}", + "style": "textStyleBody", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "textAlign": "right", + "maxLines": 1 + } + ] + } + ] + } + }, + "mainTemplate": { + "parameters": ["payload"], + "item": [ + { + "type": "Container", + "id": "BookCabSimpleDialogAPL", + "items": [ + { + "type": "TouchWrapper", + "onPress": { + "type": "SendEvent", + "arguments": ["delegateToSkillNew"] + }, + "item": { + "type": "Text", + "id": "BookCabSimpleDialogAPL", + "paddingTop": "100", + "paddingLeft": "100", + "color": "green", + "size": 50, + "text": "delegateToSkillNew" + } + }, + { + "type": "TouchWrapper", + "onPress": { + "type": "SendEvent", + "arguments": ["delegateToSkillOld"] + }, + "item": { + "type": "Text", + "id": "BookCabSimpleDialogAPL", + "paddingTop": "100", + "paddingLeft": "100", + "color": "green", + "size": 50, + "text": "delegateToSkillOld" + } + }, + { + "type": "TouchWrapper", + "onPress": { + "type": "SendEvent", + "arguments": ["delegateToColtraneNew"] + }, + "item": { + "type": "Text", + "id": "BookCabSimpleDialogAPL", + "paddingTop": "100", + "paddingLeft": "100", + "color": "green", + "size": 50, + "text": "delegateToColtraneNew" + } + }, + { + "type": "TouchWrapper", + "onPress": { + "type": "SendEvent", + "arguments": ["delegateToColtraneOld"] + }, + "item": { + "type": "Text", + "id": "BookCabSimpleDialogAPL", + "paddingTop": "100", + "paddingLeft": "100", + "color": "green", + "size": 50, + "text": "delegateToColtraneOld" + } + } + ] + } + ] + } +} diff --git a/test/fixture/dialog-evaluate/test-project-1/skill-package/response/display/request_city_apl_display/document.json b/test/fixture/dialog-evaluate/test-project-1/skill-package/response/display/request_city_apl_display/document.json new file mode 100644 index 00000000..6fea1ff7 --- /dev/null +++ b/test/fixture/dialog-evaluate/test-project-1/skill-package/response/display/request_city_apl_display/document.json @@ -0,0 +1,331 @@ +{ + "type": "APL", + "version": "1.1", + "settings": {}, + "theme": "dark", + "import": [ + { + "name": "alexa-layouts", + "version": "1.0.0" + } + ], + "resources": [ + { + "description": "Stock color for the light theme", + "colors": { + "colorTextPrimary": "#151920" + } + }, + { + "description": "Stock color for the dark theme", + "when": "${viewport.theme == 'dark'}", + "colors": { + "colorTextPrimary": "#f0f1ef" + } + }, + { + "description": "Standard font sizes", + "dimensions": { + "textSizeBody": 48, + "textSizePrimary": 27, + "textSizeSecondary": 23, + "textSizeDetails": 20, + "textSizeSecondaryHint": 25 + } + }, + { + "description": "Common spacing values", + "dimensions": { + "spacingThin": 6, + "spacingSmall": 12, + "spacingMedium": 24, + "spacingLarge": 48, + "spacingExtraLarge": 72 + } + }, + { + "description": "Common margins and padding", + "dimensions": { + "marginTop": 40, + "marginLeft": 60, + "marginRight": 60, + "marginBottom": 40 + } + } + ], + "styles": { + "textStyleBase": { + "description": "Base font description; set color", + "values": [ + { + "color": "@colorTextPrimary" + } + ] + }, + "textStyleBase0": { + "description": "Thin version of basic font", + "extend": "textStyleBase", + "values": { + "fontWeight": "100" + } + }, + "textStyleBase1": { + "description": "Light version of basic font", + "extend": "textStyleBase", + "values": { + "fontWeight": "300" + } + }, + "textStyleBase2": { + "description": "Regular version of basic font", + "extend": "textStyleBase", + "values": { + "fontWeight": "500" + } + }, + "mixinBody": { + "values": { + "fontSize": "@textSizeBody" + } + }, + "mixinPrimary": { + "values": { + "fontSize": "@textSizePrimary" + } + }, + "mixinDetails": { + "values": { + "fontSize": "@textSizeDetails" + } + }, + "mixinSecondary": { + "values": { + "fontSize": "@textSizeSecondary" + } + }, + "textStylePrimary": { + "extend": ["textStyleBase1", "mixinPrimary"] + }, + "textStyleSecondary": { + "extend": ["textStyleBase0", "mixinSecondary"] + }, + "textStyleBody": { + "extend": ["textStyleBase1", "mixinBody"] + }, + "textStyleSecondaryHint": { + "values": { + "fontFamily": "Bookerly", + "fontStyle": "italic", + "fontSize": "@textSizeSecondaryHint", + "color": "@colorTextPrimary" + } + }, + "textStyleDetails": { + "extend": ["textStyleBase2", "mixinDetails"] + } + }, + "onMount": [], + "graphics": {}, + "commands": {}, + "layouts": { + "ListTemplate1": { + "parameters": ["backgroundImage", "title", "logo", "hintText", "listData"], + "item": [ + { + "type": "Container", + "width": "100vw", + "height": "100vh", + "direction": "column", + "items": [ + { + "type": "Image", + "source": "${backgroundImage}", + "scale": "best-fill", + "width": "100vw", + "height": "100vh", + "position": "absolute" + }, + { + "type": "AlexaHeader", + "headerTitle": "${title}", + "headerAttributionImage": "${logo}" + }, + { + "type": "Sequence", + "grow": 1, + "height": "80vh", + "scrollDirection": "vertical", + "paddingLeft": "@marginLeft", + "paddingRight": "@marginRight", + "data": "${listData}", + "numbered": true, + "items": [ + { + "type": "VerticalListItem", + "image": "${data.image.sources[0].url}", + "primaryText": "${data.textContent.primaryText.text}", + "secondaryText": "${data.textContent.secondaryText.text}", + "tertiaryText": "${data.textContent.tertiaryText.text}" + } + ] + } + ] + } + ] + }, + "VerticalListItem": { + "parameters": ["primaryText", "secondaryText", "tertiaryText", "image"], + "item": [ + { + "when": "${viewport.shape == 'round'}", + "type": "Container", + "direction": "row", + "height": 200, + "width": 500, + "alignItems": "center", + "items": [ + { + "type": "Text", + "text": "${ordinal}", + "paddingBottom": "20dp", + "color": "white", + "spacing": "5dp" + }, + { + "type": "Image", + "when": "${image}", + "source": "${image}", + "height": 150, + "width": 150, + "spacing": 15, + "scale": "best-fit", + "align": "top" + }, + { + "type": "Container", + "direction": "column", + "spacing": 25, + "items": [ + { + "type": "Text", + "text": "${primaryText}", + "style": "textStyleDetail", + "grow": 1, + "shrink": 1, + "fontWeight": "300", + "maxLines": 1 + }, + { + "type": "Text", + "text": "${secondaryText}", + "style": "textStyleCaption", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + }, + { + "type": "Text", + "text": "${tertiaryText}", + "style": "textStyleDetails", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + } + ] + } + ] + }, + { + "type": "Container", + "direction": "row", + "height": 125, + "width": 800, + "alignItems": "center", + "items": [ + { + "type": "Text", + "text": "${ordinal}", + "paddingBottom": "20dp", + "color": "white", + "spacing": "5dp" + }, + { + "type": "Image", + "when": "${image}", + "source": "${image}", + "height": 100, + "width": 100, + "align": "top", + "spacing": 50, + "scale": "best-fit" + }, + { + "type": "Container", + "spacing": 30, + "direction": "column", + "items": [ + { + "type": "Text", + "text": "${primaryText}", + "style": "textStyleBody", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + }, + { + "type": "Text", + "text": "${secondaryText}", + "style": "textStyleDetails", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + } + ] + }, + { + "type": "Text", + "text": "${tertiaryText}", + "style": "textStyleBody", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "textAlign": "right", + "maxLines": 1 + } + ] + } + ] + } + }, + "mainTemplate": { + "parameters": ["payload"], + "item": [ + { + "type": "Container", + "id": "BookCabSimpleDialogAPL", + "items": [ + { + "type": "TouchWrapper", + "onPress": { + "type": "SendEvent", + "arguments": ["delegateToColtraneOld"] + }, + "item": { + "type": "Text", + "id": "BookCabSimpleDialogAPL", + "paddingTop": "100", + "paddingLeft": "100", + "color": "green", + "size": 50, + "text": "which city ?" + } + } + ] + } + ] + } +} diff --git a/test/fixture/dialog-evaluate/test-project-1/skill-package/response/display/request_date_apl_display/document.json b/test/fixture/dialog-evaluate/test-project-1/skill-package/response/display/request_date_apl_display/document.json new file mode 100644 index 00000000..d41ea236 --- /dev/null +++ b/test/fixture/dialog-evaluate/test-project-1/skill-package/response/display/request_date_apl_display/document.json @@ -0,0 +1,331 @@ +{ + "type": "APL", + "version": "1.1", + "settings": {}, + "theme": "dark", + "import": [ + { + "name": "alexa-layouts", + "version": "1.0.0" + } + ], + "resources": [ + { + "description": "Stock color for the light theme", + "colors": { + "colorTextPrimary": "#151920" + } + }, + { + "description": "Stock color for the dark theme", + "when": "${viewport.theme == 'dark'}", + "colors": { + "colorTextPrimary": "#f0f1ef" + } + }, + { + "description": "Standard font sizes", + "dimensions": { + "textSizeBody": 48, + "textSizePrimary": 27, + "textSizeSecondary": 23, + "textSizeDetails": 20, + "textSizeSecondaryHint": 25 + } + }, + { + "description": "Common spacing values", + "dimensions": { + "spacingThin": 6, + "spacingSmall": 12, + "spacingMedium": 24, + "spacingLarge": 48, + "spacingExtraLarge": 72 + } + }, + { + "description": "Common margins and padding", + "dimensions": { + "marginTop": 40, + "marginLeft": 60, + "marginRight": 60, + "marginBottom": 40 + } + } + ], + "styles": { + "textStyleBase": { + "description": "Base font description; set color", + "values": [ + { + "color": "@colorTextPrimary" + } + ] + }, + "textStyleBase0": { + "description": "Thin version of basic font", + "extend": "textStyleBase", + "values": { + "fontWeight": "100" + } + }, + "textStyleBase1": { + "description": "Light version of basic font", + "extend": "textStyleBase", + "values": { + "fontWeight": "300" + } + }, + "textStyleBase2": { + "description": "Regular version of basic font", + "extend": "textStyleBase", + "values": { + "fontWeight": "500" + } + }, + "mixinBody": { + "values": { + "fontSize": "@textSizeBody" + } + }, + "mixinPrimary": { + "values": { + "fontSize": "@textSizePrimary" + } + }, + "mixinDetails": { + "values": { + "fontSize": "@textSizeDetails" + } + }, + "mixinSecondary": { + "values": { + "fontSize": "@textSizeSecondary" + } + }, + "textStylePrimary": { + "extend": ["textStyleBase1", "mixinPrimary"] + }, + "textStyleSecondary": { + "extend": ["textStyleBase0", "mixinSecondary"] + }, + "textStyleBody": { + "extend": ["textStyleBase1", "mixinBody"] + }, + "textStyleSecondaryHint": { + "values": { + "fontFamily": "Bookerly", + "fontStyle": "italic", + "fontSize": "@textSizeSecondaryHint", + "color": "@colorTextPrimary" + } + }, + "textStyleDetails": { + "extend": ["textStyleBase2", "mixinDetails"] + } + }, + "onMount": [], + "graphics": {}, + "commands": {}, + "layouts": { + "ListTemplate1": { + "parameters": ["backgroundImage", "title", "logo", "hintText", "listData"], + "item": [ + { + "type": "Container", + "width": "100vw", + "height": "100vh", + "direction": "column", + "items": [ + { + "type": "Image", + "source": "${backgroundImage}", + "scale": "best-fill", + "width": "100vw", + "height": "100vh", + "position": "absolute" + }, + { + "type": "AlexaHeader", + "headerTitle": "${title}", + "headerAttributionImage": "${logo}" + }, + { + "type": "Sequence", + "grow": 1, + "height": "80vh", + "scrollDirection": "vertical", + "paddingLeft": "@marginLeft", + "paddingRight": "@marginRight", + "data": "${listData}", + "numbered": true, + "items": [ + { + "type": "VerticalListItem", + "image": "${data.image.sources[0].url}", + "primaryText": "${data.textContent.primaryText.text}", + "secondaryText": "${data.textContent.secondaryText.text}", + "tertiaryText": "${data.textContent.tertiaryText.text}" + } + ] + } + ] + } + ] + }, + "VerticalListItem": { + "parameters": ["primaryText", "secondaryText", "tertiaryText", "image"], + "item": [ + { + "when": "${viewport.shape == 'round'}", + "type": "Container", + "direction": "row", + "height": 200, + "width": 500, + "alignItems": "center", + "items": [ + { + "type": "Text", + "text": "${ordinal}", + "paddingBottom": "20dp", + "color": "white", + "spacing": "5dp" + }, + { + "type": "Image", + "when": "${image}", + "source": "${image}", + "height": 150, + "width": 150, + "spacing": 15, + "scale": "best-fit", + "align": "top" + }, + { + "type": "Container", + "direction": "column", + "spacing": 25, + "items": [ + { + "type": "Text", + "text": "${primaryText}", + "style": "textStyleDetail", + "grow": 1, + "shrink": 1, + "fontWeight": "300", + "maxLines": 1 + }, + { + "type": "Text", + "text": "${secondaryText}", + "style": "textStyleCaption", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + }, + { + "type": "Text", + "text": "${tertiaryText}", + "style": "textStyleDetails", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + } + ] + } + ] + }, + { + "type": "Container", + "direction": "row", + "height": 125, + "width": 800, + "alignItems": "center", + "items": [ + { + "type": "Text", + "text": "${ordinal}", + "paddingBottom": "20dp", + "color": "white", + "spacing": "5dp" + }, + { + "type": "Image", + "when": "${image}", + "source": "${image}", + "height": 100, + "width": 100, + "align": "top", + "spacing": 50, + "scale": "best-fit" + }, + { + "type": "Container", + "spacing": 30, + "direction": "column", + "items": [ + { + "type": "Text", + "text": "${primaryText}", + "style": "textStyleBody", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + }, + { + "type": "Text", + "text": "${secondaryText}", + "style": "textStyleDetails", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + } + ] + }, + { + "type": "Text", + "text": "${tertiaryText}", + "style": "textStyleBody", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "textAlign": "right", + "maxLines": 1 + } + ] + } + ] + } + }, + "mainTemplate": { + "parameters": ["payload"], + "item": [ + { + "type": "Container", + "id": "BookCabSimpleDialogAPL", + "items": [ + { + "type": "TouchWrapper", + "onPress": { + "type": "SendEvent", + "arguments": ["delegateToColtraneOld"] + }, + "item": { + "type": "Text", + "id": "BookCabSimpleDialogAPL", + "paddingTop": "100", + "paddingLeft": "100", + "color": "green", + "size": 50, + "text": "which date ?" + } + } + ] + } + ] + } +} diff --git a/test/fixture/dialog-evaluate/test-project-1/skill-package/response/display/weather_success_apl_display/document.json b/test/fixture/dialog-evaluate/test-project-1/skill-package/response/display/weather_success_apl_display/document.json new file mode 100644 index 00000000..3bcc0e4a --- /dev/null +++ b/test/fixture/dialog-evaluate/test-project-1/skill-package/response/display/weather_success_apl_display/document.json @@ -0,0 +1,379 @@ +{ + "type": "APL", + "version": "1.1", + "settings": {}, + "theme": "dark", + "import": [ + { + "name": "alexa-layouts", + "version": "1.0.0" + } + ], + "resources": [ + { + "description": "Stock color for the light theme", + "colors": { + "colorTextPrimary": "#151920" + } + }, + { + "description": "Stock color for the dark theme", + "when": "${viewport.theme == 'dark'}", + "colors": { + "colorTextPrimary": "#f0f1ef" + } + }, + { + "description": "Standard font sizes", + "dimensions": { + "textSizeBody": 48, + "textSizePrimary": 27, + "textSizeSecondary": 23, + "textSizeDetails": 20, + "textSizeSecondaryHint": 25 + } + }, + { + "description": "Common spacing values", + "dimensions": { + "spacingThin": 6, + "spacingSmall": 12, + "spacingMedium": 24, + "spacingLarge": 48, + "spacingExtraLarge": 72 + } + }, + { + "description": "Common margins and padding", + "dimensions": { + "marginTop": 40, + "marginLeft": 60, + "marginRight": 60, + "marginBottom": 40 + } + } + ], + "styles": { + "textStyleBase": { + "description": "Base font description; set color", + "values": [ + { + "color": "@colorTextPrimary" + } + ] + }, + "textStyleBase0": { + "description": "Thin version of basic font", + "extend": "textStyleBase", + "values": { + "fontWeight": "100" + } + }, + "textStyleBase1": { + "description": "Light version of basic font", + "extend": "textStyleBase", + "values": { + "fontWeight": "300" + } + }, + "textStyleBase2": { + "description": "Regular version of basic font", + "extend": "textStyleBase", + "values": { + "fontWeight": "500" + } + }, + "mixinBody": { + "values": { + "fontSize": "@textSizeBody" + } + }, + "mixinPrimary": { + "values": { + "fontSize": "@textSizePrimary" + } + }, + "mixinDetails": { + "values": { + "fontSize": "@textSizeDetails" + } + }, + "mixinSecondary": { + "values": { + "fontSize": "@textSizeSecondary" + } + }, + "textStylePrimary": { + "extend": ["textStyleBase1", "mixinPrimary"] + }, + "textStyleSecondary": { + "extend": ["textStyleBase0", "mixinSecondary"] + }, + "textStyleBody": { + "extend": ["textStyleBase1", "mixinBody"] + }, + "textStyleSecondaryHint": { + "values": { + "fontFamily": "Bookerly", + "fontStyle": "italic", + "fontSize": "@textSizeSecondaryHint", + "color": "@colorTextPrimary" + } + }, + "textStyleDetails": { + "extend": ["textStyleBase2", "mixinDetails"] + } + }, + "onMount": [], + "graphics": {}, + "commands": {}, + "layouts": { + "ListTemplate1": { + "parameters": ["backgroundImage", "title", "logo", "hintText", "listData"], + "item": [ + { + "type": "Container", + "width": "100vw", + "height": "100vh", + "direction": "column", + "items": [ + { + "type": "Image", + "source": "${backgroundImage}", + "scale": "best-fill", + "width": "100vw", + "height": "100vh", + "position": "absolute" + }, + { + "type": "AlexaHeader", + "headerTitle": "${title}", + "headerAttributionImage": "${logo}" + }, + { + "type": "Sequence", + "grow": 1, + "height": "80vh", + "scrollDirection": "vertical", + "paddingLeft": "@marginLeft", + "paddingRight": "@marginRight", + "data": "${listData}", + "numbered": true, + "items": [ + { + "type": "VerticalListItem", + "image": "${data.image.sources[0].url}", + "primaryText": "${data.textContent.primaryText.text}", + "secondaryText": "${data.textContent.secondaryText.text}", + "tertiaryText": "${data.textContent.tertiaryText.text}" + } + ] + } + ] + } + ] + }, + "VerticalListItem": { + "parameters": ["primaryText", "secondaryText", "tertiaryText", "image"], + "item": [ + { + "when": "${viewport.shape == 'round'}", + "type": "Container", + "direction": "row", + "height": 200, + "width": 500, + "alignItems": "center", + "items": [ + { + "type": "Text", + "text": "${ordinal}", + "paddingBottom": "20dp", + "color": "white", + "spacing": "5dp" + }, + { + "type": "Image", + "when": "${image}", + "source": "${image}", + "height": 150, + "width": 150, + "spacing": 15, + "scale": "best-fit", + "align": "top" + }, + { + "type": "Container", + "direction": "column", + "spacing": 25, + "items": [ + { + "type": "Text", + "text": "${primaryText}", + "style": "textStyleDetail", + "grow": 1, + "shrink": 1, + "fontWeight": "300", + "maxLines": 1 + }, + { + "type": "Text", + "text": "${secondaryText}", + "style": "textStyleCaption", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + }, + { + "type": "Text", + "text": "${tertiaryText}", + "style": "textStyleDetails", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + } + ] + } + ] + }, + { + "type": "Container", + "direction": "row", + "height": 125, + "width": 800, + "alignItems": "center", + "items": [ + { + "type": "Text", + "text": "${ordinal}", + "paddingBottom": "20dp", + "color": "white", + "spacing": "5dp" + }, + { + "type": "Image", + "when": "${image}", + "source": "${image}", + "height": 100, + "width": 100, + "align": "top", + "spacing": 50, + "scale": "best-fit" + }, + { + "type": "Container", + "spacing": 30, + "direction": "column", + "items": [ + { + "type": "Text", + "text": "${primaryText}", + "style": "textStyleBody", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + }, + { + "type": "Text", + "text": "${secondaryText}", + "style": "textStyleDetails", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + } + ] + }, + { + "type": "Text", + "text": "${tertiaryText}", + "style": "textStyleBody", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "textAlign": "right", + "maxLines": 1 + } + ] + } + ] + } + }, + "mainTemplate": { + "parameters": ["payload"], + "item": [ + { + "type": "Container", + "id": "BookCabSimpleDialogAPL", + "items": [ + { + "type": "TouchWrapper", + "onPress": { + "type": "SendEvent", + "arguments": ["delegateToSkillNew"] + }, + "item": { + "type": "Text", + "id": "BookCabSimpleDialogAPL", + "paddingTop": "100", + "paddingLeft": "100", + "color": "green", + "size": 50, + "text": "delegateToSkillNew" + } + }, + { + "type": "TouchWrapper", + "onPress": { + "type": "SendEvent", + "arguments": ["delegateToSkillOld"] + }, + "item": { + "type": "Text", + "id": "BookCabSimpleDialogAPL", + "paddingTop": "100", + "paddingLeft": "100", + "color": "green", + "size": 50, + "text": "delegateToSkillOld" + } + }, + { + "type": "TouchWrapper", + "onPress": { + "type": "SendEvent", + "arguments": ["delegateToColtraneNew"] + }, + "item": { + "type": "Text", + "id": "BookCabSimpleDialogAPL", + "paddingTop": "100", + "paddingLeft": "100", + "color": "green", + "size": 50, + "text": "delegateToColtraneNew" + } + }, + { + "type": "TouchWrapper", + "onPress": { + "type": "SendEvent", + "arguments": ["delegateToColtraneOld"] + }, + "item": { + "type": "Text", + "id": "BookCabSimpleDialogAPL", + "paddingTop": "100", + "paddingLeft": "100", + "color": "green", + "size": 50, + "text": "delegateToColtraneOld" + } + } + ] + } + ] + } +} diff --git a/test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/AlexaConversationsBye/document.json b/test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/AlexaConversationsBye/document.json new file mode 100644 index 00000000..a0e2b3a8 --- /dev/null +++ b/test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/AlexaConversationsBye/document.json @@ -0,0 +1,19 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": ["payload"], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "Bye.", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} diff --git a/test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/AlexaConversationsNotifyFailure/document.json b/test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/AlexaConversationsNotifyFailure/document.json new file mode 100644 index 00000000..61d75e08 --- /dev/null +++ b/test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/AlexaConversationsNotifyFailure/document.json @@ -0,0 +1,19 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": ["payload"], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "Sorry, there was an error in the request.", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} diff --git a/test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/AlexaConversationsOutOfDomain/document.json b/test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/AlexaConversationsOutOfDomain/document.json new file mode 100644 index 00000000..e23d5986 --- /dev/null +++ b/test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/AlexaConversationsOutOfDomain/document.json @@ -0,0 +1,19 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": ["payload"], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "Sorry, I don't understand.", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} diff --git a/test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/AlexaConversationsProvideHelp/document.json b/test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/AlexaConversationsProvideHelp/document.json new file mode 100644 index 00000000..612a6f6e --- /dev/null +++ b/test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/AlexaConversationsProvideHelp/document.json @@ -0,0 +1,19 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": ["payload"], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "I can give you the weather report. Just say \"what's the weather\" to start.", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} diff --git a/test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/AlexaConversationsRequestMore/document.json b/test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/AlexaConversationsRequestMore/document.json new file mode 100644 index 00000000..32a98507 --- /dev/null +++ b/test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/AlexaConversationsRequestMore/document.json @@ -0,0 +1,19 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": ["payload"], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "What do you want to do.", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} diff --git a/test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/AlexaConversationsThankYou/document.json b/test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/AlexaConversationsThankYou/document.json new file mode 100644 index 00000000..4aeb6f4b --- /dev/null +++ b/test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/AlexaConversationsThankYou/document.json @@ -0,0 +1,19 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": ["payload"], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "Thank you.", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} diff --git a/test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/AlexaConversationsWelcome/document.json b/test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/AlexaConversationsWelcome/document.json new file mode 100644 index 00000000..b4ce85fe --- /dev/null +++ b/test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/AlexaConversationsWelcome/document.json @@ -0,0 +1,19 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": ["payload"], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "Welcome to the weather bot, I can give you the weather report. Just say \"what's the weather\" to start.", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} diff --git a/test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/AlexaConversationsYouAreWelcome/document.json b/test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/AlexaConversationsYouAreWelcome/document.json new file mode 100644 index 00000000..2cd1b9a8 --- /dev/null +++ b/test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/AlexaConversationsYouAreWelcome/document.json @@ -0,0 +1,19 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": ["payload"], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "You are welcome.", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} diff --git a/test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/confirmAction_complexNames_apla/document.json b/test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/confirmAction_complexNames_apla/document.json new file mode 100644 index 00000000..d4f492d7 --- /dev/null +++ b/test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/confirmAction_complexNames_apla/document.json @@ -0,0 +1,19 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": ["payload"], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "confirm Action your cool name ${payload.name} ? ", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} diff --git a/test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/confirmArgs_complexNames_apla/document.json b/test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/confirmArgs_complexNames_apla/document.json new file mode 100644 index 00000000..a5a3eec5 --- /dev/null +++ b/test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/confirmArgs_complexNames_apla/document.json @@ -0,0 +1,19 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": ["payload"], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "confirm args your cool name ${payload.name} ? ", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} diff --git a/test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/confirm_colorName_apla/document.json b/test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/confirm_colorName_apla/document.json new file mode 100644 index 00000000..62c9758b --- /dev/null +++ b/test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/confirm_colorName_apla/document.json @@ -0,0 +1,19 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": ["payload"], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "confirm color is ${payload.colorName} ? ", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} diff --git a/test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/confirm_main_addon_list_apla/document.json b/test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/confirm_main_addon_list_apla/document.json new file mode 100644 index 00000000..113da0d0 --- /dev/null +++ b/test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/confirm_main_addon_list_apla/document.json @@ -0,0 +1,19 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": ["payload"], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "confirm ${payload.foodName} with ${payload.addOn} ? ", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} diff --git a/test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/notused_apla/document.json b/test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/notused_apla/document.json new file mode 100644 index 00000000..91cdb444 --- /dev/null +++ b/test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/notused_apla/document.json @@ -0,0 +1,19 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": ["payload"], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "dummy response not used", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} diff --git a/test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/numericfeedback_apla/document.json b/test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/numericfeedback_apla/document.json new file mode 100644 index 00000000..2219120c --- /dev/null +++ b/test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/numericfeedback_apla/document.json @@ -0,0 +1,19 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": ["payload"], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "Your random number was ${payload.num}. How did we do? Please give this interaction a rating between 1-5, where 5 is the highest rating", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} diff --git a/test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/rating_apla/document.json b/test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/rating_apla/document.json new file mode 100644 index 00000000..06b50d68 --- /dev/null +++ b/test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/rating_apla/document.json @@ -0,0 +1,19 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": ["payload"], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "rating please?", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} diff --git a/test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/request_city_apla/document.json b/test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/request_city_apla/document.json new file mode 100644 index 00000000..64297b5e --- /dev/null +++ b/test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/request_city_apla/document.json @@ -0,0 +1,19 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": ["payload"], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "Which city?", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} diff --git a/test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/request_city_date_apla/document.json b/test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/request_city_date_apla/document.json new file mode 100644 index 00000000..a55ea5e1 --- /dev/null +++ b/test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/request_city_date_apla/document.json @@ -0,0 +1,19 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": ["payload"], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "Which city and for which date?", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} diff --git a/test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/request_colorName_apla/document.json b/test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/request_colorName_apla/document.json new file mode 100644 index 00000000..5e5891e1 --- /dev/null +++ b/test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/request_colorName_apla/document.json @@ -0,0 +1,19 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": ["payload"], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "which color?", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} diff --git a/test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/request_date_apla/document.json b/test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/request_date_apla/document.json new file mode 100644 index 00000000..af3a3f7d --- /dev/null +++ b/test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/request_date_apla/document.json @@ -0,0 +1,19 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": ["payload"], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "Which date?", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} diff --git a/test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/request_fruitName_apla/document.json b/test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/request_fruitName_apla/document.json new file mode 100644 index 00000000..5e5d608a --- /dev/null +++ b/test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/request_fruitName_apla/document.json @@ -0,0 +1,25 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": ["payload"], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "tell me the fruit name ?", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + }, + { + "type": "Speech", + "contentType": "text", + "content": "random slection tell me the fruit name ?", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} diff --git a/test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/request_listAddOns_apla/document.json b/test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/request_listAddOns_apla/document.json new file mode 100644 index 00000000..50faed8e --- /dev/null +++ b/test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/request_listAddOns_apla/document.json @@ -0,0 +1,19 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": ["payload"], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "what are the add ons?", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} diff --git a/test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/request_mainFoodName_apla/document.json b/test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/request_mainFoodName_apla/document.json new file mode 100644 index 00000000..316161b3 --- /dev/null +++ b/test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/request_mainFoodName_apla/document.json @@ -0,0 +1,19 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": ["payload"], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "What is the main food name?", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} diff --git a/test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/request_name_apla/document.json b/test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/request_name_apla/document.json new file mode 100644 index 00000000..db05dfee --- /dev/null +++ b/test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/request_name_apla/document.json @@ -0,0 +1,19 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": ["payload"], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "SSML", + "content": "what is your cool name?", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} diff --git a/test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/success_colorFruitAPI_apla/document.json b/test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/success_colorFruitAPI_apla/document.json new file mode 100644 index 00000000..b566e3fb --- /dev/null +++ b/test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/success_colorFruitAPI_apla/document.json @@ -0,0 +1,19 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": ["payload"], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "price of an ${payload.result.fruitName} is free bucks ", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} diff --git a/test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/success_cookingAPI_apla/document.json b/test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/success_cookingAPI_apla/document.json new file mode 100644 index 00000000..2b920b3d --- /dev/null +++ b/test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/success_cookingAPI_apla/document.json @@ -0,0 +1,19 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": ["payload"], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "we have ${payload.status.orderStatus}", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} diff --git a/test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/success_favColorSign_Name_apla/document.json b/test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/success_favColorSign_Name_apla/document.json new file mode 100644 index 00000000..65211056 --- /dev/null +++ b/test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/success_favColorSign_Name_apla/document.json @@ -0,0 +1,19 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": ["payload"], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "Fav color of ${payload.result.name}, is ${payload.result.color}", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} diff --git a/test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/success_fruitNameAPI_apla/document.json b/test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/success_fruitNameAPI_apla/document.json new file mode 100644 index 00000000..0db81389 --- /dev/null +++ b/test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/success_fruitNameAPI_apla/document.json @@ -0,0 +1,19 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": ["payload"], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "price of an ${payload.result.fruitName} is ${payload.result.price} bucks ", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} diff --git a/test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/success_weather_apla/document.json b/test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/success_weather_apla/document.json new file mode 100644 index 00000000..14fa169d --- /dev/null +++ b/test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/success_weather_apla/document.json @@ -0,0 +1,19 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": ["payload"], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "In ${payload.weatherResult.cityName}, it's a high of ${payload.weatherResult.highTemp} degrees and a low of ${payload.weatherResult.lowTemp} degrees.", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} diff --git a/test/fixture/dialog-evaluate/test-project-1/skill-package/skill.json b/test/fixture/dialog-evaluate/test-project-1/skill-package/skill.json new file mode 100644 index 00000000..9ba5d6aa --- /dev/null +++ b/test/fixture/dialog-evaluate/test-project-1/skill-package/skill.json @@ -0,0 +1,92 @@ +{ + "manifest": { + "apis": { + "custom": { + "dialogManagement": { + "dialogManagers": [ + { + "type": "AMAZON.Conversations" + } + ], + "sessionStartDelegationStrategy": { + "target": "AMAZON.Conversations" + } + }, + "endpoint": { + "uri": "arn:aws:lambda:us-east-1:12345678:function:123456:Release_0" + }, + "interfaces": [ + { + "supportedViewports": [ + { + "maxHeight": 480, + "maxWidth": 480, + "minHeight": 480, + "minWidth": 480, + "mode": "HUB", + "shape": "ROUND" + }, + { + "maxHeight": 600, + "maxWidth": 1024, + "minHeight": 600, + "minWidth": 1024, + "mode": "HUB", + "shape": "RECTANGLE" + }, + { + "maxHeight": 800, + "maxWidth": 1280, + "minHeight": 800, + "minWidth": 1280, + "mode": "HUB", + "shape": "RECTANGLE" + }, + { + "maxHeight": 540, + "maxWidth": 960, + "minHeight": 540, + "minWidth": 960, + "mode": "TV", + "shape": "RECTANGLE" + } + ], + "type": "ALEXA_PRESENTATION_APL" + } + ], + "regions": { + "EU": { + "endpoint": { + "uri": "arn:aws:lambda:us-east-1:12345678:function:123456:Release_0" + } + }, + "NA": { + "endpoint": { + "uri": "arn:aws:lambda:us-east-1:12345678:function:123456:Release_0" + } + }, + "FE": { + "endpoint": { + "uri": "arn:aws:lambda:us-east-1:12345678:function:123456:Release_0" + } + } + } + } + }, + "manifestVersion": "1.0", + "publishingInformation": { + "category": "KNOWLEDGE_AND_TRIVIA", + "distributionCountries": [], + "isAvailableWorldwide": true, + "locales": { + "en-US": { + "description": "Sample Full Description", + "examplePhrases": ["Alexa open hello world", "hello", "help"], + "name": "engineering test skill one", + "summary": "Sample Short Description" + } + }, + "testingInstructions": "Sample Testing Instructions." + } + } +} diff --git a/test/functional/commands/high-level-commands-test.js b/test/functional/commands/high-level-commands-test.js index eec3249f..3c876beb 100644 --- a/test/functional/commands/high-level-commands-test.js +++ b/test/functional/commands/high-level-commands-test.js @@ -1,140 +1,160 @@ -const { expect } = require('chai'); -const parallel = require('mocha.parallel'); -const { run, KeySymbol, resetTempDirectory, deleteFolderInTempDirectory, - getPathInTempDirectory, makeFolderInTempDirectory } = require('@test/test-utils'); - -parallel('high level commands test', () => { - let cmd; - - before(() => { - resetTempDirectory(); - }); - - beforeEach(() => { - cmd = 'ask'; - }); - - it('| should init new skill', async () => { - const folderName = 'new-skill'; - deleteFolderInTempDirectory(folderName); - makeFolderInTempDirectory(`${folderName}/skill-package`); - makeFolderInTempDirectory(`${folderName}/lambda`); - - const cwd = getPathInTempDirectory(folderName); - - const args = ['init']; - const inputs = [ - { match: '? Skill Id' }, - { match: '? Skill package path' }, - { match: '? Lambda code path' }, - { match: '? Use AWS CloudFormation', input: 'n' }, - { match: '? Lambda runtime' }, - { match: '? Lambda handler' }, - { match: '? Does this look correct?' } - ]; - - const result = await run(cmd, args, { inputs, cwd }); - - expect(result).include('succeeded'); - }); - - it('| should set up, deploy, clone hosted skill', async () => { - let folderName = 'hosted-skill'; - deleteFolderInTempDirectory(folderName); - - // new - let args = ['new']; - let inputs = [ - { match: '? Choose the programming language' }, - { match: '? Choose a method to host your skill' }, - { match: '? Choose the default locale for your skill' }, - { match: '? Choose the default region for your skill' }, - { match: '? Please type in your skill name' }, - { match: '? Please type in your folder name', input: folderName } - ]; - - let result = await run(cmd, args, { inputs }); - - expect(result).include('Hosted skill provisioning finished'); - - // deploy - let cwd = getPathInTempDirectory(folderName); - cmd = 'git'; - args = ['add', '.']; - await run(cmd, args, { cwd }); - - args = ['commit', '-m', '"test"']; - await run(cmd, args, { cwd }); - - args = ['push']; - result = await run(cmd, args, { cwd }); - - expect(result).include('After the code pushed, please check the deployment status'); - - const skillId = result.match(/(amzn1\.ask\.skill\.[a-z0-9-]*)/m)[0]; - - folderName = 'cloned-hosted-skill'; - cwd = getPathInTempDirectory(folderName); - cmd = 'ask'; - args = ['init', '--hosted-skill-id', skillId]; - inputs = [ - { match: '? Please type in your folder name', input: folderName } - ]; - - result = await run(cmd, args, { inputs, cwd }); - - expect(result).include('successfully initialized'); - }); - - it('| should set up and deploy skill with cloud formation deployer', async () => { - const folderName = 'cf-deployer-skill'; - deleteFolderInTempDirectory(folderName); - // new - let args = ['new']; - const inputs = [ - { match: '? Choose the programming language' }, - { match: '? Choose a method to host your skill', input: KeySymbol.DOWN }, - { match: '? Choose a template to start with' }, - { match: '? Please type in your skill name' }, - { match: '? Please type in your folder name', input: folderName } - ]; - - let result = await run(cmd, args, { inputs }); - - expect(result).include('Project initialized with deploy delegate "@ask-cli/cfn-deployer" successfully'); - - // deploy - const cwd = getPathInTempDirectory(folderName); - args = ['deploy']; - - result = await run(cmd, args, { cwd }); - - expect(result).include('Skill infrastructures deployed successfully through @ask-cli/cfn-deployer'); - }); - - it('| should set up and deploy skill with lambda deployer', async () => { - const folderName = 'lambda-skill'; - deleteFolderInTempDirectory(folderName); - // new - let args = ['new']; - const inputs = [ - { match: '? Choose the programming language' }, - { match: '? Choose a method to host your skill', input: `${KeySymbol.DOWN}${KeySymbol.DOWN}` }, - { match: '? Choose a template to start with' }, - { match: '? Please type in your skill name', input: folderName }, - { match: '? Please type in your folder name', input: folderName } - ]; - - let result = await run(cmd, args, { inputs }); - - expect(result).include('Project initialized with deploy delegate "@ask-cli/lambda-deployer" successfully'); - - // deploy - const cwd = getPathInTempDirectory(folderName); - args = ['deploy']; - - result = await run(cmd, args, { cwd }); - - expect(result).include('Skill infrastructures deployed successfully through @ask-cli/lambda-deployer'); - }); +const {expect} = require("chai"); +const parallel = require("mocha.parallel"); +const { + run, + KeySymbol, + resetTempDirectory, + deleteFolderInTempDirectory, + getPathInTempDirectory, + makeFolderInTempDirectory, +} = require("../../test-utils"); + +parallel("high level commands test", () => { + let cmd; + + before(() => { + resetTempDirectory(); + }); + + beforeEach(() => { + cmd = "ask"; + }); + + it("| should init new skill", async () => { + const folderName = "new-skill"; + deleteFolderInTempDirectory(folderName); + makeFolderInTempDirectory(`${folderName}/skill-package`); + makeFolderInTempDirectory(`${folderName}/lambda`); + + const cwd = getPathInTempDirectory(folderName); + + const args = ["init"]; + const inputs = [ + {match: "? Skill Id"}, + {match: "? Skill package path"}, + {match: "? Lambda code path"}, + {match: "? Use AWS CloudFormation", input: "n"}, + {match: "? Lambda runtime"}, + {match: "? Lambda handler"}, + {match: "? Does this look correct?"}, + ]; + + const result = await run(cmd, args, {inputs, cwd}); + + expect(result).include("succeeded"); + }); + + it("| should set up, deploy, clone hosted skill", async () => { + let folderName = "hosted-skill"; + deleteFolderInTempDirectory(folderName); + + // new + let args = ["new"]; + let inputs = [ + {match: "? Choose the programming language"}, + {match: "? Choose a method to host your skill"}, + {match: "? Choose the default locale for your skill"}, + {match: "? Choose the default region for your skill"}, + {match: "? Please type in your skill name"}, + {match: "? Please type in your folder name", input: folderName}, + ]; + + let result = await run(cmd, args, {inputs}); + + expect(result).include("Hosted skill provisioning finished"); + + // deploy + let cwd = getPathInTempDirectory(folderName); + cmd = "git"; + args = ["add", "."]; + await run(cmd, args, {cwd}); + + args = ["commit", "-m", '"test"']; + await run(cmd, args, {cwd}); + + args = ["push"]; + result = await run(cmd, args, {cwd}); + + expect(result).include("After the code pushed, please check the deployment status"); + + const skillId = result.match(/(amzn1\.ask\.skill\.[a-z0-9-]*)/m)[0]; + + folderName = "cloned-hosted-skill"; + cwd = getPathInTempDirectory(folderName); + cmd = "ask"; + args = ["init", "--hosted-skill-id", skillId]; + inputs = [{match: "? Please type in your folder name", input: folderName}]; + + result = await run(cmd, args, {inputs, cwd}); + + expect(result).include("successfully initialized"); + }); + + it("| should set up and deploy skill with cloud formation deployer", async () => { + const folderName = "cf-deployer-skill"; + deleteFolderInTempDirectory(folderName); + // new + let args = ["new"]; + const inputs = [ + {match: "? Choose the programming language"}, + {match: "? Choose a method to host your skill", input: KeySymbol.DOWN}, + {match: "? Choose a template to start with"}, + {match: "? Please type in your skill name"}, + {match: "? Please type in your folder name", input: folderName}, + ]; + + let result = await run(cmd, args, {inputs}); + + expect(result).include('Project initialized with deploy delegate "@ask-cli/cfn-deployer" successfully'); + + // deploy + const cwd = getPathInTempDirectory(folderName); + args = ["deploy"]; + + result = await run(cmd, args, {cwd}); + + expect(result).include("Skill infrastructures deployed successfully through @ask-cli/cfn-deployer"); + }); + + it("| should set up and deploy skill with lambda deployer", async () => { + const folderName = "lambda-skill"; + deleteFolderInTempDirectory(folderName); + // new + let args = ["new"]; + const inputs = [ + {match: "? Choose the programming language"}, + {match: "? Choose a method to host your skill", input: `${KeySymbol.DOWN}${KeySymbol.DOWN}`}, + {match: "? Choose a template to start with"}, + {match: "? Please type in your skill name", input: folderName}, + {match: "? Please type in your folder name", input: folderName}, + ]; + + let result = await run(cmd, args, {inputs}); + + expect(result).include('Project initialized with deploy delegate "@ask-cli/lambda-deployer" successfully'); + + // deploy + const cwd = getPathInTempDirectory(folderName); + args = ["deploy"]; + + result = await run(cmd, args, {cwd}); + + expect(result).include("Skill infrastructures deployed successfully through @ask-cli/lambda-deployer"); + }); + + it("| should set up and AC deploy skill with lambda deployer", async () => { + const folderName = "ac-lambda-skill"; + deleteFolderInTempDirectory(folderName); + // new + let args = ["new"]; + const inputs = [ + {match: "? Choose the programming language"}, + {match: "? Choose a method to host your skill", input: `${KeySymbol.DOWN}${KeySymbol.DOWN}`}, + {match: "? Choose a template to start with", input: `${KeySymbol.DOWN}${KeySymbol.DOWN}${KeySymbol.DOWN}`}, + {match: "? Please type in your skill name", input: folderName}, + {match: "? Please type in your folder name", input: folderName}, + ]; + let result = await run(cmd, args, {inputs}); + expect(result).include('Project initialized with deploy delegate "@ask-cli/lambda-deployer" successfully'); + }); }); diff --git a/test/functional/run-test.js b/test/functional/run-test.js index b1ea8f82..e235e7ed 100644 --- a/test/functional/run-test.js +++ b/test/functional/run-test.js @@ -1,10 +1,6 @@ -require('module-alias/register'); - process.env.ASK_SHARE_USAGE = false; -[ - '@test/functional/commands/high-level-commands-test.js' -].forEach((testFile) => { - // eslint-disable-next-line global-require - require(testFile); +["./commands/high-level-commands-test.js"].forEach((testFile) => { + // eslint-disable-next-line global-require + require(testFile); }); diff --git a/test/integration/code-builder/code-builder-test.js b/test/integration/code-builder/code-builder-test.js index a7cd568a..8ba455cc 100644 --- a/test/integration/code-builder/code-builder-test.js +++ b/test/integration/code-builder/code-builder-test.js @@ -1,131 +1,131 @@ -const { expect } = require('chai'); -const fs = require('fs-extra'); -const path = require('path'); -const sinon = require('sinon'); +const {expect} = require("chai"); +const fs = require("fs-extra"); +const path = require("path"); +const sinon = require("sinon"); -const { makeFolderInTempDirectory } = require('@test/test-utils'); -const CodeBuilder = require('@src/controllers/skill-code-controller/code-builder'); -const hashUtils = require('@src/utils/hash-utils'); +const {makeFolderInTempDirectory} = require("../../test-utils"); +const CodeBuilder = require("../../../lib/controllers/skill-code-controller/code-builder"); +const hashUtils = require("../../../lib/utils/hash-utils"); -const fixturesDirectory = path.join(process.cwd(), 'test', 'integration', 'fixtures', 'code-builder'); +const fixturesDirectory = path.join(process.cwd(), "test", "integration", "fixtures", "code-builder"); const setUpTempFolder = (sourceDirName) => { - const tempDirName = `${sourceDirName}-builder`; - const cwd = makeFolderInTempDirectory(tempDirName); - const sourceDir = path.join(fixturesDirectory, sourceDirName, 'lambda'); - const buildFolder = path.join(cwd, '.ask', 'lambda'); - const buildFile = path.join(buildFolder, 'build.zip'); - return { - src: sourceDir, - build: { folder: buildFolder, file: buildFile } - }; + const tempDirName = `${sourceDirName}-builder`; + const cwd = makeFolderInTempDirectory(tempDirName); + const sourceDir = path.join(fixturesDirectory, sourceDirName, "lambda"); + const buildFolder = path.join(cwd, ".ask", "lambda"); + const buildFile = path.join(buildFolder, "build.zip"); + return { + src: sourceDir, + build: {folder: buildFolder, file: buildFile}, + }; }; -describe('code builder test', () => { - it('| should build nodejs npm skill', (done) => { - const config = setUpTempFolder('nodejs-npm'); - - const codeBuilder = new CodeBuilder(config); - - const expectedMinSizeInBytes = 100000; - codeBuilder.execute((err, res) => { - expect(err).eql(null); - expect(res).eql(undefined); - const hash = hashUtils.getFileHash(config.build.file); - expect(fs.existsSync(config.build.file)).eq(true); - expect(fs.statSync(config.build.file).size).gt(expectedMinSizeInBytes); - codeBuilder.execute(() => { - const newHash = hashUtils.getFileHash(config.build.file); - expect(hash).equal(newHash); - done(); - }); - }); +describe("code builder test", () => { + it("| should build nodejs npm skill", (done) => { + const config = setUpTempFolder("nodejs-npm"); + + const codeBuilder = new CodeBuilder(config); + + const expectedMinSizeInBytes = 100000; + codeBuilder.execute((err, res) => { + expect(err).eql(null); + expect(res).eql(undefined); + const hash = hashUtils.getFileHash(config.build.file); + expect(fs.existsSync(config.build.file)).eq(true); + expect(fs.statSync(config.build.file).size).gt(expectedMinSizeInBytes); + codeBuilder.execute(() => { + const newHash = hashUtils.getFileHash(config.build.file); + expect(hash).equal(newHash); + done(); + }); }); - - it('| should build python pip skill', (done) => { - const config = setUpTempFolder('python-pip'); - - const codeBuilder = new CodeBuilder(config); - - const expectedMinSizeInBytes = 1500000; - codeBuilder.execute((err, res) => { - expect(err).eql(null); - expect(res).eql(undefined); - const hash = hashUtils.getFileHash(config.build.file); - expect(fs.existsSync(config.build.file)).eq(true); - expect(fs.statSync(config.build.file).size).gt(expectedMinSizeInBytes); - // consistent hashing on windows does not work due to chardet package - if (process.platform === 'win32') { - done(); - } else { - codeBuilder.execute(() => { - const newHash = hashUtils.getFileHash(config.build.file); - expect(hash).equal(newHash); - done(); - }); - } + }); + + it("| should build python pip skill", (done) => { + const config = setUpTempFolder("python-pip"); + + const codeBuilder = new CodeBuilder(config); + + const expectedMinSizeInBytes = 1500000; + codeBuilder.execute((err, res) => { + expect(err).eql(null); + expect(res).eql(undefined); + const hash = hashUtils.getFileHash(config.build.file); + expect(fs.existsSync(config.build.file)).eq(true); + expect(fs.statSync(config.build.file).size).gt(expectedMinSizeInBytes); + // consistent hashing on windows does not work due to chardet package + if (process.platform === "win32") { + done(); + } else { + codeBuilder.execute(() => { + const newHash = hashUtils.getFileHash(config.build.file); + expect(hash).equal(newHash); + done(); }); + } }); - - it('| should build java mvn skill', (done) => { - const config = setUpTempFolder('java-mvn'); - - const codeBuilder = new CodeBuilder(config); - - const expectedMinSizeInBytes = 10000000; - codeBuilder.execute((err, res) => { - expect(err).eql(null); - expect(res).eql(undefined); - const hash = hashUtils.getFileHash(config.build.file); - expect(fs.existsSync(config.build.file)).eq(true); - expect(fs.statSync(config.build.file).size).gt(expectedMinSizeInBytes); - codeBuilder.execute(() => { - const newHash = hashUtils.getFileHash(config.build.file); - expect(hash).equal(newHash); - done(); - }); - }); + }); + + it("| should build java mvn skill", (done) => { + const config = setUpTempFolder("java-mvn"); + + const codeBuilder = new CodeBuilder(config); + + const expectedMinSizeInBytes = 10000000; + codeBuilder.execute((err, res) => { + expect(err).eql(null); + expect(res).eql(undefined); + const hash = hashUtils.getFileHash(config.build.file); + expect(fs.existsSync(config.build.file)).eq(true); + expect(fs.statSync(config.build.file).size).gt(expectedMinSizeInBytes); + codeBuilder.execute(() => { + const newHash = hashUtils.getFileHash(config.build.file); + expect(hash).equal(newHash); + done(); + }); }); - - it('| should build with custom script', (done) => { - const sourceDirName = 'custom'; - const config = setUpTempFolder(sourceDirName); - const sourceDir = path.join(fixturesDirectory, sourceDirName); - sinon.stub(process, 'cwd').returns(sourceDir); - - const codeBuilder = new CodeBuilder(config); - - const expectedMinSizeInBytes = 100000; - codeBuilder.execute((err, res) => { - expect(err).eql(undefined); - expect(res).eql(undefined); - expect(fs.existsSync(config.build.file)).eq(true); - expect(fs.statSync(config.build.file).size).gt(expectedMinSizeInBytes); - done(); - }); + }); + + it("| should build with custom script", (done) => { + const sourceDirName = "custom"; + const config = setUpTempFolder(sourceDirName); + const sourceDir = path.join(fixturesDirectory, sourceDirName); + sinon.stub(process, "cwd").returns(sourceDir); + + const codeBuilder = new CodeBuilder(config); + + const expectedMinSizeInBytes = 100000; + codeBuilder.execute((err, res) => { + expect(err).eql(undefined); + expect(res).eql(undefined); + expect(fs.existsSync(config.build.file)).eq(true); + expect(fs.statSync(config.build.file).size).gt(expectedMinSizeInBytes); + done(); }); - - it('| should zip only', (done) => { - const config = setUpTempFolder('zip-only'); - - const codeBuilder = new CodeBuilder(config); - - const expectedMinSizeInBytes = 100; - codeBuilder.execute((err, res) => { - expect(err).eql(null); - expect(res).eql(undefined); - const hash = hashUtils.getFileHash(config.build.file); - expect(fs.existsSync(config.build.file)).eq(true); - expect(fs.statSync(config.build.file).size).gt(expectedMinSizeInBytes); - codeBuilder.execute(() => { - const newHash = hashUtils.getFileHash(config.build.file); - expect(hash).equal(newHash); - done(); - }); - }); + }); + + it("| should zip only", (done) => { + const config = setUpTempFolder("zip-only"); + + const codeBuilder = new CodeBuilder(config); + + const expectedMinSizeInBytes = 100; + codeBuilder.execute((err, res) => { + expect(err).eql(null); + expect(res).eql(undefined); + const hash = hashUtils.getFileHash(config.build.file); + expect(fs.existsSync(config.build.file)).eq(true); + expect(fs.statSync(config.build.file).size).gt(expectedMinSizeInBytes); + codeBuilder.execute(() => { + const newHash = hashUtils.getFileHash(config.build.file); + expect(hash).equal(newHash); + done(); + }); }); + }); - afterEach(() => { - sinon.restore(); - }); + afterEach(() => { + sinon.restore(); + }); }); diff --git a/test/integration/commands/smapi-commands-test.js b/test/integration/commands/smapi-commands-test.js index 7d35e8ee..dacd7966 100644 --- a/test/integration/commands/smapi-commands-test.js +++ b/test/integration/commands/smapi-commands-test.js @@ -1,17 +1,17 @@ -const { expect } = require('chai'); -const { ModelIntrospector } = require('ask-smapi-sdk'); -const parallel = require('mocha.parallel'); - -const { CliCustomizationProcessor } = require('@src/commands/smapi/cli-customization-processor'); -const { run, startMockSmapiServer, startMockLwaServer, MockServerPort } = require('@test/test-utils'); -const skillManifest = require('@test/integration/fixtures/skill-manifest.json'); -const catalogUploadBody = require('@test/integration/fixtures/catalog-upload.json'); -const inSkillProductRequestBody = require('@test/integration/fixtures/create-in-skill-product-request.json'); -const accountLinkingRequest = require('@test/integration/fixtures/account-linking-request.json'); -const interactionModel = require('@test/integration/fixtures/interaction-model.json'); -const annotationSet = require('@test/integration/fixtures/annotation-set.json'); -const jobDefinition = require('@test/integration/fixtures/job-definition.json'); -const experimentMetricConfigurationModel = require('@test/integration/fixtures/experiment-metric-configuration.json') +const {expect} = require("chai"); +const {ModelIntrospector} = require("ask-smapi-sdk"); +const parallel = require("mocha.parallel"); + +const {CliCustomizationProcessor} = require("../../../lib/commands/smapi/cli-customization-processor"); +const {run, startMockSmapiServer, startMockLwaServer, MockServerPort} = require("../../test-utils"); +const skillManifest = require("../../integration/fixtures/skill-manifest.json"); +const catalogUploadBody = require("../../integration/fixtures/catalog-upload.json"); +const inSkillProductRequestBody = require("../../integration/fixtures/create-in-skill-product-request.json"); +const accountLinkingRequest = require("../../integration/fixtures/account-linking-request.json"); +const interactionModel = require("../../integration/fixtures/interaction-model.json"); +const annotationSet = require("../../integration/fixtures/annotation-set.json"); +const jobDefinition = require("../../integration/fixtures/job-definition.json"); +const experimentMetricConfigurationModel = require('../../integration/fixtures/experiment-metric-configuration.json'); parallel.limit(8); @@ -21,12 +21,12 @@ const untestedCommands = new Set([...modelIntrospector.getOperations().keys()].m const testedCommands = new Set(); const addCoveredCommand = (args) => { - const cmd = args[1]; - if (testedCommands.has(cmd)) { - console.warn(`${cmd} already has been covered!`); - } - testedCommands.add(cmd); - untestedCommands.delete(cmd); + const cmd = args[1]; + if (testedCommands.has(cmd)) { + console.warn(`${cmd} already has been covered!`); + } + testedCommands.add(cmd); + untestedCommands.delete(cmd); }; parallel('smapi command test', () => { @@ -135,1218 +135,1382 @@ parallel('smapi command test', () => { const partETags = JSON.stringify([{ eTag: 'someEtag', partNumber: 1 }]); const testersEmails = 'user1@gmail.com,user2@gmail.com'; - before(async () => { - mockSmapiServer = await startMockSmapiServer(); - mockLwaServer = await startMockLwaServer(); - }); - - it('| should display vendor list', async () => { - const args = [subCmd, 'get-vendor-list']; - addCoveredCommand(args); - const result = await run(cmd, args, options); - expect(result).be.an('object'); - }); - - it('| should list skills for vendor', async () => { - const args = [subCmd, 'list-skills-for-vendor', '--max-results', 1]; - addCoveredCommand(args); - const result = await run(cmd, args, options); - expect(result).be.an('object'); - }); - - it('| should create skill for vendor', async () => { - const args = [subCmd, 'create-skill-for-vendor', '--manifest', JSON.stringify(skillManifest)]; - addCoveredCommand(args); - const result = await run(cmd, args, options); - expect(result).be.an('object'); - }); - - it('| should get skill status', async () => { - const args = [subCmd, 'get-skill-status', '-s', skillId]; - addCoveredCommand(args); - const result = await run(cmd, args, options); - expect(result).be.an('object'); - }); - - it('| should display catalog list', async () => { - const args = [subCmd, 'list-catalogs-for-vendor']; - addCoveredCommand(args); - const result = await run(cmd, args, options); - expect(result).be.an('object'); - }); - - it('| should create catalog', async () => { - const args = [subCmd, 'create-catalog', '--title', 'test', - '--type', 'AMAZON.BroadcastChannel', - '--usage', 'AlexaMusic.Catalog.BroadcastChannel']; - addCoveredCommand(args); - const result = await run(cmd, args, options); - expect(result).be.an('object'); - }); - - it('| should get catalog information', async () => { - const args = [subCmd, 'get-catalog', '-c', 'someCatalogId']; - addCoveredCommand(args); - const result = await run(cmd, args, options); - expect(result).be.an('object'); - }); - - it('| should associate skill with catalog', async () => { - const args = [subCmd, 'associate-catalog-with-skill', '-c', catalogId, '-s', skillId]; - addCoveredCommand(args); - const result = await run(cmd, args, { ...options, parse: false }); - expect(result).include('Command executed successfully!'); - }); - - it('| should create catalog upload', async () => { - const args = [subCmd, 'create-catalog-upload', '-c', catalogId, '--catalog-upload-request-body', JSON.stringify(catalogUploadBody)]; - addCoveredCommand(args); - const result = await run(cmd, args, { ...options, parse: false }); - expect(result).include('Command executed successfully!'); - }); - - it('| should display catalog list for skill', async () => { - const args = [subCmd, 'list-catalogs-for-skill', '-s', skillId, '--max-results', 1]; - addCoveredCommand(args); - const result = await run(cmd, args, options); - expect(result).be.an('object'); - }); - - it('| should display alexa hosted skill metadata', async () => { - const args = [subCmd, 'get-alexa-hosted-skill-metadata', '-s', skillId]; - addCoveredCommand(args); - const result = await run(cmd, args, options); - expect(result).be.an('object'); - }); - - it('| should display utterance data', async () => { - const args = [subCmd, 'get-utterance-data', '-s', skillId, '--locale', locale, '--sort-direction', 'asc']; - addCoveredCommand(args); - const result = await run(cmd, args, options); - expect(result).be.an('object'); - }); - - it('| should add testers to beta test', async () => { - const args = [subCmd, 'add-testers-to-beta-test', '-s', skillId, '--testers-emails', testersEmails]; - addCoveredCommand(args); - const result = await run(cmd, args, { ...options, parse: false }); - expect(result).include('Command executed successfully!'); - }); - - it('| should get list of testers', async () => { - const args = [subCmd, 'get-list-of-testers', '-s', skillId, '--max-results', 1]; - addCoveredCommand(args); - const result = await run(cmd, args, options); - expect(result).be.an('object'); - }); - - it('| should request feedback from testers', async () => { - const args = [subCmd, 'request-feedback-from-testers', '-s', skillId, '--testers-emails', testersEmails]; - addCoveredCommand(args); - const result = await run(cmd, args, { ...options, parse: false }); - expect(result).include('Command executed successfully!'); - }); - - it('| should send reminder to testers', async () => { - const args = [subCmd, 'send-reminder-to-testers', '-s', skillId, '--testers-emails', testersEmails]; - addCoveredCommand(args); - const result = await run(cmd, args, { ...options, parse: false }); - expect(result).include('Command executed successfully!'); - }); - - it('| should remove testers from beta test', async () => { - const args = [subCmd, 'remove-testers-from-beta-test', '-s', skillId, '--testers-emails', testersEmails]; - addCoveredCommand(args); - const result = await run(cmd, args, { ...options, parse: false }); - expect(result).include('Command executed successfully!'); - }); - - it('| should update interaction model catalog version and return version number', async () => { - const args = [subCmd, 'update-interaction-model-catalog-version', '-c', catalogId, '--vers', 1, '--description', 'test']; - addCoveredCommand(args); - const result = await run(cmd, args, { ...options, parse: false }); - expect(result).include('Command executed successfully!'); - }); - - it('| should simulate skill', async () => { - const args = [subCmd, 'simulate-skill', '-s', skillId, '--device-locale', locale, '-g', stage, '--input-content', 'hello']; - addCoveredCommand(args); - const result = await run(cmd, args, options); - expect(result).be.an('object'); - }); - - it('| should create beta test', async () => { - const args = [subCmd, 'create-beta-test', '-s', skillId, '--feedback-email', 'someemail@email.com']; - addCoveredCommand(args); - const result = await run(cmd, args, { ...options, parse: false }); - expect(result).include('Command executed successfully!'); - }); - - it('| should update beta test', async () => { - const args = [subCmd, 'update-beta-test', '-s', skillId, '--feedback-email', 'test2@gmail.com']; - addCoveredCommand(args); - const result = await run(cmd, args, { ...options, parse: false }); - expect(result).include('Command executed successfully!'); - }); - - it('| should retrieve beta test', async () => { - const args = [subCmd, 'get-beta-test', '-s', skillId]; - addCoveredCommand(args); - const result = await run(cmd, args, options); - expect(result).be.an('object'); - }); - - it('| should list uploads for catalog', async () => { - const args = [subCmd, 'list-uploads-for-catalog', '-c', catalogId, '--max-results', 1]; - addCoveredCommand(args); - const result = await run(cmd, args, options); - expect(result).be.an('object'); - }); - - it('| should list isp for vendor', async () => { - const args = [subCmd, 'get-isp-list-for-vendor', '--max-results', 1]; - addCoveredCommand(args); - const result = await run(cmd, args, options); - expect(result).be.an('object'); - }); - - it('| should list isp for skill id ', async () => { - const args = [subCmd, 'get-isp-list-for-skill-id', '-s', skillId, '-g', stage, '--max-results', 1]; - addCoveredCommand(args); - const result = await run(cmd, args, options); - expect(result).be.an('object'); - }); - - it('| should update account linking', async () => { - const args = [subCmd, 'update-account-linking-info', '-s', skillId, '-g', stage, - '--account-linking-request', JSON.stringify(accountLinkingRequest)]; - addCoveredCommand(args); - const result = await run(cmd, args, { ...options, parse: false }); - expect(result).include('Command executed successfully!'); - }); - - it('| should retrieve account linking', async () => { - const args = [subCmd, 'get-account-linking-info', '-s', skillId, '-g', stage]; - addCoveredCommand(args); - const result = await run(cmd, args, options); - expect(result).be.an('object'); - }); - - it('| should delete account linking', async () => { - const args = [subCmd, 'delete-account-linking-info', '-s', skillId, '-g', stage]; - addCoveredCommand(args); - const result = await run(cmd, args, { ...options, parse: false }); - expect(result).include('Command executed successfully!'); - }); - - it('| should create isp', async () => { - const args = [subCmd, 'create-isp-for-vendor', '--create-in-skill-product-request', JSON.stringify(inSkillProductRequestBody)]; - addCoveredCommand(args); - const result = await run(cmd, args, options); - expect(result).be.an('object'); - }); - - it('| should get isp definition', async () => { - const args = [subCmd, 'get-isp-definition', '--product-id', productId, '-g', stage]; - addCoveredCommand(args); - const result = await run(cmd, args, options); - expect(result).be.an('object'); - }); - - it('| should reset entitlement for product', async () => { - const args = [subCmd, 'reset-entitlement-for-product', '--product-id', productId, '-g', stage]; - addCoveredCommand(args); - const result = await run(cmd, args, { ...options, parse: false }); - expect(result).include('Command executed successfully!'); - }); - - it('| should get isp associated skills', async () => { - const args = [subCmd, 'get-isp-associated-skills', '--product-id', productId, '-g', stage]; - addCoveredCommand(args); - const result = await run(cmd, args, options); - expect(result).be.an('object'); - }); - - it('| should disassociate isp with skill', async () => { - const args = [subCmd, 'disassociate-isp-with-skill', '--product-id', productId, '-s', skillId]; - addCoveredCommand(args); - const result = await run(cmd, args, { ...options, parse: false }); - expect(result).include('Command executed successfully!'); - }); - - it('| should retrieve isp summary', async () => { - const args = [subCmd, 'get-isp-summary', '--product-id', productId, '-g', stage]; - addCoveredCommand(args); - const result = await run(cmd, args, options); - expect(result).be.an('object'); - }); - - it('| should update isp for product', async () => { - const args = [subCmd, 'update-isp-for-product', '--product-id', productId, '-g', stage, - '--in-skill-product', JSON.stringify(inSkillProductRequestBody)]; - addCoveredCommand(args); - const result = await run(cmd, args, { ...options, parse: false }); - expect(result).include('Command executed successfully!'); - }); - - it('| should delete isp for product', async () => { - const args = [subCmd, 'delete-isp-for-product', '--product-id', productId, '-g', stage]; - addCoveredCommand(args); - const result = await run(cmd, args, { ...options, parse: false }); - expect(result).include('Command executed successfully!'); - }); - - it('| should create content upload', async () => { - const args = [subCmd, 'create-content-upload', '-c', catalogId, '--number-of-upload-parts', 1]; - addCoveredCommand(args); - const result = await run(cmd, args, options); - expect(result).be.an('object'); - }); - - it('| should generate credentials for alexa hosted skill', async () => { - const args = [subCmd, 'generate-credentials-for-alexa-hosted-skill', '-s', skillId, - '--repository-url', 'https://git-codecommit.us-east-1.amazonaws.com/v1/repos/e9ac9d7f-5c4f-4c3b-8e41-1b347f625d95', - '--repository-type', 'GIT']; - addCoveredCommand(args); - const result = await run(cmd, args, options); - expect(result).be.an('object'); - }); - - it('| should get content upload by id', async () => { - const args = [subCmd, 'get-content-upload-by-id', '-c', catalogId, '--upload-id', uploadId]; - addCoveredCommand(args); - const result = await run(cmd, args, options); - expect(result).be.an('object'); - }); - - it('| should complete catalog upload', async () => { - const args = [subCmd, 'complete-catalog-upload', '-c', catalogId, '--upload-id', uploadId, '--part-e-tags', partETags]; - addCoveredCommand(args); - const result = await run(cmd, args, { ...options, parse: false }); - expect(result).include('Command executed successfully!'); - }); - - it('| should list subscribers for development events', async () => { - const args = [subCmd, 'list-subscribers-for-development-events']; - addCoveredCommand(args); - const result = await run(cmd, args, options); - expect(result).be.an('object'); - }); - - it('| should create subscriber for development events', async () => { - const args = [subCmd, 'create-subscriber-for-development-events', '--create-subscriber-request', createSubscriptionRequest]; - addCoveredCommand(args); - const result = await run(cmd, args, { ...options, parse: false }); - expect(result).include('Command executed successfully!'); - }); - - it('| should get subscriber for development events', async () => { - const args = [subCmd, 'get-subscriber-for-development-events', '--subscriber-id', subscriberId]; - addCoveredCommand(args); - const result = await run(cmd, args, options); - expect(result).be.an('object'); - }); - - it('| should set subscriber for development events', async () => { - const args = [subCmd, 'set-subscriber-for-development-events', '--subscriber-id', subscriberId, - '--update-subscriber-request', updateSubscriptionRequest]; - addCoveredCommand(args); - const result = await run(cmd, args, { ...options, parse: false }); - expect(result).include('Command executed successfully!'); - }); - - it('| should delete subscriber for development events', async () => { - const args = [subCmd, 'delete-subscriber-for-development-events', '--subscriber-id', subscriberId]; - addCoveredCommand(args); - const result = await run(cmd, args, { ...options, parse: false }); - expect(result).include('Command executed successfully!'); - }); - - it('| should list subscriptions for development events', async () => { - const args = [subCmd, 'list-subscriptions-for-development-events']; - addCoveredCommand(args); - const result = await run(cmd, args, options); - expect(result).be.an('object'); - }); - - it('| should create subscription for development events', async () => { - const args = [subCmd, 'create-subscription-for-development-events', - '--name', 'someName', '--events', 'AlexaDevelopmentEvent.ManifestUpdat', - '--subscriber-id', subscriberId]; - addCoveredCommand(args); - const result = await run(cmd, args, { ...options, parse: false }); - expect(result).include('Command executed successfully!'); - }); - - it('| should get subscription for development events', async () => { - const args = [subCmd, 'get-subscription-for-development-events', '--subscription-id', subscriptionId]; - addCoveredCommand(args); - const result = await run(cmd, args, options); - expect(result).be.an('object'); - }); - - it('| should set subscription for development events', async () => { - const args = [subCmd, 'set-subscription-for-development-events', '--subscription-id', subscriptionId, - '--name', 'someName', '--events', 'AlexaDevelopmentEvent.ManifestUpdated,AlexaDevelopmentEvent.ManifestCreated']; - addCoveredCommand(args); - const result = await run(cmd, args, { ...options, parse: false }); - expect(result).include('Command executed successfully!'); - }); - - it('| should delete subscription for development events', async () => { - const args = [subCmd, 'delete-subscription-for-development-events', '--subscription-id', subscriptionId]; - addCoveredCommand(args); - const result = await run(cmd, args, { ...options, parse: false }); - expect(result).include('Command executed successfully!'); - }); - - it('| should generate catalog upload url', async () => { - const args = [subCmd, 'generate-catalog-upload-url', '-c', catalogId, '--number-of-upload-parts', 1]; - addCoveredCommand(args); - const result = await run(cmd, args, options); - expect(result).be.an('object'); - }); - - it('| should associate isp with skill', async () => { - const args = [subCmd, 'associate-isp-with-skill', '--product-id', productId, '-s', skillId]; - addCoveredCommand(args); - const result = await run(cmd, args, { ...options, parse: false }); - expect(result).include('Command executed successfully!'); - }); - - it('| should get alexa hosted skill user permissions', async () => { - const args = [subCmd, 'get-alexa-hosted-skill-user-permissions', '--hosted-skill-permission-type', 'somePermission']; - addCoveredCommand(args); - const result = await run(cmd, args, options); - expect(result).be.an('object'); - }); - - it('| should start beta test', async () => { - const args = [subCmd, 'start-beta-test', '-s', skillId]; - addCoveredCommand(args); - const result = await run(cmd, args, { ...options, parse: false }); - expect(result).include('Command executed successfully!'); - }); - - it('| should end beta test', async () => { - const args = [subCmd, 'end-beta-test', '-s', skillId]; - addCoveredCommand(args); - const result = await run(cmd, args, { ...options, parse: false }); - expect(result).include('Command executed successfully!'); - }); - - it('| should get certifications list', async () => { - const args = [subCmd, 'get-certifications-list', '-s', skillId]; - addCoveredCommand(args); - const result = await run(cmd, args, options); - expect(result).be.an('object'); - }); - - it('| should get certification review', async () => { - const args = [subCmd, 'get-certification-review', '-s', skillId, '-c', catalogId]; - addCoveredCommand(args); - const result = await run(cmd, args, options); - expect(result).be.an('object'); - }); - - it('| should get skill enablement status', async () => { - const args = [subCmd, 'get-skill-enablement-status', '-s', skillId, '-g', stage]; - addCoveredCommand(args); - const result = await run(cmd, args, { ...options, parse: false }); - expect(result).include('Command executed successfully!'); - }); - - it('| should set skill enablement', async () => { - const args = [subCmd, 'set-skill-enablement', '-s', skillId, '-g', stage]; - addCoveredCommand(args); - const result = await run(cmd, args, { ...options, parse: false }); - expect(result).include('Command executed successfully!'); - }); - - it('| should delete skill enablement', async () => { - const args = [subCmd, 'delete-skill-enablement', '-s', skillId, '-g', stage]; - addCoveredCommand(args); - const result = await run(cmd, args, { ...options, parse: false }); - expect(result).include('Command executed successfully!'); - }); - - it('| should profile nlu', async () => { - const args = [subCmd, 'profile-nlu', '-u', 'test', '--multi-turn-token', 'someToken', '-s', skillId, '-g', stage, '-l', locale]; - addCoveredCommand(args); - const result = await run(cmd, args, options); - expect(result).be.an('object'); - }); - - it('| should get interaction model', async () => { - const args = [subCmd, 'get-interaction-model', '-s', skillId, '-g', stage, '-l', locale]; - addCoveredCommand(args); - const result = await run(cmd, args, options); - expect(result).be.an('object'); - }); - - it('| should get interaction model metadata', async () => { - const args = [subCmd, 'get-interaction-model-metadata', '-s', skillId, '-g', stage, '-l', locale]; - addCoveredCommand(args); - const result = await run(cmd, args, { ...options, parse: false }); - expect(result).include('Command executed successfully!'); - }); - - it('| should set interaction model', async () => { - const args = [subCmd, 'set-interaction-model', '-s', skillId, '-g', - stage, '-l', locale, '--interaction-model', JSON.stringify(interactionModel)]; - addCoveredCommand(args); - const result = await run(cmd, args, { ...options, parse: false }); - expect(result).include('Command executed successfully!'); - }); - - it('| should list interaction model catalogs', async () => { - const args = [subCmd, 'list-interaction-model-catalogs']; - addCoveredCommand(args); - const result = await run(cmd, args, options); - expect(result).be.an('object'); - }); - - it('| should create interaction model catalog', async () => { - const args = [subCmd, 'create-interaction-model-catalog', '--catalog-name', 'name', '--catalog-description', 'someDescription']; - addCoveredCommand(args); - const result = await run(cmd, args, options); - expect(result).be.an('object'); - }); - - it('| should get interaction model catalog definition', async () => { - const args = [subCmd, 'get-interaction-model-catalog-definition', '-c', catalogId]; - addCoveredCommand(args); - const result = await run(cmd, args, options); - expect(result).be.an('object'); - }); - - it('| should delete interaction model catalog', async () => { - const args = [subCmd, 'delete-interaction-model-catalog', '-c', catalogId]; - addCoveredCommand(args); - const result = await run(cmd, args, { ...options, parse: false }); - expect(result).include('Command executed successfully!'); - }); - - it('| should get interaction model catalog update status', async () => { - const args = [subCmd, 'get-interaction-model-catalog-update-status', '-c', catalogId, '--update-request-id', updateRequestId]; - addCoveredCommand(args); - const result = await run(cmd, args, options); - expect(result).be.an('object'); - }); - - it('| should update interaction model catalog', async () => { - const args = [subCmd, 'update-interaction-model-catalog', '-c', catalogId, '--name', 'name', '--description', 'someDescription']; - addCoveredCommand(args); - const result = await run(cmd, args, { ...options, parse: false }); - expect(result).include('Command executed successfully!'); - }); - - it('| should create interaction model catalog version', async () => { - const args = [subCmd, 'create-interaction-model-catalog-version', '-c', catalogId, '--source-type', 'catalogType', '--source-url', 'catalogUrl', '--description', 'someDescription']; - addCoveredCommand(args); - const result = await run(cmd, args, { ...options, parse: false }); - expect(result).include('Command executed successfully!'); - }); - - it('| should get interaction model catalog version', async () => { - const args = [subCmd, 'get-interaction-model-catalog-version', '-c', catalogId, '--vers', version]; - addCoveredCommand(args); - const result = await run(cmd, args, options); - expect(result).be.an('object'); - }); - - it('| should delete interaction model catalog version', async () => { - const args = [subCmd, 'delete-interaction-model-catalog-version', '-c', catalogId, '--vers', version]; - addCoveredCommand(args); - const result = await run(cmd, args, { ...options, parse: false }); - expect(result).include('Command executed successfully!'); - }); - - it('| should get interaction model catalog values', async () => { - const args = [subCmd, 'get-interaction-model-catalog-values', '-c', catalogId, '--vers', version]; - addCoveredCommand(args); - const result = await run(cmd, args, options); - expect(result).be.an('object'); - }); - - it('| should get interaction model version', async () => { - const args = [subCmd, 'get-interaction-model-version', '-s', skillId, '-g', stage, '-l', locale, '--vers', version]; - addCoveredCommand(args); - const result = await run(cmd, args, options); - expect(result).be.an('object'); - }); - - it('| should list interaction model versions', async () => { - const args = [subCmd, 'list-interaction-model-versions', '-s', skillId, '-g', stage, '-l', locale]; - addCoveredCommand(args); - const result = await run(cmd, args, options); - expect(result).be.an('object'); - }); - - it('| should list interaction model slot types', async () => { - const args = [subCmd, 'list-interaction-model-slot-types']; - addCoveredCommand(args); - const result = await run(cmd, args, options); - expect(result).be.an('object'); - }); - - it('| should create interaction model slot type', async () => { - const args = [subCmd, 'create-interaction-model-slot-type', '--slot-type', slotType]; - addCoveredCommand(args); - const result = await run(cmd, args, options); - expect(result).be.an('object'); - }); - - it('| should get interaction model slot type definition', async () => { - const args = [subCmd, 'get-interaction-model-slot-type-definition', '--slot-type-id', slotTypeId]; - addCoveredCommand(args); - const result = await run(cmd, args, options); - expect(result).be.an('object'); - }); - - it('| should delete interaction model slot type', async () => { - const args = [subCmd, 'delete-interaction-model-slot-type', '--slot-type-id', slotTypeId]; - addCoveredCommand(args); - const result = await run(cmd, args, { ...options, parse: false }); - expect(result).include('Command executed successfully!'); - }); - - it('| should get interaction model slot type build status', async () => { - const args = [subCmd, 'get-interaction-model-slot-type-build-status', '--slot-type-id', slotTypeId, '--update-request-id', updateRequestId]; - addCoveredCommand(args); - const result = await run(cmd, args, options); - expect(result).be.an('object'); - }); - - it('| should update interaction model slot type', async () => { - const args = [subCmd, 'update-interaction-model-slot-type', '--slot-type-id', slotTypeId, '--slot-type-description', 'someDescription']; - addCoveredCommand(args); - const result = await run(cmd, args, { ...options, parse: false }); - expect(result).include('Command executed successfully!'); - }); - - it('| should list interaction model slot type versions', async () => { - const args = [subCmd, 'list-interaction-model-slot-type-versions', '--slot-type-id', slotTypeId]; - addCoveredCommand(args); - const result = await run(cmd, args, options); - expect(result).be.an('object'); - }); - - it('| should create interaction model slot type version', async () => { - const args = [subCmd, 'create-interaction-model-slot-type-version', '--slot-type-id', slotTypeId, '--slot-type', slotType]; - addCoveredCommand(args); - const result = await run(cmd, args, { ...options, parse: false }); - expect(result).include('Command executed successfully!'); - }); - - it('| should get interaction model slot type version', async () => { - const args = [subCmd, 'get-interaction-model-slot-type-version', '--slot-type-id', slotTypeId, '--vers', version]; - addCoveredCommand(args); - const result = await run(cmd, args, options); - expect(result).be.an('object'); - }); - - it('| should delete interaction model slot type version', async () => { - const args = [subCmd, 'delete-interaction-model-slot-type-version', '--slot-type-id', slotTypeId, '--vers', version]; - addCoveredCommand(args); - const result = await run(cmd, args, { ...options, parse: false }); - expect(result).include('Command executed successfully!'); - }); - - it('| should update interaction model slot type version', async () => { - const args = [subCmd, 'update-interaction-model-slot-type-version', '--slot-type-id', slotTypeId, '--vers', version, - '--slot-type-description', 'someDescription' - ]; - addCoveredCommand(args); - const result = await run(cmd, args, { ...options, parse: false }); - expect(result).include('Command executed successfully!'); - }); - - it('| should get skill manifest', async () => { - const args = [subCmd, 'get-skill-manifest', '-s', skillId, '-g', stage]; - addCoveredCommand(args); - const result = await run(cmd, args, options); - expect(result).be.an('object'); - }); - - it('| should update skill manifest', async () => { - const args = [subCmd, 'update-skill-manifest', '-s', skillId, '-g', stage, '--manifest', JSON.stringify(skillManifest)]; - addCoveredCommand(args); - const result = await run(cmd, args, { ...options, parse: false }); - expect(result).include('Command executed successfully!'); - }); - - it('| should get skill metrics', async () => { - const args = [subCmd, 'get-skill-metrics', '-s', skillId, '--start-time', '2017-07-21T17:32:28Z', - '--end-time', '2017-07-21T17:32:28Z', '--period', 'P3', '--metric', 'someMetric', '-g', stage, '--skill-type', 'smartHome']; - addCoveredCommand(args); - const result = await run(cmd, args, options); - expect(result).be.an('object'); - }); - - it('| should set private distribution account id', async () => { - const args = [subCmd, 'set-private-distribution-account-id', '-s', skillId, '-g', stage, '--id', 'someId']; - addCoveredCommand(args); - const result = await run(cmd, args, { ...options, parse: false }); - expect(result).include('Command executed successfully!'); - }); - - it('| should delete private distribution account id', async () => { - const args = [subCmd, 'delete-private-distribution-account-id', '-s', skillId, '-g', stage, '--id', 'someId']; - addCoveredCommand(args); - const result = await run(cmd, args, { ...options, parse: false }); - expect(result).include('Command executed successfully!'); - }); - - it('| should list private distribution accounts', async () => { - const args = [subCmd, 'list-private-distribution-accounts', '-s', skillId, '-g', stage]; - addCoveredCommand(args); - const result = await run(cmd, args, options); - expect(result).be.an('object'); - }); - - it('| should get skill simulation', async () => { - const args = [subCmd, 'get-skill-simulation', '-s', skillId, '-g', stage, '-i', simulationId]; - addCoveredCommand(args); - const result = await run(cmd, args, options); - expect(result).be.an('object'); - }); - - it('| should submit skill validation', async () => { - const args = [subCmd, 'submit-skill-validation', '-l', locale, '-s', skillId, '-g', stage]; - addCoveredCommand(args); - const result = await run(cmd, args, options); - expect(result).be.an('object'); - }); - - it('| should get skill validations', async () => { - const args = [subCmd, 'get-skill-validations', '-s', skillId, '-i', simulationId, '-g', stage]; - addCoveredCommand(args); - const result = await run(cmd, args, options); - expect(result).be.an('object'); - }); - - it('| should delete skill', async () => { - const args = [subCmd, 'delete-skill', '-s', skillId]; - addCoveredCommand(args); - const result = await run(cmd, args, { ...options, parse: false }); - expect(result).include('Command executed successfully!'); - }); - - it('| should get ssl certificates', async () => { - const args = [subCmd, 'get-ssl-certificates', '-s', skillId]; - addCoveredCommand(args); - const result = await run(cmd, args, options); - expect(result).be.an('object'); - }); - - it('| should set ssl certificates', async () => { - const args = [subCmd, 'set-ssl-certificates', '-s', skillId, '--ssl-certificate-payload', sslCertificatePayload]; - addCoveredCommand(args); - const result = await run(cmd, args, { ...options, parse: false }); - expect(result).include('Command executed successfully!'); - }); - - it('| should submit skill for certification', async () => { - const args = [subCmd, 'submit-skill-for-certification', '-s', skillId, '--publication-method', 'MANUAL_PUBLISHING']; - addCoveredCommand(args); - const result = await run(cmd, args, { ...options, parse: false }); - expect(result).include('Command executed successfully!'); - }); - - it('| should withdraw skill from certification', async () => { - const args = [subCmd, 'withdraw-skill-from-certification', '-s', skillId, '--reason', 'TEST_SKILL']; - addCoveredCommand(args); - const result = await run(cmd, args, { ...options, parse: false }); - expect(result).include('Command executed successfully!'); - }); - - it('| should create export request for skill', async () => { - const args = [subCmd, 'create-export-request-for-skill', '-s', skillId, '-g', stage]; - addCoveredCommand(args); - const result = await run(cmd, args, { ...options, parse: false }); - expect(result).include('Command executed successfully!'); - }); - - it('| should get status of export request', async () => { - const args = [subCmd, 'get-status-of-export-request', '--export-id', 'someExportId']; - addCoveredCommand(args); - const result = await run(cmd, args, options); - expect(result).be.an('object'); - }); - - it('| should create skill package', async () => { - const args = [subCmd, 'create-skill-package', '--location', location]; - addCoveredCommand(args); - const result = await run(cmd, args, { ...options, parse: false }); - expect(result).include('Command executed successfully!'); - }); - - it('| should import skill package', async () => { - const args = [subCmd, 'import-skill-package', '--location', location, '-s', skillId]; - addCoveredCommand(args); - const result = await run(cmd, args, { ...options, parse: false }); - expect(result).include('Command executed successfully!'); - }); - - it('| should get import status', async () => { - const args = [subCmd, 'get-import-status', '--import-id', 'someImportId']; - addCoveredCommand(args); - const result = await run(cmd, args, options); - expect(result).be.an('object'); - }); - - it('| should create upload url', async () => { - const args = [subCmd, 'create-upload-url']; - addCoveredCommand(args); - const result = await run(cmd, args, options); - expect(result).be.an('object'); - }); - - it('| should query development audit logs', async () => { - const args = [subCmd, 'query-development-audit-logs']; - addCoveredCommand(args); - const result = await run(cmd, args, options); - expect(result).be.an('object'); - }); - - it('| should invoke skill end point', async () => { - const args = [subCmd, 'invoke-skill', '-s', skillId, - '--endpoint-region', 'someRegion', '--skill-request-body', JSON.stringify({})]; - addCoveredCommand(args); - const result = await run(cmd, args, options); - expect(result).be.an('object'); - }); - - it('| should invoke skill end point', async () => { - const args = [subCmd, 'invoke-skill-end-point', '-s', skillId, '-g', stage, - '--endpoint-region', 'someRegion', '--skill-request-body', JSON.stringify({})]; - addCoveredCommand(args); - const result = await run(cmd, args, options); - expect(result).be.an('object'); - }); - - it('| should list nlu evaluations', async () => { - const args = [subCmd, 'list-nlu-evaluations', '-s', skillId]; - addCoveredCommand(args); - const result = await run(cmd, args, options); - expect(result).be.an('object'); - }); - - it('| should get nlu evaluation', async () => { - const args = [subCmd, 'get-nlu-evaluation', '-s', skillId, '--evaluation-id', evaluationId]; - addCoveredCommand(args); - const result = await run(cmd, args, options); - expect(result).be.an('object'); - }); - - it('| should get result for nlu evaluations', async () => { - const args = [subCmd, 'get-result-for-nlu-evaluations', '-s', skillId, '--evaluation-id', evaluationId]; - addCoveredCommand(args); - const result = await run(cmd, args, options); - expect(result).be.an('object'); - }); - - it('| should list nlu annotation sets', async () => { - const args = [subCmd, 'list-nlu-annotation-sets', '-s', skillId]; - addCoveredCommand(args); - const result = await run(cmd, args, options); - expect(result).be.an('object'); - }); - - it('| should create nlu annotation set', async () => { - const args = [subCmd, 'create-nlu-annotation-set', '-s', skillId, '-l', locale, '--name', name]; - addCoveredCommand(args); - const result = await run(cmd, args, options); - expect(result).be.an('object'); - }); - - it('| should create nlu evaluations', async () => { - const args = [subCmd, 'create-nlu-evaluations', '-g', stage, '-l', locale, '--source-annotation-id', sourceAnnotationId, '-s', skillId]; - addCoveredCommand(args); - const result = await run(cmd, args, options); - expect(result).be.an('object'); - }); - - it('| should get properties for nlu annotation sets', async () => { - const args = [subCmd, 'get-properties-for-nlu-annotation-sets', '-s', skillId, '--annotation-id', annotationId]; - addCoveredCommand(args); - const result = await run(cmd, args, options); - expect(result).be.an('object'); - }); - - it('| should update properties for nlu annotation sets', async () => { - const args = [subCmd, 'update-properties-for-nlu-annotation-sets', '-s', skillId, '--annotation-id', annotationId, '--name', name]; - addCoveredCommand(args); - const result = await run(cmd, args, { ...options, parse: false }); - expect(result).include('Command executed successfully!'); - }); - - it('| should delete properties for nlu annotation sets', async () => { - const args = [subCmd, 'delete-properties-for-nlu-annotation-sets', '-s', skillId, '--annotation-id', annotationId]; - addCoveredCommand(args); - const result = await run(cmd, args, { ...options, parse: false }); - expect(result).include('Command executed successfully!'); - }); - - it('| should get annotations for nlu annotation sets', async () => { - const args = [subCmd, 'get-annotations-for-nlu-annotation-sets', '-s', skillId, '--annotation-id', annotationId, '--accept', accept]; - addCoveredCommand(args); - const result = await run(cmd, args, options); - expect(result).be.an('object'); - }); - - it('| should update annotations for nlu annotation sets', async () => { - const args = [subCmd, 'update-annotations-for-nlu-annotation-sets', '-s', skillId, - '--annotation-id', annotationId, '--content-type', contentType, - '--update-nlu-annotation-set-annotations-request', updateNluAnnotationSetAnnotationsRequest]; - addCoveredCommand(args); - const result = await run(cmd, args, { ...options, parse: false }); - expect(result).include('Command executed successfully!'); - }); - - it('| should get conflicts for interaction model conflict detection', async () => { - const args = [subCmd, 'get-conflicts-for-interaction-model', '-s', skillId, '-l', locale, '-g', stage, '--vers', '1']; - addCoveredCommand(args); - const result = await run(cmd, args, options); - expect(result).be.an('object'); - }); - - it('| should get job status for interaction model conflict detection', async () => { - const args = [subCmd, 'get-conflict-detection-job-status-for-interaction-model', '-s', skillId, '-l', locale, '-g', stage, '--vers', '1']; - addCoveredCommand(args); - const result = await run(cmd, args, options); - expect(result).be.an('object'); - }); - - it('| should get skill credential', async () => { - const args = [subCmd, 'get-skill-credentials', '-s', skillId]; - addCoveredCommand(args); - const result = await run(cmd, args, options); - expect(result).be.an('object'); - }); - - it('| should list asr annotation sets', async () => { - const args = [subCmd, 'list-asr-annotation-sets', '-s', skillId]; - addCoveredCommand(args); - const result = await run(cmd, args, options); - expect(result).be.an('object'); - }); - - it('| should create asr annotation set', async () => { - const args = [subCmd, 'create-asr-annotation-set', '-s', skillId, '--name', name]; - addCoveredCommand(args); - const result = await run(cmd, args, options); - expect(result).be.an('object'); - }); - - it('| should get asr annotation set', async () => { - const args = [subCmd, 'get-asr-annotation-set', '-s', skillId, '--annotation-set-id', annotationSetId]; - addCoveredCommand(args); - const result = await run(cmd, args, options); - expect(result).be.an('object'); - }); - - it('| should set asr annotation set', async () => { - const args = [subCmd, 'set-asr-annotation-set', '-s', skillId, '--annotation-set-id', annotationSetId, '--name', name]; - addCoveredCommand(args); - const result = await run(cmd, args, { ...options, parse: false }); - expect(result).include('Command executed successfully!'); - }); - - it('| should delete asr annotation set', async () => { - const args = [subCmd, 'delete-asr-annotation-set', '-s', skillId, '--annotation-set-id', annotationSetId]; - addCoveredCommand(args); - const result = await run(cmd, args, { ...options, parse: false }); - expect(result).include('Command executed successfully!'); - }); - - it('| should get annotations for asr annotation set', async () => { - const args = [subCmd, 'get-annotations-for-asr-annotation-set', '-s', skillId, '--annotation-set-id', annotationSetId, '--accept', accept]; - addCoveredCommand(args); - const result = await run(cmd, args, options); - expect(result).be.an('object'); - }); - - it('| should set annotations for asr annotation set', async () => { - const args = [subCmd, 'set-annotations-for-asr-annotation-set', '-s', skillId, '--annotation-set-id', - annotationSetId, '--annotations', annotations]; - addCoveredCommand(args); - const result = await run(cmd, args, { ...options, parse: false }); - expect(result).include('Command executed successfully!'); - }); - - it('| should list asr evaluations', async () => { - const args = [subCmd, 'list-asr-evaluations', '-s', skillId]; - addCoveredCommand(args); - const result = await run(cmd, args, options); - expect(result).be.an('object'); - }); - - it('| should create asr evaluation', async () => { - const args = [subCmd, 'create-asr-evaluation', '--stage', stage, '--locale', - locale, '--annotation-set-id', annotationSetId, '-s', skillId]; - addCoveredCommand(args); - const result = await run(cmd, args, options); - expect(result).be.an('object'); - }); - - it('| should get asr evaluation status', async () => { - const args = [subCmd, 'get-asr-evaluation-status', '-s', skillId, '--evaluation-id', evaluationId]; - addCoveredCommand(args); - const result = await run(cmd, args, options); - expect(result).be.an('object'); - }); - - it('| should delete asr evaluation', async () => { - const args = [subCmd, 'delete-asr-evaluation', '-s', skillId, '--evaluation-id', evaluationId]; - addCoveredCommand(args); - const result = await run(cmd, args, { ...options, parse: false }); - expect(result).include('Command executed successfully!'); - }); - - it('| should list asr evaluations results', async () => { - const args = [subCmd, 'list-asr-evaluations-results', '-s', skillId, '--evaluation-id', evaluationId]; - addCoveredCommand(args); - const result = await run(cmd, args, options); - expect(result).be.an('object'); - }); - - it('| should list interaction model catalog versions', async () => { - const args = [subCmd, 'list-interaction-model-catalog-versions', '-c', catalogId]; - addCoveredCommand(args); - const result = await run(cmd, args, options); - expect(result).be.an('object'); - }); - - it('| should clone locale', async () => { - const args = [subCmd, 'clone-locale', '-s', skillId, '--source-locale', sourceLocale, '--target-locales', targetLocales]; - addCoveredCommand(args); - const result = await run(cmd, args, { ...options, parse: false }); - expect(result).include('Command executed successfully!'); - }); - - it('| should get clone locale status', async () => { - const args = [subCmd, 'get-clone-locale-status', '-s', skillId, '--clone-locale-request-id', cloneLocaleRequestId]; - addCoveredCommand(args); - const result = await run(cmd, args, options); - expect(result).be.an('object'); - }); - - it('| should list versions for skill', async () => { - const args = [subCmd, 'list-versions-for-skill', '-s', skillId]; - addCoveredCommand(args); - const result = await run(cmd, args, options); - expect(result).be.an('object'); - }); - - it('| should rollback skill', async () => { - const args = [subCmd, 'rollback-skill', '-s', skillId, '--target-version', targetVersion]; - addCoveredCommand(args); - const result = await run(cmd, args, options); - expect(result).be.an('object'); - }); - - it('| should get rollback for skill', async () => { - const args = [subCmd, 'get-rollback-for-skill', '-s', skillId, '--rollback-request-id', rollbackRequestId]; - addCoveredCommand(args); - const result = await run(cmd, args, options); - expect(result).be.an('object'); - }); - - it('| should publish skill', async () => { - const args = [subCmd, 'publish-skill', '-s', skillId, '--accept-language', acceptLanguage, '--publishes-at-date', '2019-04-12T23:20:50.52Z']; - addCoveredCommand(args); - const result = await run(cmd, args, options); - expect(result).be.an('object'); - }); - - it('| should get skill publications', async () => { - const args = [subCmd, 'get-skill-publications', '-s', skillId, '--accept-language', acceptLanguage]; - addCoveredCommand(args); - const result = await run(cmd, args, options); - expect(result).be.an('object'); - }); - - it('| should list all the job defintions for IM', async () => { - const args = [subCmd, 'list-job-definitions-for-interaction-model']; - addCoveredCommand(args); - const result = await run(cmd, args, options); - expect(result).be.an('object'); - }); - - it('| should create job definition for IM', async () => { - const args = [subCmd, 'create-job-definition-for-interaction-model', - '--job-definition', interactionModelJobDefinition]; - addCoveredCommand(args); - const result = await run(cmd, args, options); - expect(result).be.an('object'); - }); - - it('| should get job definition for IM', async () => { - const args = [subCmd, 'get-job-definition-for-interaction-model', '--job-id', imJobId]; - addCoveredCommand(args); - const result = await run(cmd, args, options); - expect(result).be.an('object'); - }); - - it('| should delete job definition for IM', async () => { - const args = [subCmd, 'delete-job-definition-for-interaction-model', '--job-id', imJobId]; - addCoveredCommand(args); - const result = await run(cmd, args, { ...options, parse: false }); - expect(result).include('Command executed successfully!'); - }); - - it('| should set job status for IM', async () => { - const args = [subCmd, 'set-job-status-for-interaction-model', '--job-id', imJobId, '--status', imJobStatus]; - addCoveredCommand(args); - const result = await run(cmd, args, { ...options, parse: false }); - expect(result).include('Command executed successfully!'); - }); - - it('| should list all the job executions for IM', async () => { - const args = [subCmd, 'list-job-executions-for-interaction-model', '--job-id', imJobId]; - addCoveredCommand(args); - const result = await run(cmd, args, options); - expect(result).be.an('object'); - }); - - it('| should cancel next job execution for IMJob', async () => { - const args = [subCmd, 'cancel-next-job-execution-for-interaction-model', '--job-id', imJobId, '--execution-id', imExecutionId]; - addCoveredCommand(args); - const result = await run(cmd, args, { ...options, parse: false }); - expect(result).include('Command executed successfully!'); - }); - - it('| should get resource schema', async () => { - const args = [subCmd, 'get-resource-schema', '--resource', 'manifest']; - addCoveredCommand(args); - const result = await run(cmd, args, options); - expect(result).be.an('object'); - }); - - it('| should list smarthome capability test plans', async () => { - const args = [subCmd, 'list-smarthome-capability-test-plans', '-s', skillId]; - addCoveredCommand(args); - const result = await run(cmd, args, options); - expect(result).be.an('object'); - }); - - it('| should get smarthome capablity evaluation results', async () => { - const args = [subCmd, 'get-smarthome-capablity-evaluation-results', '-s', skillId, '--evaluation-id', evaluationId]; - addCoveredCommand(args); - const result = await run(cmd, args, options); - expect(result).be.an('object'); - }); - - it('| should get smart home capability evaluation', async () => { - const args = [subCmd, 'get-smart-home-capability-evaluation', '-s', skillId, '--evaluation-id', evaluationId]; - addCoveredCommand(args); - const result = await run(cmd, args, options); - expect(result).be.an('object'); - }); - - it('| should list smarthome capability evaluations', async () => { - const args = [subCmd, 'list-smarthome-capability-evaluations', '-s', skillId]; - addCoveredCommand(args); - const result = await run(cmd, args, options); - expect(result).be.an('object'); - }); - - it('| should create smarthome capability evaluation', async () => { - const args = [subCmd, 'create-smarthome-capability-evaluation', '-s', skillId, '--capability-test-plan-id', 1, '--endpoint-endpoint-id', 2]; - addCoveredCommand(args); - const result = await run(cmd, args, options); - expect(result).be.an('object'); - }); - - it('| should list all experiments associated with this skill id', async () => { - const args = [subCmd, 'list-experiments', '-s', skillId]; - addCoveredCommand(args); - const result = await run(cmd, args, options); - expect(result).be.an('object'); - }); - - it('| should create a new experiment for a skill', async () => { - const args = [subCmd, 'create-experiment', '-s', skillId, '--experiment-name', experimentName, '--experiment-description', experimentDescription, '--experiment-type', experimentType, '--experiment-planned-duration', experimentPlannedDuration, '--experiment-exposure-percentage', experimentExposurePercentage, '--experiment-metric-configurations', experimentMetricConfigurations]; - addCoveredCommand(args); - const result = await run(cmd, args, { ...options, parse: false }); - expect(result).include('Command executed successfully!'); - }); - - it('| should update an existing experiment for a skill', async () => { - const args = [subCmd, 'update-experiment', '-s', skillId, '--experiment-id', experimentId, '--experiment-description', experimentDescription, '--experiment-planned-duration', experimentPlannedDuration, '--experiment-exposure-percentage', experimentExposurePercentage, '--experiment-metric-configurations', experimentMetricConfigurations]; - addCoveredCommand(args); - const result = await run(cmd, args, { ...options, parse: false }); - expect(result).include('Command executed successfully!'); - }); - - it('| should retrieve an existing experiment for a skill', async () => { - const args = [subCmd, 'get-experiment', '-s', skillId, '--experiment-id', experimentId]; - addCoveredCommand(args); - const result = await run(cmd, args, options); - expect(result).be.an('object'); - }); - - it('| should delete an existing experiment for a skill', async () => { - const args = [subCmd, 'delete-experiment', '-s', skillId, '--experiment-id', experimentId]; - addCoveredCommand(args); - const result = await run(cmd, args, { ...options, parse: false }); - expect(result).include('Command executed successfully!'); - }); - - it('| should update the exposure of an experiment that is in CREATED or RUNNING state.', async () => { - const args = [subCmd, 'update-exposure', '-s', skillId, '--experiment-id', experimentId, '--exposure-percentage', experimentExposurePercentage]; - addCoveredCommand(args); - const result = await run(cmd, args, { ...options, parse: false }); - expect(result).include('Command executed successfully!'); - }); - - it('| should retrieve the current user\'s customer treatment override for an existing A/B Test experiment', async () => { - const args = [subCmd, 'get-customer-treatment-override', '-s', skillId, '--experiment-id', experimentId]; - addCoveredCommand(args); - const result = await run(cmd, args, options); - expect(result).be.an('object'); - }); - - it('| should add the requesting user\'s customer treatment override to an existing experiment.', async () => { - const args = [subCmd, 'set-customer-treatment-override', '-s', skillId, '--experiment-id', experimentId, '--treatment-id', treatmentId]; - addCoveredCommand(args); - const result = await run(cmd, args, { ...options, parse: false }); - expect(result).include('Command executed successfully!'); - }); - - it('| should retrieve the current state of the experiment.', async () => { - const args = [subCmd, 'get-experiment-state', '-s', skillId, '--experiment-id', experimentId]; - addCoveredCommand(args); - const result = await run(cmd, args, options); - expect(result).be.an('object'); - }); - - it('| should request an action on the experiment to move it to the targetState.', async () => { - const args = [subCmd, 'manage-experiment-state', '-s', skillId, '--experiment-id', experimentId, '--target-state', targetState]; - addCoveredCommand(args); - const result = await run(cmd, args, { ...options, parse: false }); - expect(result).include('Command executed successfully!'); - }); - - it('| should get a list of all metric snapshots associated with this experiment id.', async () => { - const args = [subCmd, 'list-experiment-metric-snapshots', '-s', skillId, '--experiment-id', experimentId]; - addCoveredCommand(args); - const result = await run(cmd, args, options); - expect(result).be.an('object'); - }); - - it('| should gets a list of all metric data associated with this experiment\'s metric snapshot.', async () => { - const args = [subCmd, 'get-experiment-metric-snapshot', '-s', skillId, '--experiment-id', experimentId, '--metric-snapshot-id', metricSnapShotId]; - addCoveredCommand(args); - const result = await run(cmd, args, options); - expect(result).be.an('object'); - }); - - after(() => { - mockSmapiServer.kill(); - mockLwaServer.kill(); - expect(Array.from(untestedCommands), 'should not have untested commands').eql([]); - }); -}); + before(async () => { + mockSmapiServer = await startMockSmapiServer(); + mockLwaServer = await startMockLwaServer(); + }); + + it("| should display vendor list", async () => { + const args = [subCmd, "get-vendor-list"]; + addCoveredCommand(args); + const result = await run(cmd, args, options); + expect(result).be.an("object"); + }); + + it("| should list skills for vendor", async () => { + const args = [subCmd, "list-skills-for-vendor", "--max-results", 1]; + addCoveredCommand(args); + const result = await run(cmd, args, options); + expect(result).be.an("object"); + }); + + it("| should create skill for vendor", async () => { + const args = [subCmd, "create-skill-for-vendor", "--manifest", JSON.stringify(skillManifest)]; + addCoveredCommand(args); + const result = await run(cmd, args, options); + expect(result).be.an("object"); + }); + + it("| should get skill status", async () => { + const args = [subCmd, "get-skill-status", "-s", skillId]; + addCoveredCommand(args); + const result = await run(cmd, args, options); + expect(result).be.an("object"); + }); + + it("| should display catalog list", async () => { + const args = [subCmd, "list-catalogs-for-vendor"]; + addCoveredCommand(args); + const result = await run(cmd, args, options); + expect(result).be.an("object"); + }); + + it("| should create catalog", async () => { + const args = [ + subCmd, + "create-catalog", + "--title", + "test", + "--type", + "AMAZON.BroadcastChannel", + "--usage", + "AlexaMusic.Catalog.BroadcastChannel", + ]; + addCoveredCommand(args); + const result = await run(cmd, args, options); + expect(result).be.an("object"); + }); + + it("| should get catalog information", async () => { + const args = [subCmd, "get-catalog", "-c", "someCatalogId"]; + addCoveredCommand(args); + const result = await run(cmd, args, options); + expect(result).be.an("object"); + }); + + it("| should associate skill with catalog", async () => { + const args = [subCmd, "associate-catalog-with-skill", "-c", catalogId, "-s", skillId]; + addCoveredCommand(args); + const result = await run(cmd, args, {...options, parse: false}); + expect(result).include("Command executed successfully!"); + }); + + it("| should create catalog upload", async () => { + const args = [subCmd, "create-catalog-upload", "-c", catalogId, "--catalog-upload-request-body", JSON.stringify(catalogUploadBody)]; + addCoveredCommand(args); + const result = await run(cmd, args, {...options, parse: false}); + expect(result).include("Command executed successfully!"); + }); + + it("| should display catalog list for skill", async () => { + const args = [subCmd, "list-catalogs-for-skill", "-s", skillId, "--max-results", 1]; + addCoveredCommand(args); + const result = await run(cmd, args, options); + expect(result).be.an("object"); + }); + + it("| should display alexa hosted skill metadata", async () => { + const args = [subCmd, "get-alexa-hosted-skill-metadata", "-s", skillId]; + addCoveredCommand(args); + const result = await run(cmd, args, options); + expect(result).be.an("object"); + }); + + it("| should display utterance data", async () => { + const args = [subCmd, "get-utterance-data", "-s", skillId, "--locale", locale, "--sort-direction", "asc"]; + addCoveredCommand(args); + const result = await run(cmd, args, options); + expect(result).be.an("object"); + }); + + it("| should add testers to beta test", async () => { + const args = [subCmd, "add-testers-to-beta-test", "-s", skillId, "--testers-emails", testersEmails]; + addCoveredCommand(args); + const result = await run(cmd, args, {...options, parse: false}); + expect(result).include("Command executed successfully!"); + }); + + it("| should get list of testers", async () => { + const args = [subCmd, "get-list-of-testers", "-s", skillId, "--max-results", 1]; + addCoveredCommand(args); + const result = await run(cmd, args, options); + expect(result).be.an("object"); + }); + + it("| should request feedback from testers", async () => { + const args = [subCmd, "request-feedback-from-testers", "-s", skillId, "--testers-emails", testersEmails]; + addCoveredCommand(args); + const result = await run(cmd, args, {...options, parse: false}); + expect(result).include("Command executed successfully!"); + }); + + it("| should send reminder to testers", async () => { + const args = [subCmd, "send-reminder-to-testers", "-s", skillId, "--testers-emails", testersEmails]; + addCoveredCommand(args); + const result = await run(cmd, args, {...options, parse: false}); + expect(result).include("Command executed successfully!"); + }); + + it("| should remove testers from beta test", async () => { + const args = [subCmd, "remove-testers-from-beta-test", "-s", skillId, "--testers-emails", testersEmails]; + addCoveredCommand(args); + const result = await run(cmd, args, {...options, parse: false}); + expect(result).include("Command executed successfully!"); + }); + + it("| should update interaction model catalog version and return version number", async () => { + const args = [subCmd, "update-interaction-model-catalog-version", "-c", catalogId, "--vers", 1, "--description", "test"]; + addCoveredCommand(args); + const result = await run(cmd, args, {...options, parse: false}); + expect(result).include("Command executed successfully!"); + }); + + it("| should simulate skill", async () => { + const args = [subCmd, "simulate-skill", "-s", skillId, "--device-locale", locale, "-g", stage, "--input-content", "hello"]; + addCoveredCommand(args); + const result = await run(cmd, args, options); + expect(result).be.an("object"); + }); + + it("| should create beta test", async () => { + const args = [subCmd, "create-beta-test", "-s", skillId, "--feedback-email", "someemail@email.com"]; + addCoveredCommand(args); + const result = await run(cmd, args, {...options, parse: false}); + expect(result).include("Command executed successfully!"); + }); + + it("| should update beta test", async () => { + const args = [subCmd, "update-beta-test", "-s", skillId, "--feedback-email", "test2@gmail.com"]; + addCoveredCommand(args); + const result = await run(cmd, args, {...options, parse: false}); + expect(result).include("Command executed successfully!"); + }); + + it("| should retrieve beta test", async () => { + const args = [subCmd, "get-beta-test", "-s", skillId]; + addCoveredCommand(args); + const result = await run(cmd, args, options); + expect(result).be.an("object"); + }); + + it("| should list uploads for catalog", async () => { + const args = [subCmd, "list-uploads-for-catalog", "-c", catalogId, "--max-results", 1]; + addCoveredCommand(args); + const result = await run(cmd, args, options); + expect(result).be.an("object"); + }); + + it("| should list isp for vendor", async () => { + const args = [subCmd, "get-isp-list-for-vendor", "--max-results", 1]; + addCoveredCommand(args); + const result = await run(cmd, args, options); + expect(result).be.an("object"); + }); + + it("| should list isp for skill id ", async () => { + const args = [subCmd, "get-isp-list-for-skill-id", "-s", skillId, "-g", stage, "--max-results", 1]; + addCoveredCommand(args); + const result = await run(cmd, args, options); + expect(result).be.an("object"); + }); + + it("| should update account linking", async () => { + const args = [ + subCmd, + "update-account-linking-info", + "-s", + skillId, + "-g", + stage, + "--account-linking-request", + JSON.stringify(accountLinkingRequest), + ]; + addCoveredCommand(args); + const result = await run(cmd, args, {...options, parse: false}); + expect(result).include("Command executed successfully!"); + }); + + it("| should retrieve account linking", async () => { + const args = [subCmd, "get-account-linking-info", "-s", skillId, "-g", stage]; + addCoveredCommand(args); + const result = await run(cmd, args, options); + expect(result).be.an("object"); + }); + + it("| should delete account linking", async () => { + const args = [subCmd, "delete-account-linking-info", "-s", skillId, "-g", stage]; + addCoveredCommand(args); + const result = await run(cmd, args, {...options, parse: false}); + expect(result).include("Command executed successfully!"); + }); + + it("| should create isp", async () => { + const args = [subCmd, "create-isp-for-vendor", "--create-in-skill-product-request", JSON.stringify(inSkillProductRequestBody)]; + addCoveredCommand(args); + const result = await run(cmd, args, options); + expect(result).be.an("object"); + }); + + it("| should get isp definition", async () => { + const args = [subCmd, "get-isp-definition", "--product-id", productId, "-g", stage]; + addCoveredCommand(args); + const result = await run(cmd, args, options); + expect(result).be.an("object"); + }); + + it("| should reset entitlement for product", async () => { + const args = [subCmd, "reset-entitlement-for-product", "--product-id", productId, "-g", stage]; + addCoveredCommand(args); + const result = await run(cmd, args, {...options, parse: false}); + expect(result).include("Command executed successfully!"); + }); + + it("| should get isp associated skills", async () => { + const args = [subCmd, "get-isp-associated-skills", "--product-id", productId, "-g", stage]; + addCoveredCommand(args); + const result = await run(cmd, args, options); + expect(result).be.an("object"); + }); + + it("| should disassociate isp with skill", async () => { + const args = [subCmd, "disassociate-isp-with-skill", "--product-id", productId, "-s", skillId]; + addCoveredCommand(args); + const result = await run(cmd, args, {...options, parse: false}); + expect(result).include("Command executed successfully!"); + }); + + it("| should retrieve isp summary", async () => { + const args = [subCmd, "get-isp-summary", "--product-id", productId, "-g", stage]; + addCoveredCommand(args); + const result = await run(cmd, args, options); + expect(result).be.an("object"); + }); + + it("| should update isp for product", async () => { + const args = [ + subCmd, + "update-isp-for-product", + "--product-id", + productId, + "-g", + stage, + "--in-skill-product", + JSON.stringify(inSkillProductRequestBody), + ]; + addCoveredCommand(args); + const result = await run(cmd, args, {...options, parse: false}); + expect(result).include("Command executed successfully!"); + }); + + it("| should delete isp for product", async () => { + const args = [subCmd, "delete-isp-for-product", "--product-id", productId, "-g", stage]; + addCoveredCommand(args); + const result = await run(cmd, args, {...options, parse: false}); + expect(result).include("Command executed successfully!"); + }); + + it("| should create content upload", async () => { + const args = [subCmd, "create-content-upload", "-c", catalogId, "--number-of-upload-parts", 1]; + addCoveredCommand(args); + const result = await run(cmd, args, options); + expect(result).be.an("object"); + }); + + it("| should generate credentials for alexa hosted skill", async () => { + const args = [ + subCmd, + "generate-credentials-for-alexa-hosted-skill", + "-s", + skillId, + "--repository-url", + "https://git-codecommit.us-east-1.amazonaws.com/v1/repos/e9ac9d7f-5c4f-4c3b-8e41-1b347f625d95", + "--repository-type", + "GIT", + ]; + addCoveredCommand(args); + const result = await run(cmd, args, options); + expect(result).be.an("object"); + }); + + it("| should get content upload by id", async () => { + const args = [subCmd, "get-content-upload-by-id", "-c", catalogId, "--upload-id", uploadId]; + addCoveredCommand(args); + const result = await run(cmd, args, options); + expect(result).be.an("object"); + }); + + it("| should complete catalog upload", async () => { + const args = [subCmd, "complete-catalog-upload", "-c", catalogId, "--upload-id", uploadId, "--part-e-tags", partETags]; + addCoveredCommand(args); + const result = await run(cmd, args, {...options, parse: false}); + expect(result).include("Command executed successfully!"); + }); + + it("| should list subscribers for development events", async () => { + const args = [subCmd, "list-subscribers-for-development-events"]; + addCoveredCommand(args); + const result = await run(cmd, args, options); + expect(result).be.an("object"); + }); + + it("| should create subscriber for development events", async () => { + const args = [subCmd, "create-subscriber-for-development-events", "--create-subscriber-request", createSubscriptionRequest]; + addCoveredCommand(args); + const result = await run(cmd, args, {...options, parse: false}); + expect(result).include("Command executed successfully!"); + }); + + it("| should get subscriber for development events", async () => { + const args = [subCmd, "get-subscriber-for-development-events", "--subscriber-id", subscriberId]; + addCoveredCommand(args); + const result = await run(cmd, args, options); + expect(result).be.an("object"); + }); + + it("| should set subscriber for development events", async () => { + const args = [ + subCmd, + "set-subscriber-for-development-events", + "--subscriber-id", + subscriberId, + "--update-subscriber-request", + updateSubscriptionRequest, + ]; + addCoveredCommand(args); + const result = await run(cmd, args, {...options, parse: false}); + expect(result).include("Command executed successfully!"); + }); + + it("| should delete subscriber for development events", async () => { + const args = [subCmd, "delete-subscriber-for-development-events", "--subscriber-id", subscriberId]; + addCoveredCommand(args); + const result = await run(cmd, args, {...options, parse: false}); + expect(result).include("Command executed successfully!"); + }); + + it("| should list subscriptions for development events", async () => { + const args = [subCmd, "list-subscriptions-for-development-events"]; + addCoveredCommand(args); + const result = await run(cmd, args, options); + expect(result).be.an("object"); + }); + + it("| should create subscription for development events", async () => { + const args = [ + subCmd, + "create-subscription-for-development-events", + "--name", + "someName", + "--events", + "AlexaDevelopmentEvent.ManifestUpdat", + "--subscriber-id", + subscriberId, + ]; + addCoveredCommand(args); + const result = await run(cmd, args, {...options, parse: false}); + expect(result).include("Command executed successfully!"); + }); + + it("| should get subscription for development events", async () => { + const args = [subCmd, "get-subscription-for-development-events", "--subscription-id", subscriptionId]; + addCoveredCommand(args); + const result = await run(cmd, args, options); + expect(result).be.an("object"); + }); + + it("| should set subscription for development events", async () => { + const args = [ + subCmd, + "set-subscription-for-development-events", + "--subscription-id", + subscriptionId, + "--name", + "someName", + "--events", + "AlexaDevelopmentEvent.ManifestUpdated,AlexaDevelopmentEvent.ManifestCreated", + ]; + addCoveredCommand(args); + const result = await run(cmd, args, {...options, parse: false}); + expect(result).include("Command executed successfully!"); + }); + + it("| should delete subscription for development events", async () => { + const args = [subCmd, "delete-subscription-for-development-events", "--subscription-id", subscriptionId]; + addCoveredCommand(args); + const result = await run(cmd, args, {...options, parse: false}); + expect(result).include("Command executed successfully!"); + }); + + it("| should generate catalog upload url", async () => { + const args = [subCmd, "generate-catalog-upload-url", "-c", catalogId, "--number-of-upload-parts", 1]; + addCoveredCommand(args); + const result = await run(cmd, args, options); + expect(result).be.an("object"); + }); + + it("| should associate isp with skill", async () => { + const args = [subCmd, "associate-isp-with-skill", "--product-id", productId, "-s", skillId]; + addCoveredCommand(args); + const result = await run(cmd, args, {...options, parse: false}); + expect(result).include("Command executed successfully!"); + }); + + it('| should get alexa hosted skill user permissions', async () => { + const args = [subCmd, 'get-alexa-hosted-skill-user-permissions', '--hosted-skill-permission-type', 'somePermission']; + addCoveredCommand(args); + const result = await run(cmd, args, options); + expect(result).be.an('object'); + }); + + it("| should start beta test", async () => { + const args = [subCmd, "start-beta-test", "-s", skillId]; + addCoveredCommand(args); + const result = await run(cmd, args, {...options, parse: false}); + expect(result).include("Command executed successfully!"); + }); + + it("| should end beta test", async () => { + const args = [subCmd, "end-beta-test", "-s", skillId]; + addCoveredCommand(args); + const result = await run(cmd, args, {...options, parse: false}); + expect(result).include("Command executed successfully!"); + }); + + it("| should get certifications list", async () => { + const args = [subCmd, "get-certifications-list", "-s", skillId]; + addCoveredCommand(args); + const result = await run(cmd, args, options); + expect(result).be.an("object"); + }); + + it("| should get certification review", async () => { + const args = [subCmd, "get-certification-review", "-s", skillId, "-c", catalogId]; + addCoveredCommand(args); + const result = await run(cmd, args, options); + expect(result).be.an("object"); + }); + + it("| should get skill enablement status", async () => { + const args = [subCmd, "get-skill-enablement-status", "-s", skillId, "-g", stage]; + addCoveredCommand(args); + const result = await run(cmd, args, {...options, parse: false}); + expect(result).include("Command executed successfully!"); + }); + + it("| should set skill enablement", async () => { + const args = [subCmd, "set-skill-enablement", "-s", skillId, "-g", stage]; + addCoveredCommand(args); + const result = await run(cmd, args, {...options, parse: false}); + expect(result).include("Command executed successfully!"); + }); + + it("| should delete skill enablement", async () => { + const args = [subCmd, "delete-skill-enablement", "-s", skillId, "-g", stage]; + addCoveredCommand(args); + const result = await run(cmd, args, {...options, parse: false}); + expect(result).include("Command executed successfully!"); + }); + + it("| should profile nlu", async () => { + const args = [subCmd, "profile-nlu", "-u", "test", "--multi-turn-token", "someToken", "-s", skillId, "-g", stage, "-l", locale]; + addCoveredCommand(args); + const result = await run(cmd, args, options); + expect(result).be.an("object"); + }); + + it("| should get interaction model", async () => { + const args = [subCmd, "get-interaction-model", "-s", skillId, "-g", stage, "-l", locale]; + addCoveredCommand(args); + const result = await run(cmd, args, options); + expect(result).be.an("object"); + }); + + it("| should get interaction model metadata", async () => { + const args = [subCmd, "get-interaction-model-metadata", "-s", skillId, "-g", stage, "-l", locale]; + addCoveredCommand(args); + const result = await run(cmd, args, {...options, parse: false}); + expect(result).include("Command executed successfully!"); + }); + + it("| should set interaction model", async () => { + const args = [ + subCmd, + "set-interaction-model", + "-s", + skillId, + "-g", + stage, + "-l", + locale, + "--interaction-model", + JSON.stringify(interactionModel), + ]; + addCoveredCommand(args); + const result = await run(cmd, args, {...options, parse: false}); + expect(result).include("Command executed successfully!"); + }); + + it("| should list interaction model catalogs", async () => { + const args = [subCmd, "list-interaction-model-catalogs"]; + addCoveredCommand(args); + const result = await run(cmd, args, options); + expect(result).be.an("object"); + }); + + it("| should create interaction model catalog", async () => { + const args = [subCmd, "create-interaction-model-catalog", "--catalog-name", "name", "--catalog-description", "someDescription"]; + addCoveredCommand(args); + const result = await run(cmd, args, options); + expect(result).be.an("object"); + }); + + it("| should get interaction model catalog definition", async () => { + const args = [subCmd, "get-interaction-model-catalog-definition", "-c", catalogId]; + addCoveredCommand(args); + const result = await run(cmd, args, options); + expect(result).be.an("object"); + }); + + it("| should delete interaction model catalog", async () => { + const args = [subCmd, "delete-interaction-model-catalog", "-c", catalogId]; + addCoveredCommand(args); + const result = await run(cmd, args, {...options, parse: false}); + expect(result).include("Command executed successfully!"); + }); + + it("| should get interaction model catalog update status", async () => { + const args = [subCmd, "get-interaction-model-catalog-update-status", "-c", catalogId, "--update-request-id", updateRequestId]; + addCoveredCommand(args); + const result = await run(cmd, args, options); + expect(result).be.an("object"); + }); + + it("| should update interaction model catalog", async () => { + const args = [subCmd, "update-interaction-model-catalog", "-c", catalogId, "--name", "name", "--description", "someDescription"]; + addCoveredCommand(args); + const result = await run(cmd, args, {...options, parse: false}); + expect(result).include("Command executed successfully!"); + }); + + it('| should create interaction model catalog version', async () => { + const args = [subCmd, 'create-interaction-model-catalog-version', '-c', catalogId, '--source-type', 'catalogType', '--source-url', 'catalogUrl', '--description', 'someDescription']; + addCoveredCommand(args); + const result = await run(cmd, args, { ...options, parse: false }); + expect(result).include('Command executed successfully!'); + }); + + it("| should get interaction model catalog version", async () => { + const args = [subCmd, "get-interaction-model-catalog-version", "-c", catalogId, "--vers", version]; + addCoveredCommand(args); + const result = await run(cmd, args, options); + expect(result).be.an("object"); + }); + + it("| should delete interaction model catalog version", async () => { + const args = [subCmd, "delete-interaction-model-catalog-version", "-c", catalogId, "--vers", version]; + addCoveredCommand(args); + const result = await run(cmd, args, {...options, parse: false}); + expect(result).include("Command executed successfully!"); + }); + + it("| should get interaction model catalog values", async () => { + const args = [subCmd, "get-interaction-model-catalog-values", "-c", catalogId, "--vers", version]; + addCoveredCommand(args); + const result = await run(cmd, args, options); + expect(result).be.an("object"); + }); + + it("| should get interaction model version", async () => { + const args = [subCmd, "get-interaction-model-version", "-s", skillId, "-g", stage, "-l", locale, "--vers", version]; + addCoveredCommand(args); + const result = await run(cmd, args, options); + expect(result).be.an("object"); + }); + + it("| should list interaction model versions", async () => { + const args = [subCmd, "list-interaction-model-versions", "-s", skillId, "-g", stage, "-l", locale]; + addCoveredCommand(args); + const result = await run(cmd, args, options); + expect(result).be.an("object"); + }); + + it("| should list interaction model slot types", async () => { + const args = [subCmd, "list-interaction-model-slot-types"]; + addCoveredCommand(args); + const result = await run(cmd, args, options); + expect(result).be.an("object"); + }); + + it("| should create interaction model slot type", async () => { + const args = [subCmd, "create-interaction-model-slot-type", "--slot-type", slotType]; + addCoveredCommand(args); + const result = await run(cmd, args, options); + expect(result).be.an("object"); + }); + + it("| should get interaction model slot type definition", async () => { + const args = [subCmd, "get-interaction-model-slot-type-definition", "--slot-type-id", slotTypeId]; + addCoveredCommand(args); + const result = await run(cmd, args, options); + expect(result).be.an("object"); + }); + + it("| should delete interaction model slot type", async () => { + const args = [subCmd, "delete-interaction-model-slot-type", "--slot-type-id", slotTypeId]; + addCoveredCommand(args); + const result = await run(cmd, args, {...options, parse: false}); + expect(result).include("Command executed successfully!"); + }); + + it("| should get interaction model slot type build status", async () => { + const args = [ + subCmd, + "get-interaction-model-slot-type-build-status", + "--slot-type-id", + slotTypeId, + "--update-request-id", + updateRequestId, + ]; + addCoveredCommand(args); + const result = await run(cmd, args, options); + expect(result).be.an("object"); + }); + + it("| should update interaction model slot type", async () => { + const args = [subCmd, "update-interaction-model-slot-type", "--slot-type-id", slotTypeId, "--slot-type-description", "someDescription"]; + addCoveredCommand(args); + const result = await run(cmd, args, {...options, parse: false}); + expect(result).include("Command executed successfully!"); + }); + + it("| should list interaction model slot type versions", async () => { + const args = [subCmd, "list-interaction-model-slot-type-versions", "--slot-type-id", slotTypeId]; + addCoveredCommand(args); + const result = await run(cmd, args, options); + expect(result).be.an("object"); + }); + + it("| should create interaction model slot type version", async () => { + const args = [subCmd, "create-interaction-model-slot-type-version", "--slot-type-id", slotTypeId, "--slot-type", slotType]; + addCoveredCommand(args); + const result = await run(cmd, args, {...options, parse: false}); + expect(result).include("Command executed successfully!"); + }); + + it("| should get interaction model slot type version", async () => { + const args = [subCmd, "get-interaction-model-slot-type-version", "--slot-type-id", slotTypeId, "--vers", version]; + addCoveredCommand(args); + const result = await run(cmd, args, options); + expect(result).be.an("object"); + }); + + it("| should delete interaction model slot type version", async () => { + const args = [subCmd, "delete-interaction-model-slot-type-version", "--slot-type-id", slotTypeId, "--vers", version]; + addCoveredCommand(args); + const result = await run(cmd, args, {...options, parse: false}); + expect(result).include("Command executed successfully!"); + }); + + it("| should update interaction model slot type version", async () => { + const args = [ + subCmd, + "update-interaction-model-slot-type-version", + "--slot-type-id", + slotTypeId, + "--vers", + version, + "--slot-type-description", + "someDescription", + ]; + addCoveredCommand(args); + const result = await run(cmd, args, {...options, parse: false}); + expect(result).include("Command executed successfully!"); + }); + + it("| should get skill manifest", async () => { + const args = [subCmd, "get-skill-manifest", "-s", skillId, "-g", stage]; + addCoveredCommand(args); + const result = await run(cmd, args, options); + expect(result).be.an("object"); + }); + + it("| should update skill manifest", async () => { + const args = [subCmd, "update-skill-manifest", "-s", skillId, "-g", stage, "--manifest", JSON.stringify(skillManifest)]; + addCoveredCommand(args); + const result = await run(cmd, args, {...options, parse: false}); + expect(result).include("Command executed successfully!"); + }); + + it("| should get skill metrics", async () => { + const args = [ + subCmd, + "get-skill-metrics", + "-s", + skillId, + "--start-time", + "2017-07-21T17:32:28Z", + "--end-time", + "2017-07-21T17:32:28Z", + "--period", + "P3", + "--metric", + "someMetric", + "-g", + stage, + "--skill-type", + "smartHome", + ]; + addCoveredCommand(args); + const result = await run(cmd, args, options); + expect(result).be.an("object"); + }); + + it("| should set private distribution account id", async () => { + const args = [subCmd, "set-private-distribution-account-id", "-s", skillId, "-g", stage, "--id", "someId"]; + addCoveredCommand(args); + const result = await run(cmd, args, {...options, parse: false}); + expect(result).include("Command executed successfully!"); + }); + + it("| should delete private distribution account id", async () => { + const args = [subCmd, "delete-private-distribution-account-id", "-s", skillId, "-g", stage, "--id", "someId"]; + addCoveredCommand(args); + const result = await run(cmd, args, {...options, parse: false}); + expect(result).include("Command executed successfully!"); + }); + + it("| should list private distribution accounts", async () => { + const args = [subCmd, "list-private-distribution-accounts", "-s", skillId, "-g", stage]; + addCoveredCommand(args); + const result = await run(cmd, args, options); + expect(result).be.an("object"); + }); + + it("| should get skill simulation", async () => { + const args = [subCmd, "get-skill-simulation", "-s", skillId, "-g", stage, "-i", simulationId]; + addCoveredCommand(args); + const result = await run(cmd, args, options); + expect(result).be.an("object"); + }); + + it("| should submit skill validation", async () => { + const args = [subCmd, "submit-skill-validation", "-l", locale, "-s", skillId, "-g", stage]; + addCoveredCommand(args); + const result = await run(cmd, args, options); + expect(result).be.an("object"); + }); + + it("| should get skill validations", async () => { + const args = [subCmd, "get-skill-validations", "-s", skillId, "-i", simulationId, "-g", stage]; + addCoveredCommand(args); + const result = await run(cmd, args, options); + expect(result).be.an("object"); + }); + + it("| should delete skill", async () => { + const args = [subCmd, "delete-skill", "-s", skillId]; + addCoveredCommand(args); + const result = await run(cmd, args, {...options, parse: false}); + expect(result).include("Command executed successfully!"); + }); + + it("| should get ssl certificates", async () => { + const args = [subCmd, "get-ssl-certificates", "-s", skillId]; + addCoveredCommand(args); + const result = await run(cmd, args, options); + expect(result).be.an("object"); + }); + + it("| should set ssl certificates", async () => { + const args = [subCmd, "set-ssl-certificates", "-s", skillId, "--ssl-certificate-payload", sslCertificatePayload]; + addCoveredCommand(args); + const result = await run(cmd, args, {...options, parse: false}); + expect(result).include("Command executed successfully!"); + }); + + it("| should submit skill for certification", async () => { + const args = [subCmd, "submit-skill-for-certification", "-s", skillId, "--publication-method", "MANUAL_PUBLISHING"]; + addCoveredCommand(args); + const result = await run(cmd, args, {...options, parse: false}); + expect(result).include("Command executed successfully!"); + }); + + it("| should withdraw skill from certification", async () => { + const args = [subCmd, "withdraw-skill-from-certification", "-s", skillId, "--reason", "TEST_SKILL"]; + addCoveredCommand(args); + const result = await run(cmd, args, {...options, parse: false}); + expect(result).include("Command executed successfully!"); + }); + + it("| should create export request for skill", async () => { + const args = [subCmd, "create-export-request-for-skill", "-s", skillId, "-g", stage]; + addCoveredCommand(args); + const result = await run(cmd, args, {...options, parse: false}); + expect(result).include("Command executed successfully!"); + }); + + it("| should get status of export request", async () => { + const args = [subCmd, "get-status-of-export-request", "--export-id", "someExportId"]; + addCoveredCommand(args); + const result = await run(cmd, args, options); + expect(result).be.an("object"); + }); + + it("| should create skill package", async () => { + const args = [subCmd, "create-skill-package", "--location", location]; + addCoveredCommand(args); + const result = await run(cmd, args, {...options, parse: false}); + expect(result).include("Command executed successfully!"); + }); + + it("| should import skill package", async () => { + const args = [subCmd, "import-skill-package", "--location", location, "-s", skillId]; + addCoveredCommand(args); + const result = await run(cmd, args, {...options, parse: false}); + expect(result).include("Command executed successfully!"); + }); + + it("| should get import status", async () => { + const args = [subCmd, "get-import-status", "--import-id", "someImportId"]; + addCoveredCommand(args); + const result = await run(cmd, args, options); + expect(result).be.an("object"); + }); + + it("| should create upload url", async () => { + const args = [subCmd, "create-upload-url"]; + addCoveredCommand(args); + const result = await run(cmd, args, options); + expect(result).be.an("object"); + }); + + it("| should query development audit logs", async () => { + const args = [subCmd, "query-development-audit-logs"]; + addCoveredCommand(args); + const result = await run(cmd, args, options); + expect(result).be.an("object"); + }); + + it("| should invoke skill end point", async () => { + const args = [subCmd, "invoke-skill", "-s", skillId, "--endpoint-region", "someRegion", "--skill-request-body", JSON.stringify({})]; + addCoveredCommand(args); + const result = await run(cmd, args, options); + expect(result).be.an("object"); + }); + + it("| should invoke skill end point", async () => { + const args = [ + subCmd, + "invoke-skill-end-point", + "-s", + skillId, + "-g", + stage, + "--endpoint-region", + "someRegion", + "--skill-request-body", + JSON.stringify({}), + ]; + addCoveredCommand(args); + const result = await run(cmd, args, options); + expect(result).be.an("object"); + }); + + it("| should list nlu evaluations", async () => { + const args = [subCmd, "list-nlu-evaluations", "-s", skillId]; + addCoveredCommand(args); + const result = await run(cmd, args, options); + expect(result).be.an("object"); + }); + + it("| should get nlu evaluation", async () => { + const args = [subCmd, "get-nlu-evaluation", "-s", skillId, "--evaluation-id", evaluationId]; + addCoveredCommand(args); + const result = await run(cmd, args, options); + expect(result).be.an("object"); + }); + + it("| should get result for nlu evaluations", async () => { + const args = [subCmd, "get-result-for-nlu-evaluations", "-s", skillId, "--evaluation-id", evaluationId]; + addCoveredCommand(args); + const result = await run(cmd, args, options); + expect(result).be.an("object"); + }); + + it("| should list nlu annotation sets", async () => { + const args = [subCmd, "list-nlu-annotation-sets", "-s", skillId]; + addCoveredCommand(args); + const result = await run(cmd, args, options); + expect(result).be.an("object"); + }); + + it("| should create nlu annotation set", async () => { + const args = [subCmd, "create-nlu-annotation-set", "-s", skillId, "-l", locale, "--name", name]; + addCoveredCommand(args); + const result = await run(cmd, args, options); + expect(result).be.an("object"); + }); + + it("| should create nlu evaluations", async () => { + const args = [subCmd, "create-nlu-evaluations", "-g", stage, "-l", locale, "--source-annotation-id", sourceAnnotationId, "-s", skillId]; + addCoveredCommand(args); + const result = await run(cmd, args, options); + expect(result).be.an("object"); + }); + + it("| should get properties for nlu annotation sets", async () => { + const args = [subCmd, "get-properties-for-nlu-annotation-sets", "-s", skillId, "--annotation-id", annotationId]; + addCoveredCommand(args); + const result = await run(cmd, args, options); + expect(result).be.an("object"); + }); + + it("| should update properties for nlu annotation sets", async () => { + const args = [subCmd, "update-properties-for-nlu-annotation-sets", "-s", skillId, "--annotation-id", annotationId, "--name", name]; + addCoveredCommand(args); + const result = await run(cmd, args, {...options, parse: false}); + expect(result).include("Command executed successfully!"); + }); + + it("| should delete properties for nlu annotation sets", async () => { + const args = [subCmd, "delete-properties-for-nlu-annotation-sets", "-s", skillId, "--annotation-id", annotationId]; + addCoveredCommand(args); + const result = await run(cmd, args, {...options, parse: false}); + expect(result).include("Command executed successfully!"); + }); + + it("| should get annotations for nlu annotation sets", async () => { + const args = [subCmd, "get-annotations-for-nlu-annotation-sets", "-s", skillId, "--annotation-id", annotationId, "--accept", accept]; + addCoveredCommand(args); + const result = await run(cmd, args, options); + expect(result).be.an("object"); + }); + + it("| should update annotations for nlu annotation sets", async () => { + const args = [ + subCmd, + "update-annotations-for-nlu-annotation-sets", + "-s", + skillId, + "--annotation-id", + annotationId, + "--content-type", + contentType, + "--update-nlu-annotation-set-annotations-request", + updateNluAnnotationSetAnnotationsRequest, + ]; + addCoveredCommand(args); + const result = await run(cmd, args, {...options, parse: false}); + expect(result).include("Command executed successfully!"); + }); + + it("| should get conflicts for interaction model conflict detection", async () => { + const args = [subCmd, "get-conflicts-for-interaction-model", "-s", skillId, "-l", locale, "-g", stage, "--vers", "1"]; + addCoveredCommand(args); + const result = await run(cmd, args, options); + expect(result).be.an("object"); + }); + + it("| should get job status for interaction model conflict detection", async () => { + const args = [ + subCmd, + "get-conflict-detection-job-status-for-interaction-model", + "-s", + skillId, + "-l", + locale, + "-g", + stage, + "--vers", + "1", + ]; + addCoveredCommand(args); + const result = await run(cmd, args, options); + expect(result).be.an("object"); + }); + + it("| should get skill credential", async () => { + const args = [subCmd, "get-skill-credentials", "-s", skillId]; + addCoveredCommand(args); + const result = await run(cmd, args, options); + expect(result).be.an("object"); + }); + + it("| should list asr annotation sets", async () => { + const args = [subCmd, "list-asr-annotation-sets", "-s", skillId]; + addCoveredCommand(args); + const result = await run(cmd, args, options); + expect(result).be.an("object"); + }); + + it("| should create asr annotation set", async () => { + const args = [subCmd, "create-asr-annotation-set", "-s", skillId, "--name", name]; + addCoveredCommand(args); + const result = await run(cmd, args, options); + expect(result).be.an("object"); + }); + + it("| should get asr annotation set", async () => { + const args = [subCmd, "get-asr-annotation-set", "-s", skillId, "--annotation-set-id", annotationSetId]; + addCoveredCommand(args); + const result = await run(cmd, args, options); + expect(result).be.an("object"); + }); + + it("| should set asr annotation set", async () => { + const args = [subCmd, "set-asr-annotation-set", "-s", skillId, "--annotation-set-id", annotationSetId, "--name", name]; + addCoveredCommand(args); + const result = await run(cmd, args, {...options, parse: false}); + expect(result).include("Command executed successfully!"); + }); + + it("| should delete asr annotation set", async () => { + const args = [subCmd, "delete-asr-annotation-set", "-s", skillId, "--annotation-set-id", annotationSetId]; + addCoveredCommand(args); + const result = await run(cmd, args, {...options, parse: false}); + expect(result).include("Command executed successfully!"); + }); + + it("| should get annotations for asr annotation set", async () => { + const args = [ + subCmd, + "get-annotations-for-asr-annotation-set", + "-s", + skillId, + "--annotation-set-id", + annotationSetId, + "--accept", + accept, + ]; + addCoveredCommand(args); + const result = await run(cmd, args, options); + expect(result).be.an("object"); + }); + + it("| should set annotations for asr annotation set", async () => { + const args = [ + subCmd, + "set-annotations-for-asr-annotation-set", + "-s", + skillId, + "--annotation-set-id", + annotationSetId, + "--annotations", + annotations, + ]; + addCoveredCommand(args); + const result = await run(cmd, args, {...options, parse: false}); + expect(result).include("Command executed successfully!"); + }); + + it("| should list asr evaluations", async () => { + const args = [subCmd, "list-asr-evaluations", "-s", skillId]; + addCoveredCommand(args); + const result = await run(cmd, args, options); + expect(result).be.an("object"); + }); + + it("| should create asr evaluation", async () => { + const args = [ + subCmd, + "create-asr-evaluation", + "--stage", + stage, + "--locale", + locale, + "--annotation-set-id", + annotationSetId, + "-s", + skillId, + ]; + addCoveredCommand(args); + const result = await run(cmd, args, options); + expect(result).be.an("object"); + }); + + it("| should get asr evaluation status", async () => { + const args = [subCmd, "get-asr-evaluation-status", "-s", skillId, "--evaluation-id", evaluationId]; + addCoveredCommand(args); + const result = await run(cmd, args, options); + expect(result).be.an("object"); + }); + + it("| should delete asr evaluation", async () => { + const args = [subCmd, "delete-asr-evaluation", "-s", skillId, "--evaluation-id", evaluationId]; + addCoveredCommand(args); + const result = await run(cmd, args, {...options, parse: false}); + expect(result).include("Command executed successfully!"); + }); + + it("| should list asr evaluations results", async () => { + const args = [subCmd, "list-asr-evaluations-results", "-s", skillId, "--evaluation-id", evaluationId]; + addCoveredCommand(args); + const result = await run(cmd, args, options); + expect(result).be.an("object"); + }); + + it("| should list interaction model catalog versions", async () => { + const args = [subCmd, "list-interaction-model-catalog-versions", "-c", catalogId]; + addCoveredCommand(args); + const result = await run(cmd, args, options); + expect(result).be.an("object"); + }); + + it("| should clone locale", async () => { + const args = [subCmd, "clone-locale", "-s", skillId, "--source-locale", sourceLocale, "--target-locales", targetLocales]; + addCoveredCommand(args); + const result = await run(cmd, args, {...options, parse: false}); + expect(result).include("Command executed successfully!"); + }); + + it("| should get clone locale status", async () => { + const args = [subCmd, "get-clone-locale-status", "-s", skillId, "--clone-locale-request-id", cloneLocaleRequestId]; + addCoveredCommand(args); + const result = await run(cmd, args, options); + expect(result).be.an("object"); + }); + + it("| should list versions for skill", async () => { + const args = [subCmd, "list-versions-for-skill", "-s", skillId]; + addCoveredCommand(args); + const result = await run(cmd, args, options); + expect(result).be.an("object"); + }); + + it("| should rollback skill", async () => { + const args = [subCmd, "rollback-skill", "-s", skillId, "--target-version", targetVersion]; + addCoveredCommand(args); + const result = await run(cmd, args, options); + expect(result).be.an("object"); + }); + + it("| should get rollback for skill", async () => { + const args = [subCmd, "get-rollback-for-skill", "-s", skillId, "--rollback-request-id", rollbackRequestId]; + addCoveredCommand(args); + const result = await run(cmd, args, options); + expect(result).be.an("object"); + }); + + it("| should publish skill", async () => { + const args = [ + subCmd, + "publish-skill", + "-s", + skillId, + "--accept-language", + acceptLanguage, + "--publishes-at-date", + "2019-04-12T23:20:50.52Z", + ]; + addCoveredCommand(args); + const result = await run(cmd, args, options); + expect(result).be.an("object"); + }); + + it("| should get skill publications", async () => { + const args = [subCmd, "get-skill-publications", "-s", skillId, "--accept-language", acceptLanguage]; + addCoveredCommand(args); + const result = await run(cmd, args, options); + expect(result).be.an("object"); + }); + + it("| should list all the job defintions for IM", async () => { + const args = [subCmd, "list-job-definitions-for-interaction-model"]; + addCoveredCommand(args); + const result = await run(cmd, args, options); + expect(result).be.an("object"); + }); + + it("| should create job definition for IM", async () => { + const args = [subCmd, "create-job-definition-for-interaction-model", "--job-definition", interactionModelJobDefinition]; + addCoveredCommand(args); + const result = await run(cmd, args, options); + expect(result).be.an("object"); + }); + + it("| should get job definition for IM", async () => { + const args = [subCmd, "get-job-definition-for-interaction-model", "--job-id", imJobId]; + addCoveredCommand(args); + const result = await run(cmd, args, options); + expect(result).be.an("object"); + }); + + it("| should delete job definition for IM", async () => { + const args = [subCmd, "delete-job-definition-for-interaction-model", "--job-id", imJobId]; + addCoveredCommand(args); + const result = await run(cmd, args, {...options, parse: false}); + expect(result).include("Command executed successfully!"); + }); + + it("| should set job status for IM", async () => { + const args = [subCmd, "set-job-status-for-interaction-model", "--job-id", imJobId, "--status", imJobStatus]; + addCoveredCommand(args); + const result = await run(cmd, args, {...options, parse: false}); + expect(result).include("Command executed successfully!"); + }); + + it("| should list all the job executions for IM", async () => { + const args = [subCmd, "list-job-executions-for-interaction-model", "--job-id", imJobId]; + addCoveredCommand(args); + const result = await run(cmd, args, options); + expect(result).be.an("object"); + }); + + it("| should cancel next job execution for IMJob", async () => { + const args = [subCmd, "cancel-next-job-execution-for-interaction-model", "--job-id", imJobId, "--execution-id", imExecutionId]; + addCoveredCommand(args); + const result = await run(cmd, args, {...options, parse: false}); + expect(result).include("Command executed successfully!"); + }); + + it("| should get resource schema", async () => { + const args = [subCmd, "get-resource-schema", "--resource", "manifest"]; + addCoveredCommand(args); + const result = await run(cmd, args, options); + expect(result).be.an("object"); + }); + + it("| should list smarthome capability test plans", async () => { + const args = [subCmd, "list-smarthome-capability-test-plans", "-s", skillId]; + addCoveredCommand(args); + const result = await run(cmd, args, options); + expect(result).be.an("object"); + }); + + it("| should get smarthome capablity evaluation results", async () => { + const args = [subCmd, "get-smarthome-capablity-evaluation-results", "-s", skillId, "--evaluation-id", evaluationId]; + addCoveredCommand(args); + const result = await run(cmd, args, options); + expect(result).be.an("object"); + }); + + it("| should get smart home capability evaluation", async () => { + const args = [subCmd, "get-smart-home-capability-evaluation", "-s", skillId, "--evaluation-id", evaluationId]; + addCoveredCommand(args); + const result = await run(cmd, args, options); + expect(result).be.an("object"); + }); + + it("| should list smarthome capability evaluations", async () => { + const args = [subCmd, "list-smarthome-capability-evaluations", "-s", skillId]; + addCoveredCommand(args); + const result = await run(cmd, args, options); + expect(result).be.an("object"); + }); + + it("| should create smarthome capability evaluation", async () => { + const args = [ + subCmd, + "create-smarthome-capability-evaluation", + "-s", + skillId, + "--capability-test-plan-id", + 1, + "--endpoint-endpoint-id", + 2, + ]; + addCoveredCommand(args); + const result = await run(cmd, args, options); + expect(result).be.an("object"); + }); + + it('| should list all experiments associated with this skill id', async () => { + const args = [subCmd, 'list-experiments', '-s', skillId]; + addCoveredCommand(args); + const result = await run(cmd, args, options); + expect(result).be.an('object'); + }); + + it('| should create a new experiment for a skill', async () => { + const args = [subCmd, 'create-experiment', '-s', skillId, '--experiment-name', experimentName, '--experiment-description', experimentDescription, '--experiment-type', experimentType, '--experiment-planned-duration', experimentPlannedDuration, '--experiment-exposure-percentage', experimentExposurePercentage, '--experiment-metric-configurations', experimentMetricConfigurations]; + addCoveredCommand(args); + const result = await run(cmd, args, { ...options, parse: false }); + expect(result).include('Command executed successfully!'); + }); + + it('| should update an existing experiment for a skill', async () => { + const args = [subCmd, 'update-experiment', '-s', skillId, '--experiment-id', experimentId, '--experiment-description', experimentDescription, '--experiment-planned-duration', experimentPlannedDuration, '--experiment-exposure-percentage', experimentExposurePercentage, '--experiment-metric-configurations', experimentMetricConfigurations]; + addCoveredCommand(args); + const result = await run(cmd, args, { ...options, parse: false }); + expect(result).include('Command executed successfully!'); + }); + + it('| should retrieve an existing experiment for a skill', async () => { + const args = [subCmd, 'get-experiment', '-s', skillId, '--experiment-id', experimentId]; + addCoveredCommand(args); + const result = await run(cmd, args, options); + expect(result).be.an('object'); + }); + + it('| should delete an existing experiment for a skill', async () => { + const args = [subCmd, 'delete-experiment', '-s', skillId, '--experiment-id', experimentId]; + addCoveredCommand(args); + const result = await run(cmd, args, { ...options, parse: false }); + expect(result).include('Command executed successfully!'); + }); + + it('| should update the exposure of an experiment that is in CREATED or RUNNING state.', async () => { + const args = [subCmd, 'update-exposure', '-s', skillId, '--experiment-id', experimentId, '--exposure-percentage', experimentExposurePercentage]; + addCoveredCommand(args); + const result = await run(cmd, args, { ...options, parse: false }); + expect(result).include('Command executed successfully!'); + }); + + it('| should retrieve the current user\'s customer treatment override for an existing A/B Test experiment', async () => { + const args = [subCmd, 'get-customer-treatment-override', '-s', skillId, '--experiment-id', experimentId]; + addCoveredCommand(args); + const result = await run(cmd, args, options); + expect(result).be.an('object'); + }); + + it('| should add the requesting user\'s customer treatment override to an existing experiment.', async () => { + const args = [subCmd, 'set-customer-treatment-override', '-s', skillId, '--experiment-id', experimentId, '--treatment-id', treatmentId]; + addCoveredCommand(args); + const result = await run(cmd, args, { ...options, parse: false }); + expect(result).include('Command executed successfully!'); + }); + + it('| should retrieve the current state of the experiment.', async () => { + const args = [subCmd, 'get-experiment-state', '-s', skillId, '--experiment-id', experimentId]; + addCoveredCommand(args); + const result = await run(cmd, args, options); + expect(result).be.an('object'); + }); + + it('| should request an action on the experiment to move it to the targetState.', async () => { + const args = [subCmd, 'manage-experiment-state', '-s', skillId, '--experiment-id', experimentId, '--target-state', targetState]; + addCoveredCommand(args); + const result = await run(cmd, args, { ...options, parse: false }); + expect(result).include('Command executed successfully!'); + }); + + it('| should get a list of all metric snapshots associated with this experiment id.', async () => { + const args = [subCmd, 'list-experiment-metric-snapshots', '-s', skillId, '--experiment-id', experimentId]; + addCoveredCommand(args); + const result = await run(cmd, args, options); + expect(result).be.an('object'); + }); + + it('| should gets a list of all metric data associated with this experiment\'s metric snapshot.', async () => { + const args = [subCmd, 'get-experiment-metric-snapshot', '-s', skillId, '--experiment-id', experimentId, '--metric-snapshot-id', metricSnapShotId]; + addCoveredCommand(args); + const result = await run(cmd, args, options); + expect(result).be.an('object'); + }); + + after(() => { + mockSmapiServer.kill(); + mockLwaServer.kill(); + expect(Array.from(untestedCommands), 'should not have untested commands').eql([]); + }); +}); \ No newline at end of file diff --git a/test/integration/fixtures/account-linking-request.json b/test/integration/fixtures/account-linking-request.json index 6c4b9bcb..59607785 100644 --- a/test/integration/fixtures/account-linking-request.json +++ b/test/integration/fixtures/account-linking-request.json @@ -1,21 +1,15 @@ { - "accountLinkingRequest": { - "skipOnEnablement": "true", - "type": "AUTH_CODE", - "authorizationUrl": "https://www.example.com/auth_url", - "domains": [ - "example.com" - ], - "clientId": "string", - "scopes": [ - "www.example.com" - ], - "accessTokenUrl": "https://www.example.com/accessToken_url", - "clientSecret": "abcdaslkaa", - "accessTokenScheme": "HTTP_BASIC", - "defaultTokenExpirationInSeconds": 20, - "redirectUrls": [ - "https://www.example.com/redirect" - ] - } + "accountLinkingRequest": { + "skipOnEnablement": "true", + "type": "AUTH_CODE", + "authorizationUrl": "https://www.example.com/auth_url", + "domains": ["example.com"], + "clientId": "string", + "scopes": ["www.example.com"], + "accessTokenUrl": "https://www.example.com/accessToken_url", + "clientSecret": "abcdaslkaa", + "accessTokenScheme": "HTTP_BASIC", + "defaultTokenExpirationInSeconds": 20, + "redirectUrls": ["https://www.example.com/redirect"] } +} diff --git a/test/integration/fixtures/annotation-set.json b/test/integration/fixtures/annotation-set.json index 3002228e..11be7828 100644 --- a/test/integration/fixtures/annotation-set.json +++ b/test/integration/fixtures/annotation-set.json @@ -1,98 +1,98 @@ { - "data": [ - { - "inputs": { - "utterance": "plan a trip" - }, - "expected": [ - { - "intent": { - "name": "PlanMyTripIntent" - } + "data": [ + { + "inputs": { + "utterance": "plan a trip" + }, + "expected": [ + { + "intent": { + "name": "PlanMyTripIntent" } - ] + } + ] + }, + { + "inputs": { + "utterance": "book me a flight to seattle" }, - { - "inputs": { - "utterance": "book me a flight to seattle" - }, - "expected": [ - { - "intent": { - "name": "BookFlightIntent", - "slots": { - "destination": { - "value": "seattle" - } + "expected": [ + { + "intent": { + "name": "BookFlightIntent", + "slots": { + "destination": { + "value": "seattle" } } } - ] + } + ] + }, + { + "inputs": { + "utterance": "I'm going to chicago on Friday", + "referenceTimestamp": "2019-08-29T00:00:00.000Z" }, - { - "inputs": { - "utterance": "I'm going to chicago on Friday", - "referenceTimestamp": "2019-08-29T00:00:00.000Z" - }, - "expected": [ - { - "intent": { - "name": "PlanMyTripIntent", - "slots": { - "toCity": { - "value": "chicago" - }, - "travelDate": { - "value": "2019-08-30" - } + "expected": [ + { + "intent": { + "name": "PlanMyTripIntent", + "slots": { + "toCity": { + "value": "chicago" + }, + "travelDate": { + "value": "2019-08-30" } } } - ] + } + ] + }, + { + "inputs": { + "utterance": "plan a trip from seattle to boston" }, - { - "inputs": { - "utterance": "plan a trip from seattle to boston" - }, - "expected": [ - { - "intent": { - "name": "PlanMyTripIntent", - "slots": { - "toCity": { - "value": "boston" - }, - "fromCity": { - "value": "seattle" - } + "expected": [ + { + "intent": { + "name": "PlanMyTripIntent", + "slots": { + "toCity": { + "value": "boston" + }, + "fromCity": { + "value": "seattle" } } } - ] + } + ] + }, + { + "inputs": { + "utterance": "plan a trip from chicago to denver on Monday", + "referenceTimestamp": "2019-08-29T00:00:00.000Z" }, - { - "inputs": { - "utterance": "plan a trip from chicago to denver on Monday", - "referenceTimestamp": "2019-08-29T00:00:00.000Z" - }, - "expected": [ - { - "intent": { - "name": "PlanMyTripIntent", - "slots": { - "toCity": { - "value": "denver" - }, - "fromCity": { - "value": "chicago" - }, - "travelDate": { - "value": "2019-09-02" - } + "expected": [ + { + "intent": { + "name": "PlanMyTripIntent", + "slots": { + "toCity": { + "value": "denver" + }, + "fromCity": { + "value": "chicago" + }, + "travelDate": { + "value": "2019-09-02" } } } - ] - } - ] - } \ No newline at end of file + } + ] + } + ] +} diff --git a/test/integration/fixtures/catalog-upload.json b/test/integration/fixtures/catalog-upload.json index 4cd6c45a..aa84fd19 100644 --- a/test/integration/fixtures/catalog-upload.json +++ b/test/integration/fixtures/catalog-upload.json @@ -1,3 +1,3 @@ { - "location": "http://example.com" + "location": "http://example.com" } diff --git a/test/integration/fixtures/code-builder/custom/lambda/index.js b/test/integration/fixtures/code-builder/custom/lambda/index.js index f7991b44..77faecc8 100644 --- a/test/integration/fixtures/code-builder/custom/lambda/index.js +++ b/test/integration/fixtures/code-builder/custom/lambda/index.js @@ -1 +1 @@ -console.log('node lambda code'); +console.log("node lambda code"); diff --git a/test/integration/fixtures/code-builder/custom/lambda/package.json b/test/integration/fixtures/code-builder/custom/lambda/package.json index 13b8b29f..55763134 100644 --- a/test/integration/fixtures/code-builder/custom/lambda/package.json +++ b/test/integration/fixtures/code-builder/custom/lambda/package.json @@ -1,14 +1,14 @@ { - "name": "hello-world", - "version": "1.1.0", - "description": "test", - "main": "index.js", - "scripts": { - "test": "echo \"Error: no test specified\" && exit 1" - }, - "author": "Amazon Alexa", - "license": "ISC", - "dependencies": { - "ask-sdk-core": "^2.6.0" - } + "name": "hello-world", + "version": "1.1.0", + "description": "test", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "author": "Amazon Alexa", + "license": "ISC", + "dependencies": { + "ask-sdk-core": "^2.6.0" } +} diff --git a/test/integration/fixtures/code-builder/nodejs-npm/lambda/index.js b/test/integration/fixtures/code-builder/nodejs-npm/lambda/index.js index f7991b44..77faecc8 100644 --- a/test/integration/fixtures/code-builder/nodejs-npm/lambda/index.js +++ b/test/integration/fixtures/code-builder/nodejs-npm/lambda/index.js @@ -1 +1 @@ -console.log('node lambda code'); +console.log("node lambda code"); diff --git a/test/integration/fixtures/create-in-skill-product-request.json b/test/integration/fixtures/create-in-skill-product-request.json index fff9ccde..e700ed64 100644 --- a/test/integration/fixtures/create-in-skill-product-request.json +++ b/test/integration/fixtures/create-in-skill-product-request.json @@ -1,56 +1,50 @@ { - "inSkillProductDefinition": { - "version": "string", - "type": "SUBSCRIPTION", - "referenceName": "string", - "purchasableState": "PURCHASABLE", - "subscriptionInformation": { - "subscriptionPaymentFrequency": "MONTHLY", - "subscriptionTrialPeriodDays": 0 - }, - "publishingInformation": { - "locales": { - "en-US": { - "name": "string", - "smallIconUri": "https://dummyimage.com/108/108/fff", - "largeIconUri": "https://dummyimage.com/512/512/fff", - "summary": "string", - "description": "string", - "examplePhrases": [ - "string" - ], - "keywords": [ - "string" - ], - "customProductPrompts": { - "purchasePromptDescription": "test", - "boughtCardDescription": "test" - } - } - }, - "distributionCountries": [ - "US" - ], - "pricing": { - "amazon.com": { - "releaseDate": "2099-04-13", - "defaultPriceListing": { - "price": 0.99, - "currency": "USD" - } + "inSkillProductDefinition": { + "version": "string", + "type": "SUBSCRIPTION", + "referenceName": "string", + "purchasableState": "PURCHASABLE", + "subscriptionInformation": { + "subscriptionPaymentFrequency": "MONTHLY", + "subscriptionTrialPeriodDays": 0 + }, + "publishingInformation": { + "locales": { + "en-US": { + "name": "string", + "smallIconUri": "https://dummyimage.com/108/108/fff", + "largeIconUri": "https://dummyimage.com/512/512/fff", + "summary": "string", + "description": "string", + "examplePhrases": ["string"], + "keywords": ["string"], + "customProductPrompts": { + "purchasePromptDescription": "test", + "boughtCardDescription": "test" } - }, - "taxInformation": { - "category": "SOFTWARE" } }, - "privacyAndCompliance": { - "locales": { - "en-US": { - "privacyPolicyUrl": "http://www.example.com" + "distributionCountries": ["US"], + "pricing": { + "amazon.com": { + "releaseDate": "2099-04-13", + "defaultPriceListing": { + "price": 0.99, + "currency": "USD" } } }, - "testingInstructions": "string" - } + "taxInformation": { + "category": "SOFTWARE" + } + }, + "privacyAndCompliance": { + "locales": { + "en-US": { + "privacyPolicyUrl": "http://www.example.com" + } + } + }, + "testingInstructions": "string" } +} diff --git a/test/integration/fixtures/interaction-model.json b/test/integration/fixtures/interaction-model.json index 66dfc9d5..fad4c389 100644 --- a/test/integration/fixtures/interaction-model.json +++ b/test/integration/fixtures/interaction-model.json @@ -1,93 +1,87 @@ { - "version": "string", - "description": "string", - "interactionModel": { - "languageModel": { - "invocationName": "string", - "types": [ - { - "name": "string", - "values": [ - { - "id": "string", - "name": { - "value": "string", - "synonyms": [ - "string" - ] - } + "version": "string", + "description": "string", + "interactionModel": { + "languageModel": { + "invocationName": "string", + "types": [ + { + "name": "string", + "values": [ + { + "id": "string", + "name": { + "value": "string", + "synonyms": ["string"] } - ], - "valueSupplier": { - "type": "string" } - } - ], - "intents": [ - { - "name": "string", - "slots": [ - { - "name": "string", - "type": "string", - "samples": [ - "string" - ] - } - ], - "samples": [ - "string" - ] - } - ], - "modelConfiguration": { - "fallbackIntentSensitivity": { - "level": "HIGH" + ], + "valueSupplier": { + "type": "string" } } - }, - "dialog": { - "delegationStrategy": "ALWAYS", - "intents": [ - { - "name": "string", - "delegationStrategy": "ALWAYS", - "slots": [ - { - "name": "string", - "type": "string", - "elicitationRequired": true, - "confirmationRequired": true, - "prompts": { - "elicitation": "string", - "confirmation": "string" - }, - "validations": [ - { - "type": "string", - "prompt": "string" - } - ] - } - ], - "confirmationRequired": true, - "prompts": { - "elicitation": "string", - "confirmation": "string" + ], + "intents": [ + { + "name": "string", + "slots": [ + { + "name": "string", + "type": "string", + "samples": ["string"] } - } - ] - }, - "prompts": [ + ], + "samples": ["string"] + } + ], + "modelConfiguration": { + "fallbackIntentSensitivity": { + "level": "HIGH" + } + } + }, + "dialog": { + "delegationStrategy": "ALWAYS", + "intents": [ { - "id": "string", - "variations": [ + "name": "string", + "delegationStrategy": "ALWAYS", + "slots": [ { - "type": "SSML", - "value": "string" + "name": "string", + "type": "string", + "elicitationRequired": true, + "confirmationRequired": true, + "prompts": { + "elicitation": "string", + "confirmation": "string" + }, + "validations": [ + { + "type": "string", + "prompt": "string" + } + ] } - ] + ], + "confirmationRequired": true, + "prompts": { + "elicitation": "string", + "confirmation": "string" + } } ] - } + }, + "prompts": [ + { + "id": "string", + "variations": [ + { + "type": "SSML", + "value": "string" + } + ] + } + ] } +} diff --git a/test/integration/fixtures/job-definition.json b/test/integration/fixtures/job-definition.json index 8025ab94..e0a4af61 100644 --- a/test/integration/fixtures/job-definition.json +++ b/test/integration/fixtures/job-definition.json @@ -1,14 +1,14 @@ { - "jobDefinition": { - "type": "CatalogAutoRefresh", - "resource": { - "type": "Catalog", - "id": "amzn1.ask.interactionModel.catalog.661c3570-99d8-4b3f-95b7-db8c403a6125" - }, - "trigger": { - "type": "Scheduled", - "hour": 4 + "jobDefinition": { + "type": "CatalogAutoRefresh", + "resource": { + "type": "Catalog", + "id": "amzn1.ask.interactionModel.catalog.661c3570-99d8-4b3f-95b7-db8c403a6125" }, - "status": "ENABLED" - } + "trigger": { + "type": "Scheduled", + "hour": 4 + }, + "status": "ENABLED" + } } diff --git a/test/integration/fixtures/lwa-swagger.json b/test/integration/fixtures/lwa-swagger.json index f2a77fa4..4b8ff960 100644 --- a/test/integration/fixtures/lwa-swagger.json +++ b/test/integration/fixtures/lwa-swagger.json @@ -4,15 +4,11 @@ "version": "1.0", "title": "LWA" }, - "produces": [ - "application/json" - ], + "produces": ["application/json"], "paths": { "/auth/O2/token": { "post": { - "consumes": [ - "application/x-www-form-urlencoded" - ], + "consumes": ["application/x-www-form-urlencoded"], "parameters": [ { "in": "body", @@ -43,11 +39,7 @@ "definitions": { "TokenForm": { "type": "object", - "required": [ - "grant_type", - "client_secret", - "client_id" - ], + "required": ["grant_type", "client_secret", "client_id"], "properties": { "grant_type": { "type": "string" diff --git a/test/integration/fixtures/skill-manifest.json b/test/integration/fixtures/skill-manifest.json index f1e99f0c..2422fb8a 100644 --- a/test/integration/fixtures/skill-manifest.json +++ b/test/integration/fixtures/skill-manifest.json @@ -1,21 +1,19 @@ { - "manifest":{ - "publishingInformation":{ - "locales":{ - "en-US":{ - "name":"integration test" - } - } - }, - "apis":{ - "custom":{ - - } - } + "manifest": { + "publishingInformation": { + "locales": { + "en-US": { + "name": "integration test" + } + } }, - "hosting":{ - "alexaHosted":{ - "runtime":"NODE_16_X" - } + "apis": { + "custom": {} } - } + }, + "hosting": { + "alexaHosted": { + "runtime": "NODE_16_X" + } + } +} diff --git a/test/integration/run-test.js b/test/integration/run-test.js index e79da283..b0f3b07f 100644 --- a/test/integration/run-test.js +++ b/test/integration/run-test.js @@ -1,16 +1,12 @@ -require('module-alias/register'); - process.env.ASK_SHARE_USAGE = false; -const tests = [ - '@test/integration/code-builder/code-builder-test.js' -]; +const tests = ["./code-builder/code-builder-test.js"]; if (process.platform !== 'win32') { // smapi tests are not supported on windows - tests.push('@test/integration/commands/smapi-commands-test.js'); + tests.push('./commands/smapi-commands-test.js'); } tests.forEach((testFile) => { - // eslint-disable-next-line global-require - require(testFile); + // eslint-disable-next-line global-require + require(testFile); }); diff --git a/test/temp/abstract-build-flow/build.zip b/test/temp/abstract-build-flow/build.zip new file mode 100644 index 0000000000000000000000000000000000000000..99ca6a8c61721ac2eaf1c368038dfdae69ea5c2c GIT binary patch literal 135 zcmWIWW@Zs#VBp|jU|?_*x%0w~fg8x;1Y%wwF3!(Q)lJLHN!2T { - fs.ensureDirSync(tempDirectory); - fs.emptyDirSync(tempDirectory); + fs.ensureDirSync(tempDirectory); + fs.emptyDirSync(tempDirectory); }; const deleteFolderInTempDirectory = (folder) => { - const folderPath = path.join(tempDirectory, folder); - fs.removeSync(folderPath); + const folderPath = path.join(tempDirectory, folder); + fs.removeSync(folderPath); }; const getPathInTempDirectory = (folderPath) => path.join(tempDirectory, folderPath); const makeFolderInTempDirectory = (folderPath) => { - const fullPath = getPathInTempDirectory(folderPath); - fs.ensureDirSync(fullPath); - return fullPath; + const fullPath = getPathInTempDirectory(folderPath); + fs.ensureDirSync(fullPath); + return fullPath; }; const run = (cmd, args, options = {}) => { - const inputs = options.inputs || []; - const parse = options.parse || false; - const returnProcessHandle = options.returnProcessHandle || false; - const cwd = options.cwd || tempDirectory; - const env = { ...process.env, ...options.env }; - - fs.ensureDirSync(cwd); - - const childProcess = spawn(cmd, args, { cwd, env, stdio: [null, null, null, 'ipc'] }); - - return new Promise((resolve, reject) => { - let output = ''; - let errorMessage = ''; - const processStream = (data, isError = false) => { - const dataStr = data.toString(); - if (isError) { - errorMessage += dataStr; - } else { - output += dataStr; - } - if (process.env.DEBUG) { - console.log(dataStr); - } - return dataStr; - }; - const processData = (data) => processStream(data); - const processError = (data) => processStream(data, true); - - childProcess.stdout.on('data', (data) => { - const dataStr = processData(data); - - const index = inputs.findIndex(i => dataStr.includes(i.match)); - if (index > -1) { - const { input } = inputs[index]; - inputs.splice(index, 1); - const value = input ? `${input}${KeySymbol.ENTER}` : KeySymbol.ENTER; - childProcess.stdin.write(value); - } - if (returnProcessHandle && inputs.length === 0) { - resolve(childProcess); - } - }); - - childProcess.stderr.on('data', (data) => { - errorMessage = processError(data); - }); - - childProcess.on('close', (code) => { - if (code) { - reject(new Error(`${output}${errorMessage}`)); - } else { - output = parse ? JSON.parse(output) : output; - resolve(output); - } - }); + const inputs = options.inputs || []; + const parse = options.parse || false; + const returnProcessHandle = options.returnProcessHandle || false; + const cwd = options.cwd || tempDirectory; + const env = {...process.env, ...options.env}; + + fs.ensureDirSync(cwd); + + const childProcess = spawn(cmd, args, {cwd, env, stdio: [null, null, null, null]}); + + return new Promise((resolve, reject) => { + let output = ""; + let errorMessage = ""; + const processStream = (data, isError = false) => { + const dataStr = data.toString(); + if (isError) { + errorMessage += dataStr; + } else { + output += dataStr; + } + if (process.env.DEBUG) { + console.log(dataStr); + } + return dataStr; + }; + const processData = (data) => processStream(data); + const processError = (data) => processStream(data, true); + + childProcess.stdout.on("data", (data) => { + const dataStr = processData(data); + + const index = inputs.findIndex((i) => dataStr.includes(i.match)); + if (index > -1) { + const {input} = inputs[index]; + inputs.splice(index, 1); + const value = input ? `${input}${KeySymbol.ENTER}` : KeySymbol.ENTER; + childProcess.stdin.write(value); + } + if (returnProcessHandle && inputs.length === 0) { + resolve(childProcess); + } }); + + childProcess.stderr.on("data", (data) => { + errorMessage = processError(data); + }); + + childProcess.on("close", (code) => { + if (code) { + reject(new Error(`${output}${errorMessage}`)); + } else { + output = parse ? JSON.parse(output) : output; + resolve(output); + } + }); + }); }; const _startMockServer = async (port, swaggerSpecPath) => { - const inputs = [ - { match: 'Prism is listening on' } - ]; - const args = ['run', 'prism', '--', 'mock', '-p', port, swaggerSpecPath]; - const options = { returnProcessHandle: true, inputs, cwd: process.cwd() }; - return run('npm', args, options); + const inputs = [{match: "Prism is listening on"}]; + const args = ["run", "prism", "--", "mock", "-p", port, swaggerSpecPath]; + const options = {returnProcessHandle: true, inputs, cwd: process.cwd()}; + return run("npm", args, options); }; -const startMockSmapiServer = () => _startMockServer(MockServerPort.SMAPI, 'node_modules/ask-smapi-model/spec.json'); -const startMockLwaServer = () => _startMockServer(MockServerPort.LWA, 'test/integration/fixtures/lwa-swagger.json'); +const startMockSmapiServer = () => _startMockServer(MockServerPort.SMAPI, "node_modules/ask-smapi-model/spec.json"); +const startMockLwaServer = () => _startMockServer(MockServerPort.LWA, "test/integration/fixtures/lwa-swagger.json"); module.exports = { - KeySymbol, - getPathInTempDirectory, - makeFolderInTempDirectory, - resetTempDirectory, - deleteFolderInTempDirectory, - run, - startMockSmapiServer, - startMockLwaServer, - MockServerPort + KeySymbol, + getPathInTempDirectory, + makeFolderInTempDirectory, + resetTempDirectory, + deleteFolderInTempDirectory, + run, + startMockSmapiServer, + startMockLwaServer, + MockServerPort, }; diff --git a/test/tsconfig.json b/test/tsconfig.json new file mode 100644 index 00000000..306f39e8 --- /dev/null +++ b/test/tsconfig.json @@ -0,0 +1,8 @@ +{ + "compilerOptions": { + "types": ["mocha"], + "noEmit": true + }, + "extends": "../tsconfig.json", + "include": ["./**/*"] +} diff --git a/test/unit/builtins/build-flows/abstract-build-flow-test.js b/test/unit/builtins/build-flows/abstract-build-flow-test.js index d39f83d1..6fcad925 100644 --- a/test/unit/builtins/build-flows/abstract-build-flow-test.js +++ b/test/unit/builtins/build-flows/abstract-build-flow-test.js @@ -1,100 +1,100 @@ -const { expect } = require('chai'); -const childProcess = require('child_process'); -const fs = require('fs-extra'); -const path = require('path'); -const sinon = require('sinon'); - -const { makeFolderInTempDirectory } = require('@test/test-utils'); -const AbstractBuildFlow = require('@src/builtins/build-flows/abstract-build-flow'); -const Messenger = require('@src/view/messenger'); - -const fixturesDirectory = path.join(process.cwd(), 'test', 'unit', 'fixture', 'build-flow'); - -describe('AbstractBuildFlow test', () => { - let config; - let debugStub; - beforeEach(() => { - const cwd = makeFolderInTempDirectory('abstract-build-flow'); - const buildFile = path.join(cwd, 'build.zip'); - fs.copySync(fixturesDirectory, cwd); - config = { - cwd, - src: 'src', - buildFile, - doDebug: false - }; - debugStub = sinon.stub(); - sinon.stub(Messenger, 'getInstance').returns({ debug: debugStub }); +const {expect} = require("chai"); +const childProcess = require("child_process"); +const fs = require("fs-extra"); +const path = require("path"); +const sinon = require("sinon"); + +const {makeFolderInTempDirectory} = require("../../../test-utils"); +const AbstractBuildFlow = require("../../../../lib/builtins/build-flows/abstract-build-flow"); +const Messenger = require("../../../../lib/view/messenger"); + +const fixturesDirectory = path.join(process.cwd(), "test", "unit", "fixture", "build-flow"); + +describe("AbstractBuildFlow test", () => { + let config; + let debugStub; + beforeEach(() => { + const cwd = makeFolderInTempDirectory("abstract-build-flow"); + const buildFile = path.join(cwd, "build.zip"); + fs.copySync(fixturesDirectory, cwd); + config = { + cwd, + src: "src", + buildFile, + doDebug: false, + }; + debugStub = sinon.stub(); + sinon.stub(Messenger, "getInstance").returns({debug: debugStub}); + }); + + describe("# inspect correctness for constructor", () => { + it("| initiate the class", () => { + const buildFlow = new AbstractBuildFlow(config); + + expect(buildFlow).to.be.instanceOf(AbstractBuildFlow); }); - - describe('# inspect correctness for constructor', () => { - it('| initiate the class', () => { - const buildFlow = new AbstractBuildFlow(config); - - expect(buildFlow).to.be.instanceOf(AbstractBuildFlow); + }); + + describe("# inspect correctness of createZip and modifyZip", () => { + it("| should call create and modify temp zip", (done) => { + const buildFlow = new AbstractBuildFlow(config); + + buildFlow.createZip((err, res) => { + expect(err).eql(null); + expect(res).eql(""); + buildFlow.modifyZip((errModify, resModify) => { + expect(errModify).eql(null); + expect(resModify).eql(""); + done(); }); + }); }); - describe('# inspect correctness of createZip and modifyZip', () => { - it('| should call create and modify temp zip', (done) => { - const buildFlow = new AbstractBuildFlow(config); - - buildFlow.createZip((err, res) => { - expect(err).eql(null); - expect(res).eql(''); - buildFlow.modifyZip((errModify, resModify) => { - expect(errModify).eql(null); - expect(resModify).eql(''); - done(); - }); - }); - }); + it("| should call create and modify temp zip with options", (done) => { + const buildFlow = new AbstractBuildFlow(config); - it('| should call create and modify temp zip with options', (done) => { - const buildFlow = new AbstractBuildFlow(config); - - buildFlow.createZip({ filter: () => false }, (err, res) => { - expect(err).eql(null); - expect(res).eql(''); - buildFlow.modifyZip({ entryProcessor: () => {} }, (errModify, resModify) => { - expect(errModify).eql(null); - expect(resModify).eql(''); - done(); - }); - }); + buildFlow.createZip({filter: () => false}, (err, res) => { + expect(err).eql(null); + expect(res).eql(""); + buildFlow.modifyZip({entryProcessor: () => {}}, (errModify, resModify) => { + expect(errModify).eql(null); + expect(resModify).eql(""); + done(); }); + }); }); + }); - describe('# inspect correctness of execCommand', () => { - it('| should execute the command', () => { - const testCommand = 'test'; - const stub = sinon.stub(childProcess, 'execSync'); - const buildFlow = new AbstractBuildFlow(config); + describe("# inspect correctness of execCommand", () => { + it("| should execute the command", () => { + const testCommand = "test"; + const stub = sinon.stub(childProcess, "execSync"); + const buildFlow = new AbstractBuildFlow(config); - buildFlow.execCommand(testCommand); - expect(stub.callCount).eql(1); - expect(stub.args[0][0]).eql(testCommand); - }); + buildFlow.execCommand(testCommand); + expect(stub.callCount).eql(1); + expect(stub.args[0][0]).eql(testCommand); }); + }); - describe('# inspect correctness of debug', () => { - it('| should not output debug message', () => { - const buildFlow = new AbstractBuildFlow(config); + describe("# inspect correctness of debug", () => { + it("| should not output debug message", () => { + const buildFlow = new AbstractBuildFlow(config); - buildFlow.debug('test'); - expect(debugStub.callCount).eql(0); - }); + buildFlow.debug("test"); + expect(debugStub.callCount).eql(0); + }); - it('| should output debug message', () => { - config.doDebug = true; - const buildFlow = new AbstractBuildFlow(config); + it("| should output debug message", () => { + config.doDebug = true; + const buildFlow = new AbstractBuildFlow(config); - buildFlow.debug('test'); - expect(debugStub.callCount).eql(1); - }); + buildFlow.debug("test"); + expect(debugStub.callCount).eql(1); }); + }); - afterEach(() => { - sinon.restore(); - }); + afterEach(() => { + sinon.restore(); + }); }); diff --git a/test/unit/builtins/build-flows/custom-test.js b/test/unit/builtins/build-flows/custom-test.js index fc9d3961..b36b9b55 100644 --- a/test/unit/builtins/build-flows/custom-test.js +++ b/test/unit/builtins/build-flows/custom-test.js @@ -1,96 +1,96 @@ -const { expect } = require('chai'); -const path = require('path'); -const sinon = require('sinon'); +const {expect} = require("chai"); +const path = require("path"); +const sinon = require("sinon"); -const AbstractBuildFlow = require('@src/builtins/build-flows/abstract-build-flow'); -const CustomBuildFlow = require('@src/builtins/build-flows/custom'); +const AbstractBuildFlow = require("../../../../lib/builtins/build-flows/abstract-build-flow"); +const CustomBuildFlow = require("../../../../lib/builtins/build-flows/custom"); -describe('CustomBuildFlow test', () => { - let config; - let execStub; - let debugStub; - let platformStub; - beforeEach(() => { - config = { - cwd: 'cwd', - src: 'src', - buildFile: 'buildFile', - doDebug: false - }; - sinon.stub(path, 'join').returns('some-script'); - execStub = sinon.stub(AbstractBuildFlow.prototype, 'execCommand'); - debugStub = sinon.stub(AbstractBuildFlow.prototype, 'debug'); - platformStub = sinon.stub(process, 'platform').value('darwin'); - }); - describe('# inspect correctness of execute', () => { - it('| should execute commands', (done) => { - const buildFlow = new CustomBuildFlow(config); +describe("CustomBuildFlow test", () => { + let config; + let execStub; + let debugStub; + let platformStub; + beforeEach(() => { + config = { + cwd: "cwd", + src: "src", + buildFile: "buildFile", + doDebug: false, + }; + sinon.stub(path, "join").returns("some-script"); + execStub = sinon.stub(AbstractBuildFlow.prototype, "execCommand"); + debugStub = sinon.stub(AbstractBuildFlow.prototype, "debug"); + platformStub = sinon.stub(process, "platform").value("darwin"); + }); + describe("# inspect correctness of execute", () => { + it("| should execute commands", (done) => { + const buildFlow = new CustomBuildFlow(config); - buildFlow.execute((err, res) => { - expect(err).eql(undefined); - expect(res).eql(undefined); - expect(execStub.args[0][0]).eql('some-script "buildFile" false'); - done(); - }); - }); + buildFlow.execute((err, res) => { + expect(err).eql(undefined); + expect(res).eql(undefined); + expect(execStub.args[0][0]).eql('some-script "buildFile" false'); + done(); + }); + }); - it('| should execute commands on windows', (done) => { - platformStub.value('win32'); - const buildFlow = new CustomBuildFlow(config); + it("| should execute commands on windows", (done) => { + platformStub.value("win32"); + const buildFlow = new CustomBuildFlow(config); - buildFlow.execute((err, res) => { - expect(err).eql(undefined); - expect(res).eql(undefined); - expect(execStub.args[0][0]).eql('PowerShell.exe -Command "& {& \'some-script\' \'buildFile\' $False }"'); - done(); - }); - }); + buildFlow.execute((err, res) => { + expect(err).eql(undefined); + expect(res).eql(undefined); + expect(execStub.args[0][0]).eql("PowerShell.exe -Command \"& {& 'some-script' 'buildFile' $False }\""); + done(); + }); + }); - it('| should execute commands with debug', (done) => { - config.doDebug = true; - const buildFlow = new CustomBuildFlow(config); + it("| should execute commands with debug", (done) => { + config.doDebug = true; + const buildFlow = new CustomBuildFlow(config); - buildFlow.execute((err, res) => { - expect(err).eql(undefined); - expect(res).eql(undefined); - expect(execStub.args[0][0]).eql('some-script "buildFile" true'); - expect(debugStub.args[0][0]).eql('Executing custom hook script some-script.'); - done(); - }); - }); + buildFlow.execute((err, res) => { + expect(err).eql(undefined); + expect(res).eql(undefined); + expect(execStub.args[0][0]).eql('some-script "buildFile" true'); + expect(debugStub.args[0][0]).eql("Executing custom hook script some-script."); + done(); + }); + }); - it('| should execute commands with debug on windows', (done) => { - platformStub.value('win32'); - config.doDebug = true; - const buildFlow = new CustomBuildFlow(config); + it("| should execute commands with debug on windows", (done) => { + platformStub.value("win32"); + config.doDebug = true; + const buildFlow = new CustomBuildFlow(config); - buildFlow.execute((err, res) => { - expect(err).eql(undefined); - expect(res).eql(undefined); - expect(execStub.args[0][0]).eql('PowerShell.exe -Command "& {& \'some-script\' \'buildFile\' $True }"'); - expect(debugStub.args[0][0]).eql('Executing custom hook script some-script.'); - done(); - }); - }); + buildFlow.execute((err, res) => { + expect(err).eql(undefined); + expect(res).eql(undefined); + expect(execStub.args[0][0]).eql("PowerShell.exe -Command \"& {& 'some-script' 'buildFile' $True }\""); + expect(debugStub.args[0][0]).eql("Executing custom hook script some-script."); + done(); + }); }); + }); - describe('# inspect correctness of manifest getter', () => { - it('| should return manifest script for windows', () => { - platformStub.value('win32'); + describe("# inspect correctness of manifest getter", () => { + it("| should return manifest script for windows", () => { + platformStub.value("win32"); - const { manifest } = CustomBuildFlow; + const {manifest} = CustomBuildFlow; - expect(manifest).eq('build.ps1'); - }); + expect(manifest).eq("build.ps1"); + }); - it('| should return manifest script for non windows', () => { - const { manifest } = CustomBuildFlow; + it("| should return manifest script for non windows", () => { + const {manifest} = CustomBuildFlow; - expect(manifest).eq('build.sh'); - }); + expect(manifest).eq("build.sh"); }); + }); - afterEach(() => { - sinon.restore(); - }); + afterEach(() => { + sinon.restore(); + }); }); diff --git a/test/unit/builtins/build-flows/java-mvn-test.js b/test/unit/builtins/build-flows/java-mvn-test.js index 17819540..39724f54 100644 --- a/test/unit/builtins/build-flows/java-mvn-test.js +++ b/test/unit/builtins/build-flows/java-mvn-test.js @@ -1,85 +1,87 @@ -const { expect } = require('chai'); -const fs = require('fs-extra'); -const path = require('path'); -const sinon = require('sinon'); +const {expect} = require("chai"); +const fs = require("fs-extra"); +const path = require("path"); +const sinon = require("sinon"); -const AbstractBuildFlow = require('@src/builtins/build-flows/abstract-build-flow'); -const JavaMvnBuildFlow = require('@src/builtins/build-flows/java-mvn'); +const AbstractBuildFlow = require("../../../../lib/builtins/build-flows/abstract-build-flow"); +const JavaMvnBuildFlow = require("../../../../lib/builtins/build-flows/java-mvn"); -describe('JavaMvnBuildFlow test', () => { - let config; - let execStub; - let debugStub; - beforeEach(() => { - config = { - cwd: 'cwd', - src: 'src', - buildFile: 'buildFile', - doDebug: false - }; - sinon.stub(fs, 'moveSync'); - sinon.stub(fs, 'readdirSync').returns([]); - sinon.stub(path, 'join').returns('some-path'); - sinon.stub(AbstractBuildFlow.prototype, 'modifyZip').yields(); - execStub = sinon.stub(AbstractBuildFlow.prototype, 'execCommand'); - debugStub = sinon.stub(AbstractBuildFlow.prototype, 'debug'); - }); - describe('# inspect correctness of execute', () => { - it('| should execute commands', (done) => { - const buildFlow = new JavaMvnBuildFlow(config); +describe("JavaMvnBuildFlow test", () => { + let config; + let execStub; + let debugStub; + beforeEach(() => { + config = { + cwd: "cwd", + src: "src", + buildFile: "buildFile", + doDebug: false, + }; + sinon.stub(fs, "moveSync"); + sinon.stub(fs, "readdirSync").returns([]); + sinon.stub(path, "join").returns("some-path"); + sinon.stub(AbstractBuildFlow.prototype, "modifyZip").yields(); + execStub = sinon.stub(AbstractBuildFlow.prototype, "execCommand"); + debugStub = sinon.stub(AbstractBuildFlow.prototype, "debug"); + }); + describe("# inspect correctness of execute", () => { + it("| should execute commands", (done) => { + const buildFlow = new JavaMvnBuildFlow(config); - buildFlow.execute((err, res) => { - expect(err).eql(undefined); - expect(res).eql(undefined); - expect(execStub.args[0][0]).eql('mvn clean org.apache.maven.plugins:maven-' - + 'assembly-plugin:2.6:assembly -DdescriptorId=jar-with-dependencies package'); - done(); - }); - }); + buildFlow.execute((err, res) => { + expect(err).eql(undefined); + expect(res).eql(undefined); + expect(execStub.args[0][0]).eql( + "mvn clean org.apache.maven.plugins:maven-" + "assembly-plugin:2.6:assembly -DdescriptorId=jar-with-dependencies package", + ); + done(); + }); + }); - it('| should execute commands with debug', (done) => { - config.doDebug = true; - const buildFlow = new JavaMvnBuildFlow(config); + it("| should execute commands with debug", (done) => { + config.doDebug = true; + const buildFlow = new JavaMvnBuildFlow(config); - buildFlow.execute((err, res) => { - expect(err).eql(undefined); - expect(res).eql(undefined); - expect(execStub.args[0][0]).eql('mvn clean org.apache.maven.plugins:maven-' - + 'assembly-plugin:2.6:assembly -DdescriptorId=jar-with-dependencies package'); - expect(debugStub.args[0][0]).eql('Building skill artifacts based on the pom.xml.'); - expect(debugStub.args[1][0]).eql('Renaming the jar file some-path to buildFile.'); - done(); - }); - }); + buildFlow.execute((err, res) => { + expect(err).eql(undefined); + expect(res).eql(undefined); + expect(execStub.args[0][0]).eql( + "mvn clean org.apache.maven.plugins:maven-" + "assembly-plugin:2.6:assembly -DdescriptorId=jar-with-dependencies package", + ); + expect(debugStub.args[0][0]).eql("Building skill artifacts based on the pom.xml."); + expect(debugStub.args[1][0]).eql("Renaming the jar file some-path to buildFile."); + done(); + }); }); + }); - describe('# inspect correctness of removeCommentsFromPomProperties', () => { - it('| should remove comments from pom properties file', () => { - const entry = { - entryName: 'pom.properties', - getData: () => '# some comment\n# generated at Thu Oct 22 2020 12:28:31\nsome value\nanother-value', - setData: () => {} - }; - const setDataSpy = sinon.spy(entry, 'setData'); - const buildFlow = new JavaMvnBuildFlow(config); - buildFlow._removeCommentsFromPomProperties(entry); - expect(setDataSpy.args[0][0]).eq('some value\nanother-value'); - }); - - it('| should note remove comments from non pom properties file', () => { - const entry = { - entryName: 'other.properties', - getData: () => '# some comment\n# generated at Thu Oct 22 2020 12:28:31\nsome value\nanother-value', - setData: () => {} - }; - const setDataSpy = sinon.spy(entry, 'setData'); - const buildFlow = new JavaMvnBuildFlow(config); - buildFlow._removeCommentsFromPomProperties(entry); - expect(setDataSpy.callCount).eq(0); - }); + describe("# inspect correctness of removeCommentsFromPomProperties", () => { + it("| should remove comments from pom properties file", () => { + const entry = { + entryName: "pom.properties", + getData: () => "# some comment\n# generated at Thu Oct 22 2020 12:28:31\nsome value\nanother-value", + setData: () => {}, + }; + const setDataSpy = sinon.spy(entry, "setData"); + const buildFlow = new JavaMvnBuildFlow(config); + buildFlow._removeCommentsFromPomProperties(entry); + expect(setDataSpy.args[0][0]).eq("some value\nanother-value"); }); - afterEach(() => { - sinon.restore(); + it("| should note remove comments from non pom properties file", () => { + const entry = { + entryName: "other.properties", + getData: () => "# some comment\n# generated at Thu Oct 22 2020 12:28:31\nsome value\nanother-value", + setData: () => {}, + }; + const setDataSpy = sinon.spy(entry, "setData"); + const buildFlow = new JavaMvnBuildFlow(config); + buildFlow._removeCommentsFromPomProperties(entry); + expect(setDataSpy.callCount).eq(0); }); + }); + + afterEach(() => { + sinon.restore(); + }); }); diff --git a/test/unit/builtins/build-flows/nodejs-npm-test.js b/test/unit/builtins/build-flows/nodejs-npm-test.js index 5bfb6f5f..bb266b95 100644 --- a/test/unit/builtins/build-flows/nodejs-npm-test.js +++ b/test/unit/builtins/build-flows/nodejs-npm-test.js @@ -1,73 +1,73 @@ -const { expect } = require('chai'); -const sinon = require('sinon'); -const fs = require('fs-extra'); +const {expect} = require("chai"); +const sinon = require("sinon"); +const fs = require("fs-extra"); -const AbstractBuildFlow = require('@src/builtins/build-flows/abstract-build-flow'); -const NodeJsNpmBuildFlow = require('@src/builtins/build-flows/nodejs-npm'); +const AbstractBuildFlow = require("../../../../lib/builtins/build-flows/abstract-build-flow"); +const NodeJsNpmBuildFlow = require("../../../../lib/builtins/build-flows/nodejs-npm"); -describe('NodeJsNpmBuildFlow test', () => { - let config; - let execStub; - let debugStub; - let createZipStub; - let lockFileStub; - beforeEach(() => { - config = { - cwd: 'cwd', - src: 'src', - buildFile: 'buildFile', - doDebug: false - }; - execStub = sinon.stub(AbstractBuildFlow.prototype, 'execCommand'); - debugStub = sinon.stub(AbstractBuildFlow.prototype, 'debug'); - createZipStub = sinon.stub(AbstractBuildFlow.prototype, 'createZip').yields(); - lockFileStub = sinon.stub(fs, 'existsSync').returns(false); - }); - describe('# inspect correctness of execute', () => { - it('| should execute commands', (done) => { - const buildFlow = new NodeJsNpmBuildFlow(config); +describe("NodeJsNpmBuildFlow test", () => { + let config; + let execStub; + let debugStub; + let createZipStub; + let lockFileStub; + beforeEach(() => { + config = { + cwd: "cwd", + src: "src", + buildFile: "buildFile", + doDebug: false + }; + execStub = sinon.stub(AbstractBuildFlow.prototype, "execCommand"); + debugStub = sinon.stub(AbstractBuildFlow.prototype, "debug"); + createZipStub = sinon.stub(AbstractBuildFlow.prototype, "createZip").yields(); + lockFileStub = sinon.stub(fs, "existsSync").returns(false); + }); + describe("# inspect correctness of execute", () => { + it("| should execute commands", (done) => { + const buildFlow = new NodeJsNpmBuildFlow(config); - buildFlow.execute((err, res) => { - expect(err).eql(undefined); - expect(res).eql(undefined); - expect(buildFlow.env.NODE_ENV).eql('production'); - expect(execStub.args[0][0]).eql('npm install --quiet'); - expect(createZipStub.callCount).eql(1); - done(); - }); - }); + buildFlow.execute((err, res) => { + expect(err).eql(undefined); + expect(res).eql(undefined); + expect(buildFlow.env.NODE_ENV).eql("production"); + expect(execStub.args[0][0]).eql("npm install --quiet"); + expect(createZipStub.callCount).eql(1); + done(); + }); + }); - it('| should execute commands with package lock file', (done) => { - lockFileStub.returns(true); - const buildFlow = new NodeJsNpmBuildFlow(config); + it("| should execute commands with package lock file", (done) => { + lockFileStub.returns(true); + const buildFlow = new NodeJsNpmBuildFlow(config); - buildFlow.execute((err, res) => { - expect(err).eql(undefined); - expect(res).eql(undefined); - expect(buildFlow.env.NODE_ENV).eql('production'); - expect(execStub.args[0][0]).eql('npm ci --quiet'); - expect(createZipStub.callCount).eql(1); - done(); - }); - }); + buildFlow.execute((err, res) => { + expect(err).eql(undefined); + expect(res).eql(undefined); + expect(buildFlow.env.NODE_ENV).eql("production"); + expect(execStub.args[0][0]).eql("npm ci --quiet"); + expect(createZipStub.callCount).eql(1); + done(); + }); + }); - it('| should execute commands with debug flag', (done) => { - config.doDebug = true; - const buildFlow = new NodeJsNpmBuildFlow(config); + it("| should execute commands with debug flag", (done) => { + config.doDebug = true; + const buildFlow = new NodeJsNpmBuildFlow(config); - buildFlow.execute((err, res) => { - expect(err).eql(undefined); - expect(res).eql(undefined); - expect(buildFlow.env.NODE_ENV).eql('production'); - expect(execStub.args[0][0]).eql('npm install'); - expect(debugStub.args[0][0]).eql('Installing NodeJS dependencies based on the package.json.'); - expect(createZipStub.callCount).eql(1); - done(); - }); - }); + buildFlow.execute((err, res) => { + expect(err).eql(undefined); + expect(res).eql(undefined); + expect(buildFlow.env.NODE_ENV).eql("production"); + expect(execStub.args[0][0]).eql("npm install"); + expect(debugStub.args[0][0]).eql("Installing NodeJS dependencies based on the package.json."); + expect(createZipStub.callCount).eql(1); + done(); + }); }); + }); - afterEach(() => { - sinon.restore(); - }); + afterEach(() => { + sinon.restore(); + }); }); diff --git a/test/unit/builtins/build-flows/python-pip-test.js b/test/unit/builtins/build-flows/python-pip-test.js index a38ff994..659dd3b1 100644 --- a/test/unit/builtins/build-flows/python-pip-test.js +++ b/test/unit/builtins/build-flows/python-pip-test.js @@ -1,92 +1,94 @@ -const { expect } = require('chai'); -const childProcess = require('child_process'); -const sinon = require('sinon'); +const {expect} = require("chai"); +const childProcess = require("child_process"); +const sinon = require("sinon"); -const AbstractBuildFlow = require('@src/builtins/build-flows/abstract-build-flow'); -const PythonPipBuildFlow = require('@src/builtins/build-flows/python-pip'); +const AbstractBuildFlow = require("../../../../lib/builtins/build-flows/abstract-build-flow"); +const PythonPipBuildFlow = require("../../../../lib/builtins/build-flows/python-pip"); -describe('PythonPipBuildFlow test', () => { - let config; - let execStub; - let debugStub; - let createZipStub; - let platformStub; - let checkVersionStub; - beforeEach(() => { - config = { - cwd: 'cwd', - src: 'src', - buildFile: 'buildFile', - doDebug: false - }; - execStub = sinon.stub(AbstractBuildFlow.prototype, 'execCommand'); - debugStub = sinon.stub(AbstractBuildFlow.prototype, 'debug'); - createZipStub = sinon.stub(AbstractBuildFlow.prototype, 'createZip').yields(); - platformStub = sinon.stub(process, 'platform').value('darwin'); - checkVersionStub = sinon.stub(childProcess, 'spawnSync').returns({ output: ', Python 3.10.1 ,' }); - }); - describe('# inspect correctness of execute', () => { - it('| should execute commands', (done) => { - const buildFlow = new PythonPipBuildFlow(config); +describe("PythonPipBuildFlow test", () => { + let config; + let execStub; + let debugStub; + let createZipStub; + let platformStub; + let checkVersionStub; + beforeEach(() => { + config = { + cwd: "cwd", + src: "src", + buildFile: "buildFile", + doDebug: false, + }; + execStub = sinon.stub(AbstractBuildFlow.prototype, "execCommand"); + debugStub = sinon.stub(AbstractBuildFlow.prototype, "debug"); + createZipStub = sinon.stub(AbstractBuildFlow.prototype, "createZip").yields(); + platformStub = sinon.stub(process, "platform").value("darwin"); + checkVersionStub = sinon.stub(childProcess, "spawnSync").returns({output: ", Python 3.7.2 ,"}); + }); + describe("# inspect correctness of execute", () => { + it("| should execute commands", (done) => { + const buildFlow = new PythonPipBuildFlow(config); - buildFlow.execute((err, res) => { - expect(err).eql(undefined); - expect(res).eql(undefined); - expect(execStub.args[0][0]).eql('python3 -m venv venv'); - expect(execStub.args[1][0]).eql('venv/bin/python -m pip --disable-pip-version-check install -r requirements.txt -t ./'); - expect(createZipStub.callCount).eql(1); - expect(checkVersionStub.callCount).eql(1); - done(); - }); - }); + buildFlow.execute((err, res) => { + expect(err).eql(undefined); + expect(res).eql(undefined); + expect(execStub.args[0][0]).eql("python3 -m venv venv"); + expect(execStub.args[1][0]).eql("venv/bin/python -m pip --disable-pip-version-check install -r requirements.txt -t ./"); + expect(createZipStub.callCount).eql(1); + expect(checkVersionStub.callCount).eql(1); + done(); + }); + }); - it('| should execute commands for windows', (done) => { - platformStub.value('win32'); - const buildFlow = new PythonPipBuildFlow(config); + it("| should execute commands for windows", (done) => { + platformStub.value("win32"); + const buildFlow = new PythonPipBuildFlow(config); - buildFlow.execute((err, res) => { - expect(err).eql(undefined); - expect(res).eql(undefined); - expect(execStub.args[0][0]).eql('python -m venv venv'); - expect(execStub.args[1][0]).eql('"venv/Scripts/pip3" --disable-pip-version-check install -r requirements.txt -t ./'); - expect(createZipStub.callCount).eql(1); - expect(checkVersionStub.callCount).eql(1); - done(); - }); - }); + buildFlow.execute((err, res) => { + expect(err).eql(undefined); + expect(res).eql(undefined); + expect(execStub.args[0][0]).eql("python -m venv venv"); + expect(execStub.args[1][0]).eql('"venv/Scripts/pip3" --disable-pip-version-check install -r requirements.txt -t ./'); + expect(createZipStub.callCount).eql(1); + expect(checkVersionStub.callCount).eql(1); + done(); + }); + }); - it('| should execute commands with debug flag', (done) => { - config.doDebug = true; - const buildFlow = new PythonPipBuildFlow(config); + it("| should execute commands with debug flag", (done) => { + config.doDebug = true; + const buildFlow = new PythonPipBuildFlow(config); - buildFlow.execute((err, res) => { - expect(err).eql(undefined); - expect(res).eql(undefined); - expect(execStub.args[0][0]).eql('python3 -m venv venv'); - expect(execStub.args[1][0]).eql('venv/bin/python -m pip --disable-pip-version-check install -r requirements.txt -t ./'); - expect(debugStub.args[0][0]).eql('Setting up virtual environment.'); - expect(debugStub.args[1][0]).eql('Installing Python dependencies based on the requirements.txt.'); - expect(checkVersionStub.callCount).eql(1); - done(); - }); - }); + buildFlow.execute((err, res) => { + expect(err).eql(undefined); + expect(res).eql(undefined); + expect(execStub.args[0][0]).eql("python3 -m venv venv"); + expect(execStub.args[1][0]).eql("venv/bin/python -m pip --disable-pip-version-check install -r requirements.txt -t ./"); + expect(debugStub.args[0][0]).eql("Setting up virtual environment."); + expect(debugStub.args[1][0]).eql("Installing Python dependencies based on the requirements.txt."); + expect(checkVersionStub.callCount).eql(1); + done(); + }); + }); - it('| should throw error when python 2 is used', (done) => { - checkVersionStub.returns({ output: ', Python 2.7.2 ,' }); - const buildFlow = new PythonPipBuildFlow(config); + it("| should throw error when python 2 is used", (done) => { + checkVersionStub.returns({output: ", Python 2.7.2 ,"}); + const buildFlow = new PythonPipBuildFlow(config); - buildFlow.execute((err, res) => { - expect(err.message).eql('Current python (2.7.2) is not supported. ' - + 'Please make sure you are using python3, or use your custom script to build the code.'); - expect(res).eql(undefined); - expect(checkVersionStub.callCount).eql(1); - expect(createZipStub.callCount).eql(0); - done(); - }); - }); + buildFlow.execute((err, res) => { + expect(err.message).eql( + "Current python (2.7.2) is not supported. " + + "Please make sure you are using python3, or use your custom script to build the code.", + ); + expect(res).eql(undefined); + expect(checkVersionStub.callCount).eql(1); + expect(createZipStub.callCount).eql(0); + done(); + }); }); + }); - afterEach(() => { - sinon.restore(); - }); + afterEach(() => { + sinon.restore(); + }); }); diff --git a/test/unit/builtins/build-flows/zip-only-test.js b/test/unit/builtins/build-flows/zip-only-test.js index 1d9b8d9e..c0fca33d 100644 --- a/test/unit/builtins/build-flows/zip-only-test.js +++ b/test/unit/builtins/build-flows/zip-only-test.js @@ -1,35 +1,35 @@ -const { expect } = require('chai'); -const sinon = require('sinon'); +const {expect} = require("chai"); +const sinon = require("sinon"); -const AbstractBuildFlow = require('@src/builtins/build-flows/abstract-build-flow'); -const ZipOnlyBuildFlow = require('@src/builtins/build-flows/zip-only'); +const AbstractBuildFlow = require("../../../../lib/builtins/build-flows/abstract-build-flow"); +const ZipOnlyBuildFlow = require("../../../../lib/builtins/build-flows/zip-only"); -describe('ZipOnlyBuildFlow test', () => { - let config; - let createZipStub; - beforeEach(() => { - config = { - cwd: 'cwd', - src: 'src', - buildFile: 'buildFile', - doDebug: false - }; - createZipStub = sinon.stub(AbstractBuildFlow.prototype, 'createZip').yields(); - }); - describe('# inspect correctness of execute', () => { - it('| should execute commands', (done) => { - const buildFlow = new ZipOnlyBuildFlow(config); +describe("ZipOnlyBuildFlow test", () => { + let config; + let createZipStub; + beforeEach(() => { + config = { + cwd: "cwd", + src: "src", + buildFile: "buildFile", + doDebug: false, + }; + createZipStub = sinon.stub(AbstractBuildFlow.prototype, "createZip").yields(); + }); + describe("# inspect correctness of execute", () => { + it("| should execute commands", (done) => { + const buildFlow = new ZipOnlyBuildFlow(config); - buildFlow.execute((err, res) => { - expect(err).eql(undefined); - expect(res).eql(undefined); - expect(createZipStub.callCount).eql(1); - done(); - }); - }); + buildFlow.execute((err, res) => { + expect(err).eql(undefined); + expect(res).eql(undefined); + expect(createZipStub.callCount).eql(1); + done(); + }); }); + }); - afterEach(() => { - sinon.restore(); - }); + afterEach(() => { + sinon.restore(); + }); }); diff --git a/test/unit/builtins/cfn-deployer/helper-test.js b/test/unit/builtins/cfn-deployer/helper-test.js index cf007382..af8c0bb0 100644 --- a/test/unit/builtins/cfn-deployer/helper-test.js +++ b/test/unit/builtins/cfn-deployer/helper-test.js @@ -1,240 +1,239 @@ -const aws = require('aws-sdk'); -const { expect } = require('chai'); -const fs = require('fs'); -const sinon = require('sinon'); - -const CliCFNDeployerError = require('@src/exceptions/cli-cfn-deployer-error'); -const Helper = require('@src/builtins/deploy-delegates/cfn-deployer/helper'); - -describe('Builtins test - cfn-deployer helper test', () => { - const profile = 'default'; - const doDebug = false; - const awsProfile = 'test'; - const awsRegion = 'test-region'; - const bucketName = 'some-bucket'; - const versioningConfiguration = { MFADelete: 'Disabled', Status: 'Enabled' }; - const stackId = 'some id'; - const stackName = 'some name'; - const templateBody = 'some template body'; - const endpointUri = 'some-endpoint'; - const parameters = [{ ParameterKey: 'SkillId', ParameterValue: 'some id' }]; - const capabilities = []; - let helper; - let reporter; - let updateStatusStub; - let headBucketStub; - let createBucketStub; - let waitForStub; - let getBucketVersioningStub; - let putBucketVersioningStub; - let putObjectStub; - let describeStacksStub; - let updateStackStub; - let createStackStub; - let describeStackEventsStub; - - beforeEach(() => { - createBucketStub = sinon.stub().returns({ promise: sinon.stub().resolves() }); - headBucketStub = sinon.stub(); - waitForStub = sinon.stub().returns({ promise: sinon.stub().resolves() }); - getBucketVersioningStub = sinon.stub(); - putBucketVersioningStub = sinon.stub().returns({ promise: sinon.stub().resolves() }); - putObjectStub = sinon.stub().returns({ promise: sinon.stub().resolves() }); - - sinon.stub(aws, 'S3').returns({ - headBucket: headBucketStub, - createBucket: createBucketStub, - waitFor: waitForStub, - getBucketVersioning: getBucketVersioningStub, - putBucketVersioning: putBucketVersioningStub, - putObject: putObjectStub - }); - - describeStacksStub = sinon.stub(); - updateStackStub = sinon.stub().returns({ promise: sinon.stub().resolves() }); - createStackStub = sinon.stub().returns({ promise: sinon.stub().resolves() }); - describeStackEventsStub = sinon.stub(); - - sinon.stub(aws, 'CloudFormation').returns({ - describeStacks: describeStacksStub, - updateStack: updateStackStub, - createStack: createStackStub, - describeStackEvents: describeStackEventsStub - }); - updateStatusStub = sinon.stub(); - - reporter = { - updateStatus: updateStatusStub - }; - - helper = new Helper(profile, doDebug, awsProfile, awsRegion, reporter); - sinon.stub(helper, 'sleep').resolves(); - }); +const aws = require("aws-sdk"); +const {expect} = require("chai"); +const fs = require("fs"); +const sinon = require("sinon"); + +const CliCFNDeployerError = require("../../../../lib/exceptions/cli-cfn-deployer-error"); +const Helper = require("../../../../lib/builtins/deploy-delegates/cfn-deployer/helper"); + +describe("Builtins test - cfn-deployer helper test", () => { + const profile = 'default'; + const doDebug = false; + const awsProfile = "test"; + const awsRegion = "test-region"; + const bucketName = "some-bucket"; + const versioningConfiguration = {MFADelete: "Disabled", Status: "Enabled"}; + const stackId = "some id"; + const stackName = "some name"; + const templateBody = "some template body"; + const endpointUri = "some-endpoint"; + const parameters = [{ParameterKey: "SkillId", ParameterValue: "some id"}]; + const capabilities = []; + let helper; + let reporter; + let updateStatusStub; + let headBucketStub; + let createBucketStub; + let waitForStub; + let getBucketVersioningStub; + let putBucketVersioningStub; + let putObjectStub; + let describeStacksStub; + let updateStackStub; + let createStackStub; + let describeStackEventsStub; + + beforeEach(() => { + createBucketStub = sinon.stub().returns({promise: sinon.stub().resolves()}); + headBucketStub = sinon.stub(); + waitForStub = sinon.stub().returns({promise: sinon.stub().resolves()}); + getBucketVersioningStub = sinon.stub(); + putBucketVersioningStub = sinon.stub().returns({promise: sinon.stub().resolves()}); + putObjectStub = sinon.stub().returns({promise: sinon.stub().resolves()}); + + sinon.stub(aws, "S3").returns({ + headBucket: headBucketStub, + createBucket: createBucketStub, + waitFor: waitForStub, + getBucketVersioning: getBucketVersioningStub, + putBucketVersioning: putBucketVersioningStub, + putObject: putObjectStub, + }); + + describeStacksStub = sinon.stub(); + updateStackStub = sinon.stub().returns({promise: sinon.stub().resolves()}); + createStackStub = sinon.stub().returns({promise: sinon.stub().resolves()}); + describeStackEventsStub = sinon.stub(); + + sinon.stub(aws, "CloudFormation").returns({ + describeStacks: describeStacksStub, + updateStack: updateStackStub, + createStack: createStackStub, + describeStackEvents: describeStackEventsStub, + }); + updateStatusStub = sinon.stub(); + + reporter = { + updateStatus: updateStatusStub, + }; + + helper = new Helper(profile, doDebug, awsProfile, awsRegion, reporter); + sinon.stub(helper, "sleep").resolves(); + }); + + it("should not create s3 bucket when the bucket already exists", async () => { + headBucketStub.returns({promise: sinon.stub().resolves()}); + + await helper.createS3BucketIfNotExists(bucketName); + + expect(headBucketStub.callCount).eq(1); + expect(createBucketStub.callCount).eq(0); + }); + + it("should create s3 bucket when the bucket does not exist in us-east-1", async () => { + headBucketStub.returns({promise: sinon.stub().rejects()}); + + helper = new Helper(profile, doDebug, awsProfile, 'us-east-1', reporter); + await helper.createS3BucketIfNotExists(bucketName); + + expect(headBucketStub.callCount).eq(1); + expect(createBucketStub.callCount).eq(1); + expect(createBucketStub.args[0][0].Bucket).eq(bucketName); + expect(waitForStub.callCount).eq(1); + }); + + it("should create s3 bucket when the bucket does not exist in non us-east-1", async () => { + headBucketStub.returns({promise: sinon.stub().rejects()}); + + await helper.createS3BucketIfNotExists(bucketName); + + expect(headBucketStub.callCount).eq(1); + expect(createBucketStub.callCount).eq(1); + expect(createBucketStub.args[0][0].Bucket).eq(bucketName); + expect(createBucketStub.args[0][0].CreateBucketConfiguration.LocationConstraint).eq(awsRegion); + expect(waitForStub.callCount).eq(1); + }); + + it("should not enable s3 bucket versioning when the versioning already enabled", async () => { + getBucketVersioningStub.returns({promise: sinon.stub().resolves(versioningConfiguration)}); + + await helper.enableS3BucketVersioningIfNotEnabled(bucketName); + + expect(putBucketVersioningStub.callCount).eq(0); + }); + + it("should enable s3 bucket versioning when the versioning is not enabled", async () => { + getBucketVersioningStub.returns({promise: sinon.stub().resolves({})}); + + await helper.enableS3BucketVersioningIfNotEnabled(bucketName); + + expect(putBucketVersioningStub.callCount).eq(1); + expect(putBucketVersioningStub.args[0][0]).eql({Bucket: bucketName, VersioningConfiguration: versioningConfiguration}); + }); - it('should not create s3 bucket when the bucket already exists', async () => { - headBucketStub.returns({ promise: sinon.stub().resolves() }); + it("should upload to s3", async () => { + const objectBody = "some body"; + sinon.stub(fs, "readFileSync").returns(objectBody); + const bucketKey = "someKey"; + const filePath = "some-path"; - await helper.createS3BucketIfNotExists(bucketName); + await helper.uploadToS3(bucketName, bucketKey, filePath); - expect(headBucketStub.callCount).eq(1); - expect(createBucketStub.callCount).eq(0); - }); + expect(putObjectStub.callCount).eq(1); + expect(putObjectStub.args[0][0]).eql({Bucket: bucketName, Key: bucketKey, Body: objectBody}); + expect(updateStatusStub.callCount).eq(1); + expect(updateStatusStub.args[0][0]).eq(`Uploading code artifact to s3://${bucketName}/${bucketKey}`); + }); - it('should create s3 bucket when the bucket does not exist in us-east-1', async () => { - headBucketStub.returns({ promise: sinon.stub().rejects() }); + it("should create new cloud formation stack when stack does not exist", async () => { + describeStacksStub.returns({promise: sinon.stub().rejects({})}); - helper = new Helper(profile, doDebug, awsProfile, 'us-east-1', reporter); - await helper.createS3BucketIfNotExists(bucketName); + await helper.deployStack(stackId, stackName, templateBody, parameters, capabilities); - expect(headBucketStub.callCount).eq(1); - expect(createBucketStub.callCount).eq(1); - expect(createBucketStub.args[0][0].Bucket).eq(bucketName); - expect(waitForStub.callCount).eq(1); - }); + expect(updateStatusStub.args[0][0]).contains("No stack exists or stack has been deleted. Creating cloudformation stack"); + expect(createStackStub.callCount).eq(1); + expect(createStackStub.args[0][0]).eql({StackName: stackName, Capabilities: [], TemplateBody: templateBody, Parameters: parameters}); + }); - it('should create s3 bucket when the bucket does not exist in non us-east-1', async () => { - headBucketStub.returns({ promise: sinon.stub().rejects() }); + it("should create new cloud formation stack when stack id is undefined", async () => { + await helper.deployStack(undefined, stackName, templateBody, parameters, capabilities); - await helper.createS3BucketIfNotExists(bucketName); + expect(updateStatusStub.args[0][0]).contains("No stack exists or stack has been deleted. Creating cloudformation stack"); + expect(createStackStub.callCount).eq(1); + expect(createStackStub.args[0][0]).eql({StackName: stackName, Capabilities: [], TemplateBody: templateBody, Parameters: parameters}); + }); - expect(headBucketStub.callCount).eq(1); - expect(createBucketStub.callCount).eq(1); - expect(createBucketStub.args[0][0].Bucket).eq(bucketName); - expect(createBucketStub.args[0][0].CreateBucketConfiguration.LocationConstraint).eq(awsRegion); - expect(waitForStub.callCount).eq(1); - }); + it("should update cloud formation stack when stack exists", async () => { + describeStacksStub.returns({promise: sinon.stub().resolves({Stacks: [{StackStatus: "CREATE_COMPLETE"}]})}); - it('should not enable s3 bucket versioning when the versioning already enabled', async () => { - getBucketVersioningStub.returns({ promise: sinon.stub().resolves(versioningConfiguration) }); - - await helper.enableS3BucketVersioningIfNotEnabled(bucketName); - - expect(putBucketVersioningStub.callCount).eq(0); - }); + await helper.deployStack(stackId, stackName, templateBody, parameters, capabilities); - it('should enable s3 bucket versioning when the versioning is not enabled', async () => { - getBucketVersioningStub.returns({ promise: sinon.stub().resolves({}) }); + expect(updateStatusStub.args[0][0]).contains(`Updating stack (${stackId})...`); + expect(updateStackStub.callCount).eq(1); + expect(updateStackStub.args[0][0]).eql({StackName: stackId, Capabilities: [], TemplateBody: templateBody, Parameters: parameters}); + }); - await helper.enableS3BucketVersioningIfNotEnabled(bucketName); - - expect(putBucketVersioningStub.callCount).eq(1); - expect(putBucketVersioningStub.args[0][0]).eql({ Bucket: bucketName, VersioningConfiguration: versioningConfiguration }); - }); - - it('should upload to s3', async () => { - const objectBody = 'some body'; - sinon.stub(fs, 'readFileSync').returns(objectBody); - const bucketKey = 'someKey'; - const filePath = 'some-path'; - - await helper.uploadToS3(bucketName, bucketKey, filePath); - - expect(putObjectStub.callCount).eq(1); - expect(putObjectStub.args[0][0]).eql({ Bucket: bucketName, Key: bucketKey, Body: objectBody }); - expect(updateStatusStub.callCount).eq(1); - expect(updateStatusStub.args[0][0]).eq(`Uploading code artifact to s3://${bucketName}/${bucketKey}`); - }); + it("should wait for cloud formation stack deploy and return endpoint uri", async () => { + const stackInfo1 = {StackStatus: "CREATE_IN_PROGRESS", StackStatusReason: "User initiated"}; + const stackInfo2 = {StackStatus: "CREATE_COMPLETE", Outputs: [{OutputKey: "SkillEndpoint", OutputValue: endpointUri}]}; - it('should create new cloud formation stack when stack does not exist', async () => { - describeStacksStub.returns({ promise: sinon.stub().rejects({}) }); + describeStacksStub.onCall(0).returns({promise: sinon.stub().resolves({Stacks: [stackInfo1]})}); + describeStacksStub.onCall(1).returns({promise: sinon.stub().resolves({Stacks: [stackInfo2]})}); - await helper.deployStack(stackId, stackName, templateBody, parameters, capabilities); + const response = await helper.waitForStackDeploy(stackId); - expect(updateStatusStub.args[0][0]).contains('No stack exists or stack has been deleted. Creating cloudformation stack'); - expect(createStackStub.callCount).eq(1); - expect(createStackStub.args[0][0]).eql({ StackName: stackName, Capabilities: [], TemplateBody: templateBody, Parameters: parameters }); - }); + expect(response).eql({stackInfo: stackInfo2, endpointUri}); + expect(updateStatusStub.args[0][0]).eq( + `Current stack status: ${stackInfo1.StackStatus}... Status reason: ${stackInfo1.StackStatusReason}.`, + ); + expect(updateStatusStub.args[1][0]).eq(`Current stack status: ${stackInfo2.StackStatus}... `); + }); - it('should create new cloud formation stack when stack id is undefined', async () => { - await helper.deployStack(undefined, stackName, templateBody, parameters, capabilities); + it("should wait for cloud formation stack deploy and throw a deploy error", async () => { + const stackInfo = {StackStatus: "ROLLBACK_COMPLETE", Outputs: [{OutputKey: "SkillEndpoint", OutputValue: endpointUri}]}; + describeStacksStub.returns({promise: sinon.stub().resolves({Stacks: [stackInfo]})}); - expect(updateStatusStub.args[0][0]).contains('No stack exists or stack has been deleted. Creating cloudformation stack'); - expect(createStackStub.callCount).eq(1); - expect(createStackStub.args[0][0]).eql({ StackName: stackName, Capabilities: [], TemplateBody: templateBody, Parameters: parameters }); + const failureReason = "some failure reason"; + const stackEvent = { + ResourceStatus: "CREATE_FAILED", + LogicalResourceId: "some resource id", + ResourceType: "some resource type", + ResourceStatusReason: failureReason, + }; + describeStackEventsStub.returns({ + promise: sinon.stub().resolves({StackEvents: [{ResourceStatus: "reason 1"}, stackEvent, {ResourceStatus: "reason 2"}]}), }); - it('should update cloud formation stack when stack exists', async () => { - describeStacksStub.returns({ promise: sinon.stub().resolves({ Stacks: [{ StackStatus: 'CREATE_COMPLETE' }] }) }); - - await helper.deployStack(stackId, stackName, templateBody, parameters, capabilities); - - expect(updateStatusStub.args[0][0]).contains(`Updating stack (${stackId})...`); - expect(updateStackStub.callCount).eq(1); - expect(updateStackStub.args[0][0]).eql({ StackName: stackId, Capabilities: [], TemplateBody: templateBody, Parameters: parameters }); + return helper.waitForStackDeploy(stackId).catch((err) => { + expect(err).instanceOf(CliCFNDeployerError); + expect(err.message).includes(failureReason); }); + }); - it('should wait for cloud formation stack deploy and return endpoint uri', async () => { - const stackInfo1 = { StackStatus: 'CREATE_IN_PROGRESS', StackStatusReason: 'User initiated' }; - const stackInfo2 = { StackStatus: 'CREATE_COMPLETE', - Outputs: [{ OutputKey: 'SkillEndpoint', OutputValue: endpointUri }] }; - - describeStacksStub.onCall(0).returns({ promise: sinon.stub() - .resolves({ Stacks: [stackInfo1] }) }); - describeStacksStub.onCall(1).returns({ promise: sinon.stub() - .resolves({ Stacks: [stackInfo2] }) }); + it("should wait for cloud formation stack deploy and throw a default error", async () => { + const stackInfo = {StackStatus: "ROLLBACK_COMPLETE", Outputs: [{OutputKey: "SkillEndpoint", OutputValue: endpointUri}]}; + describeStacksStub.returns({promise: sinon.stub().resolves({Stacks: [stackInfo]})}); - const response = await helper.waitForStackDeploy(stackId); - - expect(response).eql({ stackInfo: stackInfo2, endpointUri }); - expect(updateStatusStub.args[0][0]).eq(`Current stack status: ${stackInfo1.StackStatus}... Status reason: ${stackInfo1.StackStatusReason}.`); - expect(updateStatusStub.args[1][0]).eq(`Current stack status: ${stackInfo2.StackStatus}... `); + describeStackEventsStub.returns({ + promise: sinon.stub().resolves({StackEvents: [{ResourceStatus: "reason 1"}, {ResourceStatus: "reason 2"}]}), }); - it('should wait for cloud formation stack deploy and throw a deploy error', async () => { - const stackInfo = { StackStatus: 'ROLLBACK_COMPLETE', - Outputs: [{ OutputKey: 'SkillEndpoint', OutputValue: endpointUri }] }; - describeStacksStub.returns({ promise: sinon.stub() - .resolves({ Stacks: [stackInfo] }) }); - - const failureReason = 'some failure reason'; - const stackEvent = { ResourceStatus: 'CREATE_FAILED', - LogicalResourceId: 'some resource id', - ResourceType: 'some resource type', - ResourceStatusReason: failureReason }; - describeStackEventsStub.returns({ promise: sinon.stub() - .resolves({ StackEvents: [{ ResourceStatus: 'reason 1' }, stackEvent, { ResourceStatus: 'reason 2' }] }) }); - - return helper.waitForStackDeploy(stackId).catch(err => { - expect(err).instanceOf(CliCFNDeployerError); - expect(err.message).includes(failureReason); - }); + return helper.waitForStackDeploy(stackId).catch((err) => { + expect(err).instanceOf(CliCFNDeployerError); + expect(err.message).includes("We could not find details for deploy error"); }); + }); - it('should wait for cloud formation stack deploy and throw a default error', async () => { - const stackInfo = { StackStatus: 'ROLLBACK_COMPLETE', - Outputs: [{ OutputKey: 'SkillEndpoint', OutputValue: endpointUri }] }; - describeStacksStub.returns({ promise: sinon.stub() - .resolves({ Stacks: [stackInfo] }) }); - - describeStackEventsStub.returns({ promise: sinon.stub() - .resolves({ StackEvents: [{ ResourceStatus: 'reason 1' }, { ResourceStatus: 'reason 2' }] }) }); + it("should get skill credentials successful", async () => { + const credentials = {clientId: "id", clientSecret: "secret"}; + const response = { body: { skillMessagingCredentials: credentials } }; + sinon.stub(helper.smapiClient.skill, "getSkillCredentials").yields(null, response); - return helper.waitForStackDeploy(stackId).catch(err => { - expect(err).instanceOf(CliCFNDeployerError); - expect(err.message).includes('We could not find details for deploy error'); - }); - }); + const result = await helper.getSkillCredentials("skill-id"); - it('should get skill credentials successful', async () => { - const credentials = { clientId: 'id', clientSecret: 'secret' }; - const response = { body: { skillMessagingCredentials: credentials } }; - sinon.stub(helper.smapiClient.skill, 'getSkillCredentials').yields(null, response); - - const result = await helper.getSkillCredentials('skill-id'); - - expect(result).eql(credentials); - }); + expect(result).eql(credentials); +}); - it('should get skill credentials failure', async () => { - const error = 'some failure reason'; - sinon.stub(helper.smapiClient.skill, 'getSkillCredentials').yields(error); +it("should get skill credentials failure", async () => { + const error = "some failure reason"; + sinon.stub(helper.smapiClient.skill, "getSkillCredentials").yields(error); - return helper.getSkillCredentials('skill-id').catch(err => { - expect(err).eql(error); - }); + return helper.getSkillCredentials("skill-id").catch(err => { + expect(err).eql(error); }); +}); - afterEach(() => { - sinon.restore(); - }); + afterEach(() => { + sinon.restore(); + }); }); diff --git a/test/unit/builtins/cfn-deployer/index-test.js b/test/unit/builtins/cfn-deployer/index-test.js index b008cf00..d2d07183 100644 --- a/test/unit/builtins/cfn-deployer/index-test.js +++ b/test/unit/builtins/cfn-deployer/index-test.js @@ -1,314 +1,306 @@ -const fs = require('fs'); -const path = require('path'); -const { expect } = require('chai'); -const sinon = require('sinon'); - -const awsUtil = require('@src/clients/aws-client/aws-util'); -const CliCFNDeployerError = require('@src/exceptions/cli-cfn-deployer-error'); -const Helper = require('@src/builtins/deploy-delegates/cfn-deployer/helper'); -const Deployer = require('@src/builtins/deploy-delegates/cfn-deployer/index'); - -describe('Builtins test - cfn-deployer index test', () => { - const templatePath = path.join(process.cwd(), 'test', 'unit', 'fixture', 'model', 'yaml-config.yml'); - const s3VersionId = 'some version'; - const profile = 'default'; - const alexaRegion = 'default'; - const awsRegion = 'us-east-1'; - const runtime = 'nodejs12.x'; - const handler = 'index.handler'; - const stackId = 'some stack id'; - const bucketName = 'someName'; - const bucketKey = 'someKey.zip'; - const endpointUri = 'some endpoint uri'; - const userDefinedParamKey = 'someKey'; - const userDefinedParamValue = 'someValue'; - let waitForStackDeployStub; - let getAWSProfileStub; - let deployStackStub; - - describe('bootstrap', () => { - const bootstrapOptions = { - profile, - userConfig: { runtime, handler }, - workspacePath: 'some-path' +const fs = require("fs"); +const path = require("path"); +const {expect} = require("chai"); +const sinon = require("sinon"); + +const awsUtil = require("../../../../lib/clients/aws-client/aws-util"); +const CliCFNDeployerError = require("../../../../lib/exceptions/cli-cfn-deployer-error"); +const Helper = require("../../../../lib/builtins/deploy-delegates/cfn-deployer/helper"); +const Deployer = require("../../../../lib/builtins/deploy-delegates/cfn-deployer/index"); + +describe("Builtins test - cfn-deployer index test", () => { + const templatePath = path.join(process.cwd(), "test", "unit", "fixture", "model", "yaml-config.yml"); + const s3VersionId = "some version"; + const profile = "default"; + const alexaRegion = "default"; + const awsRegion = "us-east-1"; + const runtime = "nodejs12.x"; + const handler = "index.handler"; + const stackId = "some stack id"; + const bucketName = "someName"; + const bucketKey = "someKey.zip"; + const endpointUri = "some endpoint uri"; + const userDefinedParamKey = "someKey"; + const userDefinedParamValue = "someValue"; + let waitForStackDeployStub; + let getAWSProfileStub; + let deployStackStub; + + describe("bootstrap", () => { + const bootstrapOptions = { + profile, + userConfig: {runtime, handler}, + workspacePath: "some-path", + }; + + beforeEach(() => { + sinon.stub(fs, "readFileSync"); + sinon.stub(fs, "writeFileSync"); + getAWSProfileStub = sinon.stub(awsUtil, "getAWSProfile"); + sinon.stub(awsUtil, "getCLICompatibleDefaultRegion").returns(awsRegion); + }); + it("should bootstrap deployer", (done) => { + Deployer.bootstrap(bootstrapOptions, (err, result) => { + const expected = { + userConfig: {runtime, handler, templatePath: `./infrastructure/${bootstrapOptions.workspacePath}/skill-stack.yaml`, awsRegion}, }; + expect(err).eql(null); + expect(result).eql(expected); + done(); + }); + }); + + it("should catch bootstrap error", (done) => { + const errorMessage = "some error"; + getAWSProfileStub.throws(new Error(errorMessage)); + + Deployer.bootstrap(bootstrapOptions, (err, result) => { + expect(err).eql(errorMessage); + expect(result).eql(undefined); + done(); + }); + }); + }); + + describe("deploy", () => { + let deployOptions; + let expectedOutput; + let expectedErrorOutput; + + beforeEach(() => { + expectedOutput = { + isAllStepSuccess: true, + isCodeDeployed: true, + deployState: {stackId, outputs: [], s3: {bucket: bucketName, key: bucketKey}}, + endpoint: {uri: endpointUri}, + resultMessage: `The CloudFormation deploy succeeded for Alexa region "${alexaRegion}" with output Lambda ARN: ${endpointUri}.`, + }; + expectedErrorOutput = { + isAllStepSuccess: false, + isCodeDeployed: false, + deployState: {stackId, s3: {bucket: bucketName, key: bucketKey}}, + resultMessage: "Some error", + }; + deployOptions = { + profile, + doDebug: false, + alexaRegion, + skillId: "some skill id", + skillName: "cf-skill", + code: { + codeBuild: "/some-path/.ask/lambda/build.zip", + isCodeModified: true, + }, + userConfig: { + runtime, + handler, + templatePath, + awsRegion: "us-east-1", + artifactsS3: { + bucketName, + bucketKey, + }, + cfn: { + parameters: { + [userDefinedParamKey]: userDefinedParamValue, + }, + capabilities: ["CAPABILITY_IAM"], + }, + }, + deployState: { + default: { + stackId, + s3: { + bucket: bucketName, + key: bucketKey, + }, + }, + }, + deployRegions: { + default: "us-east-1", + }, + }; + getAWSProfileStub = sinon.stub(awsUtil, "getAWSProfile").returns("some profile"); + sinon.stub(Helper.prototype, "getSkillCredentials").resolves({clientId: "id", clientSecret: "secret"}); + sinon.stub(Helper.prototype, "createS3BucketIfNotExists").resolves(); + sinon.stub(Helper.prototype, "enableS3BucketVersioningIfNotEnabled").resolves(); + sinon.stub(Helper.prototype, "uploadToS3").resolves({VersionId: s3VersionId}); + deployStackStub = sinon.stub(Helper.prototype, "deployStack").resolves({StackId: stackId}); + waitForStackDeployStub = sinon.stub(Helper.prototype, "waitForStackDeploy"); + }); + + it("should deploy", (done) => { + waitForStackDeployStub.resolves({endpointUri, stackInfo: {Outputs: []}}); + + Deployer.invoke({}, deployOptions, (err, result) => { + expect(err).eql(null); + expect(result).eql(expectedOutput); + done(); + }); + }); + + it("should deploy with skill credentials", (done) => { + sinon.stub(fs, "readFileSync").withArgs(templatePath, "utf-8").returns("SkillClientId SkillClientSecret"); + waitForStackDeployStub.resolves({endpointUri, stackInfo: {Outputs: []}}); + + Deployer.invoke({}, deployOptions, (err, result) => { + expect(err).eql(null); + expect(result).eql(expectedOutput); + done(); + }); + }); + + it("should deploy without initial state", (done) => { + waitForStackDeployStub.resolves({endpointUri, stackInfo: {Outputs: []}}); + deployOptions.deployState = undefined; + + Deployer.invoke({}, deployOptions, (err, result) => { + expect(err).eql(null); + expect(result).eql(expectedOutput); + done(); + }); + }); + + it("should always deploy with CAPABILITY_IAM capabilities", (done) => { + waitForStackDeployStub.resolves({endpointUri, stackInfo: {Outputs: []}}); + deployOptions.userConfig.cfn.capabilities = undefined; + + Deployer.invoke({}, deployOptions, (err, result) => { + expect(err).eql(null); + expect(result).eql(expectedOutput); + expect(deployStackStub.args[0][4]).includes("CAPABILITY_IAM"); + done(); + }); + }); + + it("should deploy without user defined cf parameters", (done) => { + waitForStackDeployStub.resolves({endpointUri, stackInfo: {Outputs: []}}); + delete deployOptions.userConfig.cfn.parameters; - beforeEach(() => { - sinon.stub(fs, 'readFileSync'); - sinon.stub(fs, 'writeFileSync'); - getAWSProfileStub = sinon.stub(awsUtil, 'getAWSProfile'); - sinon.stub(awsUtil, 'getCLICompatibleDefaultRegion').returns(awsRegion); - }); - it('should bootstrap deployer', (done) => { - Deployer.bootstrap(bootstrapOptions, (err, result) => { - const expected = { userConfig: - { runtime, - handler, - templatePath: `./infrastructure/${bootstrapOptions.workspacePath}/skill-stack.yaml`, - awsRegion } }; - expect(err).eql(null); - expect(result).eql(expected); - done(); - }); - }); - - it('should catch bootstrap error', (done) => { - const errorMessage = 'some error'; - getAWSProfileStub.throws(new Error(errorMessage)); - - Deployer.bootstrap(bootstrapOptions, (err, result) => { - expect(err).eql(errorMessage); - expect(result).eql(undefined); - done(); - }); - }); + Deployer.invoke({}, deployOptions, (err, result) => { + expect(err).eql(null); + expect(result).eql(expectedOutput); + expect(deployStackStub.args[0][3]).to.not.include({ParameterKey: userDefinedParamKey, ParameterValue: userDefinedParamValue}); + done(); + }); }); - describe('deploy', () => { - let deployOptions; - let expectedOutput; - let expectedErrorOutput; - - beforeEach(() => { - expectedOutput = { - isAllStepSuccess: true, - isCodeDeployed: true, - deployState: - { stackId, - outputs: [], - s3: { bucket: bucketName, - key: bucketKey } }, - endpoint: { uri: endpointUri }, - resultMessage: `The CloudFormation deploy succeeded for Alexa region "${alexaRegion}" with output Lambda ARN: ${endpointUri}.` - }; - expectedErrorOutput = { - isAllStepSuccess: false, - isCodeDeployed: false, - deployState: - { stackId, - s3: { bucket: bucketName, - key: bucketKey } }, - resultMessage: 'Some error' - }; - deployOptions = { - profile, - doDebug: false, - alexaRegion, - skillId: 'some skill id', - skillName: 'cf-skill', - code: { - codeBuild: '/some-path/.ask/lambda/build.zip', - isCodeModified: true - }, - userConfig: { - runtime, - handler, - templatePath, - awsRegion: 'us-east-1', - artifactsS3: { - bucketName, - bucketKey - }, - cfn: { - parameters: { - [userDefinedParamKey]: userDefinedParamValue - }, - capabilities: [ - 'CAPABILITY_IAM' - ] - } - }, - deployState: { - default: { - stackId, - s3: { - bucket: bucketName, - key: bucketKey - } - } - }, - deployRegions: { - default: 'us-east-1' - } - }; - getAWSProfileStub = sinon.stub(awsUtil, 'getAWSProfile').returns('some profile'); - sinon.stub(Helper.prototype, 'getSkillCredentials').resolves({ clientId: 'id', clientSecret: 'secret' }); - sinon.stub(Helper.prototype, 'createS3BucketIfNotExists').resolves(); - sinon.stub(Helper.prototype, 'enableS3BucketVersioningIfNotEnabled').resolves(); - sinon.stub(Helper.prototype, 'uploadToS3').resolves({ VersionId: s3VersionId }); - deployStackStub = sinon.stub(Helper.prototype, 'deployStack').resolves({ StackId: stackId }); - waitForStackDeployStub = sinon.stub(Helper.prototype, 'waitForStackDeploy'); - }); - - it('should deploy', (done) => { - waitForStackDeployStub.resolves({ endpointUri, stackInfo: { Outputs: [] } }); - - Deployer.invoke({}, deployOptions, (err, result) => { - expect(err).eql(null); - expect(result).eql(expectedOutput); - done(); - }); - }); - - it('should deploy with skill credentials', (done) => { - sinon.stub(fs, 'readFileSync').withArgs(templatePath, 'utf-8').returns('SkillClientId SkillClientSecret'); - waitForStackDeployStub.resolves({ endpointUri, stackInfo: { Outputs: [] } }); - - Deployer.invoke({}, deployOptions, (err, result) => { - expect(err).eql(null); - expect(result).eql(expectedOutput); - done(); - }); - }); - - it('should deploy without initial state', (done) => { - waitForStackDeployStub.resolves({ endpointUri, stackInfo: { Outputs: [] } }); - deployOptions.deployState = undefined; - - Deployer.invoke({}, deployOptions, (err, result) => { - expect(err).eql(null); - expect(result).eql(expectedOutput); - done(); - }); - }); - - it('should always deploy with CAPABILITY_IAM capabilities', (done) => { - waitForStackDeployStub.resolves({ endpointUri, stackInfo: { Outputs: [] } }); - deployOptions.userConfig.cfn.capabilities = undefined; - - Deployer.invoke({}, deployOptions, (err, result) => { - expect(err).eql(null); - expect(result).eql(expectedOutput); - expect(deployStackStub.args[0][4]).includes('CAPABILITY_IAM'); - done(); - }); - }); - - it('should deploy without user defined cf parameters', (done) => { - waitForStackDeployStub.resolves({ endpointUri, stackInfo: { Outputs: [] } }); - delete deployOptions.userConfig.cfn.parameters; - - Deployer.invoke({}, deployOptions, (err, result) => { - expect(err).eql(null); - expect(result).eql(expectedOutput); - expect(deployStackStub.args[0][3]).to.not.include({ ParameterKey: userDefinedParamKey, ParameterValue: userDefinedParamValue }); - done(); - }); - }); - - it('should invoke deploy and catch deploy error', (done) => { - const errorMessage = 'some error'; - waitForStackDeployStub.rejects(new CliCFNDeployerError(errorMessage)); - - Deployer.invoke({}, deployOptions, (err, result) => { - expectedErrorOutput.isCodeDeployed = true; - expectedErrorOutput.resultMessage = `The CloudFormation deploy failed for Alexa region "${alexaRegion}": ${errorMessage}`; - expect(err).eql(null); - expect(result).eql(expectedErrorOutput); - done(); - }); - }); - - it('should skip deploy when region is not primary deploy region', (done) => { - const deployRegion = 'default'; - const skipRegion = 'NA'; - deployOptions.alexaRegion = skipRegion; - deployOptions.deployRegions[skipRegion] = deployOptions.deployRegions[deployRegion]; - deployOptions.deployState[skipRegion] = deployOptions.deployState[deployRegion]; - expectedOutput = { - ...expectedErrorOutput, - isDeploySkipped: true, - deployRegion, - resultMessage: `The CloudFormation deploy for Alexa region "${skipRegion}" is same as "${deployRegion}".` - }; - - Deployer.invoke({}, deployOptions, (err, result) => { - expect(err).eql(null); - expect(result).eql(expectedOutput); - done(); - }); - }); - - it('should not skip deploy when region is not primary deploy region but has different deploy state', (done) => { - const deployRegion = 'default'; - const currentRegion = 'NA'; - waitForStackDeployStub.resolves({ endpointUri, stackInfo: { Outputs: [] } }); - deployOptions.alexaRegion = currentRegion; - deployOptions.deployRegions[currentRegion] = deployOptions.deployRegions[deployRegion]; - deployOptions.deployState[currentRegion] = { ...deployOptions.deployState[deployRegion], stackId: 'different stack id' }; - expectedOutput.resultMessage = `The CloudFormation deploy succeeded for Alexa region "${currentRegion}" with output Lambda ARN: ${endpointUri}.`; - - Deployer.invoke({}, deployOptions, (err, result) => { - expect(err).eql(null); - expect(result).eql(expectedOutput); - done(); - }); - }); - - it('should throw error when reserved parameter is used', (done) => { - deployOptions.userConfig.cfn.parameters.SkillId = 'reserved parameter value'; - - Deployer.invoke({}, deployOptions, (err, result) => { - expectedErrorOutput.resultMessage = `The CloudFormation deploy failed for Alexa region "${alexaRegion}": ` - + 'Cloud Formation parameter "SkillId" is reserved. Please use a different name.'; - expect(err).eql(null); - expect(result).eql(expectedErrorOutput); - done(); - }); - }); - - it('should throw error when no template path is provided', (done) => { - delete deployOptions.userConfig.templatePath; - - Deployer.invoke({}, deployOptions, (err, result) => { - expectedErrorOutput.resultMessage = `The CloudFormation deploy failed for Alexa region "${alexaRegion}": ` - + 'The template path in userConfig must be provided.'; - expect(err).eql(null); - expect(result).eql(expectedErrorOutput); - done(); - }); - }); - - it('should generate s3 bucket name if not provided or not in state', (done) => { - delete deployOptions.userConfig.artifactsS3; - delete deployOptions.deployState.default.s3; - - Deployer.invoke({}, deployOptions, (err, result) => { - expect(err).eql(null); - expect(result.deployState.s3.bucket).contains('ask-'); - done(); - }); - }); - - it('should throw error when aws profile is not linked to the ask cli', (done) => { - getAWSProfileStub.returns(undefined); - - Deployer.invoke({}, deployOptions, (err, result) => { - expectedErrorOutput.resultMessage = `The CloudFormation deploy failed for Alexa region "${alexaRegion}": ` - + `Profile [${profile}] doesn't have AWS profile linked to it. Please run "ask configure" to re-configure your profile.`; - expect(err).eql(null); - expect(result).eql(expectedErrorOutput); - done(); - }); - }); - - it('should throw error when unsupported alexa region is used', (done) => { - const unsupportedRegion = 'non existing region'; - deployOptions.alexaRegion = unsupportedRegion; - - Deployer.invoke({}, deployOptions, (err, result) => { - expectedErrorOutput.deployState = {}; - expectedErrorOutput.resultMessage = `The CloudFormation deploy failed for Alexa region "${unsupportedRegion}": ` - + `Unsupported Alexa region: ${unsupportedRegion}. Please check your region name or ` - + 'use "regionalOverrides" to specify AWS region.'; - expect(err).eql(null); - expect(result).eql(expectedErrorOutput); - done(); - }); - }); + it("should invoke deploy and catch deploy error", (done) => { + const errorMessage = "some error"; + waitForStackDeployStub.rejects(new CliCFNDeployerError(errorMessage)); + + Deployer.invoke({}, deployOptions, (err, result) => { + expectedErrorOutput.isCodeDeployed = true; + expectedErrorOutput.resultMessage = `The CloudFormation deploy failed for Alexa region "${alexaRegion}": ${errorMessage}`; + expect(err).eql(null); + expect(result).eql(expectedErrorOutput); + done(); + }); }); - afterEach(() => { - sinon.restore(); + it("should skip deploy when region is not primary deploy region", (done) => { + const deployRegion = "default"; + const skipRegion = "NA"; + deployOptions.alexaRegion = skipRegion; + deployOptions.deployRegions[skipRegion] = deployOptions.deployRegions[deployRegion]; + deployOptions.deployState[skipRegion] = deployOptions.deployState[deployRegion]; + expectedOutput = { + ...expectedErrorOutput, + isDeploySkipped: true, + deployRegion, + resultMessage: `The CloudFormation deploy for Alexa region "${skipRegion}" is same as "${deployRegion}".`, + }; + + Deployer.invoke({}, deployOptions, (err, result) => { + expect(err).eql(null); + expect(result).eql(expectedOutput); + done(); + }); + }); + + it("should not skip deploy when region is not primary deploy region but has different deploy state", (done) => { + const deployRegion = "default"; + const currentRegion = "NA"; + waitForStackDeployStub.resolves({endpointUri, stackInfo: {Outputs: []}}); + deployOptions.alexaRegion = currentRegion; + deployOptions.deployRegions[currentRegion] = deployOptions.deployRegions[deployRegion]; + deployOptions.deployState[currentRegion] = {...deployOptions.deployState[deployRegion], stackId: "different stack id"}; + expectedOutput.resultMessage = `The CloudFormation deploy succeeded for Alexa region "${currentRegion}" with output Lambda ARN: ${endpointUri}.`; + + Deployer.invoke({}, deployOptions, (err, result) => { + expect(err).eql(null); + expect(result).eql(expectedOutput); + done(); + }); + }); + + it("should throw error when reserved parameter is used", (done) => { + deployOptions.userConfig.cfn.parameters.SkillId = "reserved parameter value"; + + Deployer.invoke({}, deployOptions, (err, result) => { + expectedErrorOutput.resultMessage = + `The CloudFormation deploy failed for Alexa region "${alexaRegion}": ` + + 'Cloud Formation parameter "SkillId" is reserved. Please use a different name.'; + expect(err).eql(null); + expect(result).eql(expectedErrorOutput); + done(); + }); + }); + + it("should throw error when no template path is provided", (done) => { + delete deployOptions.userConfig.templatePath; + + Deployer.invoke({}, deployOptions, (err, result) => { + expectedErrorOutput.resultMessage = + `The CloudFormation deploy failed for Alexa region "${alexaRegion}": ` + "The template path in userConfig must be provided."; + expect(err).eql(null); + expect(result).eql(expectedErrorOutput); + done(); + }); }); + + it("should generate s3 bucket name if not provided or not in state", (done) => { + delete deployOptions.userConfig.artifactsS3; + delete deployOptions.deployState.default.s3; + + Deployer.invoke({}, deployOptions, (err, result) => { + expect(err).eql(null); + expect(result.deployState.s3.bucket).contains("ask-"); + done(); + }); + }); + + it("should throw error when aws profile is not linked to the ask cli", (done) => { + getAWSProfileStub.returns(undefined); + + Deployer.invoke({}, deployOptions, (err, result) => { + expectedErrorOutput.resultMessage = + `The CloudFormation deploy failed for Alexa region "${alexaRegion}": ` + + `Profile [${profile}] doesn't have AWS profile linked to it. Please run "ask configure" to re-configure your profile.`; + expect(err).eql(null); + expect(result).eql(expectedErrorOutput); + done(); + }); + }); + + it("should throw error when unsupported alexa region is used", (done) => { + const unsupportedRegion = "non existing region"; + deployOptions.alexaRegion = unsupportedRegion; + + Deployer.invoke({}, deployOptions, (err, result) => { + expectedErrorOutput.deployState = {}; + expectedErrorOutput.resultMessage = + `The CloudFormation deploy failed for Alexa region "${unsupportedRegion}": ` + + `Unsupported Alexa region: ${unsupportedRegion}. Please check your region name or ` + + 'use "regionalOverrides" to specify AWS region.'; + expect(err).eql(null); + expect(result).eql(expectedErrorOutput); + done(); + }); + }); + }); + + afterEach(() => { + sinon.restore(); + }); }); diff --git a/test/unit/builtins/lambda-deployer/helper-test.js b/test/unit/builtins/lambda-deployer/helper-test.js index 9086ca6a..ad82dc9f 100644 --- a/test/unit/builtins/lambda-deployer/helper-test.js +++ b/test/unit/builtins/lambda-deployer/helper-test.js @@ -1,612 +1,635 @@ -const aws = require('aws-sdk'); -const { expect } = require('chai'); -const fs = require('fs'); -const path = require('path'); -const sinon = require('sinon'); - -const helper = require('@src/builtins/deploy-delegates/lambda-deployer/helper'); -const IAMClient = require('@src/clients/aws-client/iam-client'); -const LambdaClient = require('@src/clients/aws-client/lambda-client'); -const Manifest = require('@src/model/manifest'); -const ResourcesConfig = require('@src/model/resources-config'); - -describe('Builtins test - lambda-deployer helper.js test', () => { - const FIXTURE_MANIFEST_FILE_PATH = path.join(process.cwd(), 'test', 'unit', 'fixture', 'model', 'manifest.json'); - const TEST_PROFILE = 'default'; // test file uses 'default' profile - const TEST_IGNORE_HASH = false; - const TEST_AWS_PROFILE = 'default'; - const TEST_AWS_REGION = 'us-east-1'; - const TEST_ALEXA_REGION = 'default'; - const TEST_ALEXA_REGION_NON_DEFAULT = 'EU'; - const TEST_SKILL_NAME = 'skill_name'; - const TEST_SKILL_ID = 'skill_id'; - const TEST_IAM_ROLE_ARN = 'iam_role_arn'; - const TEST_LAMBDA_ARN = 'iam_lambda_arn'; - const TEST_NO_SUCH_ENTITY_ERROR = { - code: 'NoSuchEntity' +const aws = require("aws-sdk"); +const {expect} = require("chai"); +const fs = require("fs"); +const path = require("path"); +const sinon = require("sinon"); + +const helper = require("../../../../lib/builtins/deploy-delegates/lambda-deployer/helper"); +const IAMClient = require("../../../../lib/clients/aws-client/iam-client"); +const LambdaClient = require("../../../../lib/clients/aws-client/lambda-client"); +const Manifest = require("../../../../lib/model/manifest"); +const ResourcesConfig = require("../../../../lib/model/resources-config"); + +describe("Builtins test - lambda-deployer helper.js test", () => { + const FIXTURE_MANIFEST_FILE_PATH = path.join(process.cwd(), "test", "unit", "fixture", "model", "manifest.json"); + const TEST_PROFILE = "default"; // test file uses 'default' profile + const TEST_IGNORE_HASH = false; + const TEST_AWS_PROFILE = "default"; + const TEST_AWS_REGION = "us-east-1"; + const TEST_ALEXA_REGION = "default"; + const TEST_ALEXA_REGION_NON_DEFAULT = "EU"; + const TEST_SKILL_NAME = "skill_name"; + const TEST_SKILL_ID = "skill_id"; + const TEST_IAM_ROLE_ARN = "iam_role_arn"; + const TEST_LAMBDA_ARN = "iam_lambda_arn"; + const TEST_NO_SUCH_ENTITY_ERROR = { + code: "NoSuchEntity", + }; + const REPORTER = { + updateStatus: () => {}, + }; + const TEST_ROLE_DATA = { + Role: { + Arn: TEST_IAM_ROLE_ARN, + }, + }; + + describe("# test class method: loadLambdaInformation", () => { + const TEST_LOCAL_IAM_ROLE = "local_iam_role"; + const TEST_LOCAL_REVISION_ID = "local_revision_id"; + const TEST_LOCAL_DEPLOY_STATE = { + iamRole: TEST_LOCAL_IAM_ROLE, + lambda: { + arn: TEST_LAMBDA_ARN, + revisionId: TEST_LOCAL_REVISION_ID, + }, }; - const REPORTER = { - updateStatus: () => {} + const TEST_USER_CONFIG_WITH_SOURCELAMBDA = { + regionalOverrides: { + [TEST_ALEXA_REGION_NON_DEFAULT]: { + sourceLambda: { + arn: TEST_LAMBDA_ARN, + }, + }, + }, }; - const TEST_ROLE_DATA = { - Role: { - Arn: TEST_IAM_ROLE_ARN - } + const TEST_REMOTE_IAM_ROLE = "remote_iam_role"; + const TEST_REMOTE_REVISION_ID = "remote_revision_id"; + const TEST_LOAD_LAMBDA_OPTION_NO_LAMBDA_STATE = { + awsProfile: TEST_AWS_PROFILE, + awsRegion: TEST_AWS_REGION, + alexaRegion: TEST_ALEXA_REGION, + ignoreHash: TEST_IGNORE_HASH, + deployState: {}, + userConfig: {}, }; - describe('# test class method: loadLambdaInformation', () => { - const TEST_LOCAL_IAM_ROLE = 'local_iam_role'; - const TEST_LOCAL_REVISION_ID = 'local_revision_id'; - const TEST_LOCAL_DEPLOY_STATE = { - iamRole: TEST_LOCAL_IAM_ROLE, - lambda: { - arn: TEST_LAMBDA_ARN, - revisionId: TEST_LOCAL_REVISION_ID - } - }; - const TEST_USER_CONFIG_WITH_SOURCELAMBDA = { - regionalOverrides: { - [TEST_ALEXA_REGION_NON_DEFAULT]: { - sourceLambda: { - arn: TEST_LAMBDA_ARN - } - } - } - }; - const TEST_REMOTE_IAM_ROLE = 'remote_iam_role'; - const TEST_REMOTE_REVISION_ID = 'remote_revision_id'; - const TEST_LOAD_LAMBDA_OPTION_NO_LAMBDA_STATE = { - awsProfile: TEST_AWS_PROFILE, - awsRegion: TEST_AWS_REGION, - alexaRegion: TEST_ALEXA_REGION, - ignoreHash: TEST_IGNORE_HASH, - deployState: {}, - userConfig: {} - }; - - const TEST_LOAD_LAMBDA_OPTION_WITH_LAMBDA_STATE = { - awsProfile: TEST_AWS_PROFILE, - awsRegion: TEST_AWS_REGION, - alexaRegion: TEST_ALEXA_REGION, - ignoreHash: TEST_IGNORE_HASH, - deployState: TEST_LOCAL_DEPLOY_STATE, - userConfig: {} - }; + const TEST_LOAD_LAMBDA_OPTION_WITH_LAMBDA_STATE = { + awsProfile: TEST_AWS_PROFILE, + awsRegion: TEST_AWS_REGION, + alexaRegion: TEST_ALEXA_REGION, + ignoreHash: TEST_IGNORE_HASH, + deployState: TEST_LOCAL_DEPLOY_STATE, + userConfig: {}, + }; - const TEST_LOAD_LAMBDA_OPTION_WITH_LAMBDA_STATE_IGNORE_HASH = { - awsProfile: TEST_AWS_PROFILE, - awsRegion: TEST_AWS_REGION, - alexaRegion: TEST_ALEXA_REGION, - ignoreHash: true, - deployState: TEST_LOCAL_DEPLOY_STATE, - userConfig: {} - }; + const TEST_LOAD_LAMBDA_OPTION_WITH_LAMBDA_STATE_IGNORE_HASH = { + awsProfile: TEST_AWS_PROFILE, + awsRegion: TEST_AWS_REGION, + alexaRegion: TEST_ALEXA_REGION, + ignoreHash: true, + deployState: TEST_LOCAL_DEPLOY_STATE, + userConfig: {}, + }; - const TEST_LOAD_LAMBDA_OPTION_WITH_SOURCELAMBDA = { - awsProfile: TEST_AWS_PROFILE, - awsRegion: TEST_AWS_REGION, - alexaRegion: TEST_ALEXA_REGION_NON_DEFAULT, - ignoreHash: true, - deployState: TEST_LOCAL_DEPLOY_STATE, - userConfig: TEST_USER_CONFIG_WITH_SOURCELAMBDA - }; + const TEST_LOAD_LAMBDA_OPTION_WITH_SOURCELAMBDA = { + awsProfile: TEST_AWS_PROFILE, + awsRegion: TEST_AWS_REGION, + alexaRegion: TEST_ALEXA_REGION_NON_DEFAULT, + ignoreHash: true, + deployState: TEST_LOCAL_DEPLOY_STATE, + userConfig: TEST_USER_CONFIG_WITH_SOURCELAMBDA, + }; - afterEach(() => { - sinon.restore(); - }); + afterEach(() => { + sinon.restore(); + }); - it('| no lambda arn found, expect original deploystate return', (done) => { - // call - helper.loadLambdaInformation(REPORTER, TEST_LOAD_LAMBDA_OPTION_NO_LAMBDA_STATE, (err, data) => { - // verify - expect(data).deep.equal({}); - done(); - }); - }); + it("| no lambda arn found, expect original deploystate return", (done) => { + // call + helper.loadLambdaInformation(REPORTER, TEST_LOAD_LAMBDA_OPTION_NO_LAMBDA_STATE, (err, data) => { + // verify + expect(data).deep.equal({}); + done(); + }); + }); - it('| an existing lambda arn found in deployState, getFunction request fails, expect an error return', (done) => { - // setup - const TEST_GET_FUNCTION_ERROR = 'get_function_error'; - sinon.stub(LambdaClient.prototype, 'getFunction').callsArgWith(1, TEST_GET_FUNCTION_ERROR); - // call - helper.loadLambdaInformation(REPORTER, TEST_LOAD_LAMBDA_OPTION_WITH_LAMBDA_STATE, (err) => { - // verify - expect(err).equal(TEST_GET_FUNCTION_ERROR); - done(); - }); - }); + it("| an existing lambda arn found in deployState, getFunction request fails, expect an error return", (done) => { + // setup + const TEST_GET_FUNCTION_ERROR = "get_function_error"; + sinon.stub(LambdaClient.prototype, "getFunction").callsArgWith(1, TEST_GET_FUNCTION_ERROR); + // call + helper.loadLambdaInformation(REPORTER, TEST_LOAD_LAMBDA_OPTION_WITH_LAMBDA_STATE, (err) => { + // verify + expect(err).equal(TEST_GET_FUNCTION_ERROR); + done(); + }); + }); - it('| an existing lambda arn found in deployState, getFunction request passes, the local iam role does not equal with the remote iam role, ' - + 'expect an error return', (done) => { - // setup - const TEST_REMOTE_DEPLOY_STATE = { - Configuration: { - Role: TEST_REMOTE_IAM_ROLE, - RevisionId: TEST_REMOTE_REVISION_ID - } - }; - const TEST_IAM_ROLE_ERROR = `The IAM role for Lambda ARN (${TEST_LAMBDA_ARN}) should be "${TEST_REMOTE_IAM_ROLE}", \ + it( + "| an existing lambda arn found in deployState, getFunction request passes, the local iam role does not equal with the remote iam role, " + + "expect an error return", + (done) => { + // setup + const TEST_REMOTE_DEPLOY_STATE = { + Configuration: { + Role: TEST_REMOTE_IAM_ROLE, + RevisionId: TEST_REMOTE_REVISION_ID, + }, + }; + const TEST_IAM_ROLE_ERROR = `The IAM role for Lambda ARN (${TEST_LAMBDA_ARN}) should be "${TEST_REMOTE_IAM_ROLE}", \ but found "${TEST_LOCAL_IAM_ROLE}". Please solve this IAM role mismatch and re-deploy again. To ignore this error run "ask deploy --ignore-hash".`; - sinon.stub(LambdaClient.prototype, 'getFunction').callsArgWith(1, null, TEST_REMOTE_DEPLOY_STATE); - // call - helper.loadLambdaInformation(REPORTER, TEST_LOAD_LAMBDA_OPTION_WITH_LAMBDA_STATE, (err) => { - // verify - expect(err).equal(TEST_IAM_ROLE_ERROR); - done(); - }); + sinon.stub(LambdaClient.prototype, "getFunction").callsArgWith(1, null, TEST_REMOTE_DEPLOY_STATE); + // call + helper.loadLambdaInformation(REPORTER, TEST_LOAD_LAMBDA_OPTION_WITH_LAMBDA_STATE, (err) => { + // verify + expect(err).equal(TEST_IAM_ROLE_ERROR); + done(); }); - - it('| an existing lambda arn found in deployState, getFunction request passes, the local revisionId does not equal with the remote revisionId,' - + 'expect an error return', (done) => { - // setup - const TEST_REMOTE_DEPLOY_STATE = { - Configuration: { - Role: TEST_LOCAL_IAM_ROLE, - RevisionId: TEST_REMOTE_REVISION_ID - } - }; - const TEST_REVISION_ID_ERROR = `The current revisionId (The revision ID for Lambda ARN (${TEST_LAMBDA_ARN}) should be \ + }, + ); + + it( + "| an existing lambda arn found in deployState, getFunction request passes, the local revisionId does not equal with the remote revisionId," + + "expect an error return", + (done) => { + // setup + const TEST_REMOTE_DEPLOY_STATE = { + Configuration: { + Role: TEST_LOCAL_IAM_ROLE, + RevisionId: TEST_REMOTE_REVISION_ID, + }, + }; + const TEST_REVISION_ID_ERROR = `The current revisionId (The revision ID for Lambda ARN (${TEST_LAMBDA_ARN}) should be \ ${TEST_REMOTE_REVISION_ID}, but found ${TEST_LOCAL_REVISION_ID}. \ Please solve this revision mismatch and re-deploy again. To ignore this error run "ask deploy --ignore-hash".`; - sinon.stub(LambdaClient.prototype, 'getFunction').callsArgWith(1, null, TEST_REMOTE_DEPLOY_STATE); - // call - helper.loadLambdaInformation(REPORTER, TEST_LOAD_LAMBDA_OPTION_WITH_LAMBDA_STATE, (err) => { - // verify - expect(err).equal(TEST_REVISION_ID_ERROR); - done(); - }); - }); - - it('| an existing lambda arn found in deployState, getFunction request passes, the local revisionId and remote revisionId compare is ignored' - + 'expect lambda data returned', (done) => { - // setup - const TEST_REMOTE_DEPLOY_STATE = { - Configuration: { - Role: TEST_LOCAL_IAM_ROLE, - RevisionId: TEST_REMOTE_REVISION_ID - } - }; - sinon.stub(LambdaClient.prototype, 'getFunction').callsArgWith(1, null, TEST_REMOTE_DEPLOY_STATE); - // call - helper.loadLambdaInformation(REPORTER, TEST_LOAD_LAMBDA_OPTION_WITH_LAMBDA_STATE_IGNORE_HASH, (err, data) => { - // verify - expect(data.iamRole).equal(TEST_LOCAL_IAM_ROLE); - done(); - }); - }); - - it('| an existing lambda arn found in deployState, getFunction request passes, expect lambda data returned', (done) => { - // setup - const TEST_REMOTE_DEPLOY_STATE = { - Configuration: { - Role: TEST_LOCAL_IAM_ROLE, - RevisionId: TEST_LOCAL_REVISION_ID - } - }; - sinon.stub(LambdaClient.prototype, 'getFunction').callsArgWith(1, null, TEST_REMOTE_DEPLOY_STATE); - // call - helper.loadLambdaInformation(REPORTER, TEST_LOAD_LAMBDA_OPTION_WITH_LAMBDA_STATE, (err, data) => { - // verify - expect(data.iamRole).equal(TEST_LOCAL_IAM_ROLE); - expect(data.lambda.revisionId).equal(TEST_LOCAL_REVISION_ID); - done(); - }); + sinon.stub(LambdaClient.prototype, "getFunction").callsArgWith(1, null, TEST_REMOTE_DEPLOY_STATE); + // call + helper.loadLambdaInformation(REPORTER, TEST_LOAD_LAMBDA_OPTION_WITH_LAMBDA_STATE, (err) => { + // verify + expect(err).equal(TEST_REVISION_ID_ERROR); + done(); }); - - it('| using Lambda arn from sourceLambda, getFunction return error, expect error called back', (done) => { - // setup - const GET_FUNC_ERR = 'get func err'; - sinon.stub(LambdaClient.prototype, 'getFunction').callsArgWith(1, GET_FUNC_ERR); - // call - helper.loadLambdaInformation(REPORTER, TEST_LOAD_LAMBDA_OPTION_WITH_SOURCELAMBDA, (err, data) => { - // verify - expect(err).equal(`Failed to load the Lambda (${TEST_LAMBDA_ARN}) specified in "sourceLambda". ${GET_FUNC_ERR}`); - expect(data).equal(undefined); - done(); - }); - }); - - it('| using Lambda arn from sourceLambda, getFunction request passes, expect lambda data returned', (done) => { - // setup - const TEST_REMOTE_DEPLOY_STATE = { - Configuration: { - Role: TEST_REMOTE_IAM_ROLE, - RevisionId: TEST_REMOTE_REVISION_ID - } - }; - sinon.stub(LambdaClient.prototype, 'getFunction').callsArgWith(1, null, TEST_REMOTE_DEPLOY_STATE); - // call - helper.loadLambdaInformation(REPORTER, TEST_LOAD_LAMBDA_OPTION_WITH_SOURCELAMBDA, (err, data) => { - // verify - expect(data.iamRole).equal(TEST_REMOTE_IAM_ROLE); - expect(data.lambda.revisionId).equal(TEST_REMOTE_REVISION_ID); - expect(data.lambda.arn).equal(TEST_LAMBDA_ARN); - done(); - }); + }, + ); + + it( + "| an existing lambda arn found in deployState, getFunction request passes, the local revisionId and remote revisionId compare is ignored" + + "expect lambda data returned", + (done) => { + // setup + const TEST_REMOTE_DEPLOY_STATE = { + Configuration: { + Role: TEST_LOCAL_IAM_ROLE, + RevisionId: TEST_REMOTE_REVISION_ID, + }, + }; + sinon.stub(LambdaClient.prototype, "getFunction").callsArgWith(1, null, TEST_REMOTE_DEPLOY_STATE); + // call + helper.loadLambdaInformation(REPORTER, TEST_LOAD_LAMBDA_OPTION_WITH_LAMBDA_STATE_IGNORE_HASH, (err, data) => { + // verify + expect(data.iamRole).equal(TEST_LOCAL_IAM_ROLE); + done(); }); + }, + ); + + it("| an existing lambda arn found in deployState, getFunction request passes, expect lambda data returned", (done) => { + // setup + const TEST_REMOTE_DEPLOY_STATE = { + Configuration: { + Role: TEST_LOCAL_IAM_ROLE, + RevisionId: TEST_LOCAL_REVISION_ID, + }, + }; + sinon.stub(LambdaClient.prototype, "getFunction").callsArgWith(1, null, TEST_REMOTE_DEPLOY_STATE); + // call + helper.loadLambdaInformation(REPORTER, TEST_LOAD_LAMBDA_OPTION_WITH_LAMBDA_STATE, (err, data) => { + // verify + expect(data.iamRole).equal(TEST_LOCAL_IAM_ROLE); + expect(data.lambda.revisionId).equal(TEST_LOCAL_REVISION_ID); + done(); + }); }); - describe('# test class method: deployIAMRole', () => { - const TEST_DEPLOYSTATE_NO_ROLE = {}; - const TEST_DEPLOYSTATE = { - iamRole: TEST_IAM_ROLE_ARN - }; - const TEST_IAM_CONFIG_NO_ROLE = { - awsProfile: TEST_AWS_PROFILE, - alexaRegion: TEST_ALEXA_REGION, - skillName: TEST_SKILL_NAME, - awsRegion: TEST_AWS_REGION, - deployState: {} - }; - const TEST_IAM_CONFIG = { - awsProfile: TEST_AWS_PROFILE, - alexaRegion: TEST_ALEXA_REGION, - skillName: TEST_SKILL_NAME, - awsRegion: TEST_AWS_REGION, - deployState: TEST_DEPLOYSTATE - }; + it("| using Lambda arn from sourceLambda, getFunction return error, expect error called back", (done) => { + // setup + const GET_FUNC_ERR = "get func err"; + sinon.stub(LambdaClient.prototype, "getFunction").callsArgWith(1, GET_FUNC_ERR); + // call + helper.loadLambdaInformation(REPORTER, TEST_LOAD_LAMBDA_OPTION_WITH_SOURCELAMBDA, (err, data) => { + // verify + expect(err).equal(`Failed to load the Lambda (${TEST_LAMBDA_ARN}) specified in "sourceLambda". ${GET_FUNC_ERR}`); + expect(data).equal(undefined); + done(); + }); + }); - afterEach(() => { - sinon.restore(); - }); + it("| using Lambda arn from sourceLambda, getFunction request passes, expect lambda data returned", (done) => { + // setup + const TEST_REMOTE_DEPLOY_STATE = { + Configuration: { + Role: TEST_REMOTE_IAM_ROLE, + RevisionId: TEST_REMOTE_REVISION_ID, + }, + }; + sinon.stub(LambdaClient.prototype, "getFunction").callsArgWith(1, null, TEST_REMOTE_DEPLOY_STATE); + // call + helper.loadLambdaInformation(REPORTER, TEST_LOAD_LAMBDA_OPTION_WITH_SOURCELAMBDA, (err, data) => { + // verify + expect(data.iamRole).equal(TEST_REMOTE_IAM_ROLE); + expect(data.lambda.revisionId).equal(TEST_REMOTE_REVISION_ID); + expect(data.lambda.arn).equal(TEST_LAMBDA_ARN); + done(); + }); + }); + }); - it('| an existing IAM role found, get IAM Role fails, expect an error return', (done) => { - // setup - const TEST_ERROR = 'getRole error message'; - sinon.stub(IAMClient.prototype, 'getIAMRole').callsArgWith(1, TEST_ERROR); - // call - helper.deployIAMRole(REPORTER, TEST_IAM_CONFIG, (err) => { - // verify - expect(err).equal(`Failed to retrieve IAM role (${TEST_IAM_ROLE_ARN}) for Lambda. ${TEST_ERROR}`); - done(); - }); - }); + describe("# test class method: deployIAMRole", () => { + const TEST_DEPLOYSTATE_NO_ROLE = {}; + const TEST_DEPLOYSTATE = { + iamRole: TEST_IAM_ROLE_ARN, + }; + const TEST_IAM_CONFIG_NO_ROLE = { + awsProfile: TEST_AWS_PROFILE, + alexaRegion: TEST_ALEXA_REGION, + skillName: TEST_SKILL_NAME, + awsRegion: TEST_AWS_REGION, + deployState: {}, + }; + const TEST_IAM_CONFIG = { + awsProfile: TEST_AWS_PROFILE, + alexaRegion: TEST_ALEXA_REGION, + skillName: TEST_SKILL_NAME, + awsRegion: TEST_AWS_REGION, + deployState: TEST_DEPLOYSTATE, + }; - it('| an existing IAM role found, get IAM Role throw "NoSuchEntity" error, expect an error return', (done) => { - // setup - const TEST_GET_ROLE_ERROR = `The IAM role is not found. Please check if your IAM role from region ${TEST_ALEXA_REGION} is valid.`; - sinon.stub(IAMClient.prototype, 'getIAMRole').callsArgWith(1, TEST_NO_SUCH_ENTITY_ERROR); - // call - helper.deployIAMRole(REPORTER, TEST_IAM_CONFIG, (err) => { - // verify - expect(err).equal(TEST_GET_ROLE_ERROR); - done(); - }); - }); + afterEach(() => { + sinon.restore(); + }); - it('| an existing IAM role found, get IAM Role passes, expect correct data return', (done) => { - // setup - sinon.stub(IAMClient.prototype, 'getIAMRole').callsArgWith(1, null, TEST_ROLE_DATA); - // call - helper.deployIAMRole(REPORTER, TEST_IAM_CONFIG, (err, res) => { - // verify - expect(res).equal(TEST_IAM_ROLE_ARN); - done(); - }); - }); + it("| an existing IAM role found, get IAM Role fails, expect an error return", (done) => { + // setup + const TEST_ERROR = "getRole error message"; + sinon.stub(IAMClient.prototype, "getIAMRole").callsArgWith(1, TEST_ERROR); + // call + helper.deployIAMRole(REPORTER, TEST_IAM_CONFIG, (err) => { + // verify + expect(err).equal(`Failed to retrieve IAM role (${TEST_IAM_ROLE_ARN}) for Lambda. ${TEST_ERROR}`); + done(); + }); + }); - it('| no IAM role found, create IAM role fails, expect an error return', (done) => { - // setup - const TEST_CREATE_ROLE_ERROR = 'createIAMRole error message'; - sinon.stub(IAMClient.prototype, 'createBasicLambdaRole').callsArgWith(1, TEST_CREATE_ROLE_ERROR); - // call - helper.deployIAMRole(REPORTER, TEST_IAM_CONFIG_NO_ROLE, (err) => { - // verify - expect(err).equal(`Failed to create IAM role before deploying Lambda. ${TEST_CREATE_ROLE_ERROR}`); - done(); - }); - }); + it('| an existing IAM role found, get IAM Role throw "NoSuchEntity" error, expect an error return', (done) => { + // setup + const TEST_GET_ROLE_ERROR = `The IAM role is not found. Please check if your IAM role from region ${TEST_ALEXA_REGION} is valid.`; + sinon.stub(IAMClient.prototype, "getIAMRole").callsArgWith(1, TEST_NO_SUCH_ENTITY_ERROR); + // call + helper.deployIAMRole(REPORTER, TEST_IAM_CONFIG, (err) => { + // verify + expect(err).equal(TEST_GET_ROLE_ERROR); + done(); + }); + }); - it('| no IAM role found, create IAM role passes, attach role policy fails, expect an error return', (done) => { - // setup - const TEST_POLICY_ERROR = 'attachRolePolicy error message'; - sinon.stub(IAMClient.prototype, 'createBasicLambdaRole').callsArgWith(1, null, TEST_ROLE_DATA); - sinon.stub(IAMClient.prototype, 'attachBasicLambdaRolePolicy').callsArgWith(1, TEST_POLICY_ERROR); - // call - helper.deployIAMRole(REPORTER, TEST_IAM_CONFIG_NO_ROLE, (err) => { - // verify - expect(err).equal(`Failed to create IAM role before deploying Lambda. ${TEST_POLICY_ERROR}`); - done(); - }); - }); + it("| an existing IAM role found, get IAM Role passes, expect correct data return", (done) => { + // setup + sinon.stub(IAMClient.prototype, "getIAMRole").callsArgWith(1, null, TEST_ROLE_DATA); + // call + helper.deployIAMRole(REPORTER, TEST_IAM_CONFIG, (err, res) => { + // verify + expect(res).equal(TEST_IAM_ROLE_ARN); + done(); + }); + }); - it('| no IAM role found, create IAM role and attach role policy passes, expect a IAM role arn return.', (done) => { - // setup - sinon.stub(IAMClient.prototype, 'createBasicLambdaRole').callsArgWith(1, null, TEST_ROLE_DATA); - sinon.stub(IAMClient.prototype, 'attachBasicLambdaRolePolicy').callsArgWith(1, null, TEST_IAM_ROLE_ARN); - // call - helper.deployIAMRole(REPORTER, TEST_IAM_CONFIG_NO_ROLE, (err, res) => { - // verify - expect(res).equal(TEST_IAM_ROLE_ARN); - done(); - }); - }); + it("| no IAM role found, create IAM role fails, expect an error return", (done) => { + // setup + const TEST_CREATE_ROLE_ERROR = "createIAMRole error message"; + sinon.stub(IAMClient.prototype, "createBasicLambdaRole").callsArgWith(1, TEST_CREATE_ROLE_ERROR); + // call + helper.deployIAMRole(REPORTER, TEST_IAM_CONFIG_NO_ROLE, (err) => { + // verify + expect(err).equal(`Failed to create IAM role before deploying Lambda. ${TEST_CREATE_ROLE_ERROR}`); + done(); + }); }); - describe('# test class method: deployLambdaFunction', () => { - const TEST_ZIP_FILE_PATH = 'zip_file_path'; - const TEST_ZIP_FILE = 'zip_file'; - const TEST_CODE_BUILD = 'code_build_path'; - const TEST_LAST_MODIFIED = 'last_modified_time'; - const TEST_REVISION_ID = 'revision_id'; - const TEST_UPDATED_REVISION_ID = 'revision id'; - const TEST_FUNCTION_ARN = 'lambda function arn'; - const TEST_FUNCTION_STATE = 'Active'; - const TEST_LAST_UPDATE_STATUS = 'Successful'; - const TEST_RUNTIME = 'runtime'; - const TEST_HANDLER = 'handler'; - const TEST_CREATE_OPTIONS = { - profile: TEST_PROFILE, - awsProfile: TEST_PROFILE, - alexaRegion: TEST_ALEXA_REGION, - awsRegion: TEST_AWS_REGION, - skillId: TEST_SKILL_ID, - skillName: TEST_SKILL_NAME, - code: { codeBuild: TEST_CODE_BUILD }, - iamRoleArn: TEST_IAM_ROLE_ARN, - zipFilePath: TEST_ZIP_FILE_PATH, - userConfig: { awsRegion: TEST_AWS_REGION }, - deployState: {} - }; - const TEST_UPDATE_OPTIONS = { - profile: TEST_PROFILE, - awsProfile: TEST_PROFILE, - alexaRegion: TEST_ALEXA_REGION, - awsRegion: TEST_AWS_REGION, - skillId: TEST_SKILL_ID, - skillName: TEST_SKILL_NAME, - code: { codeBuild: TEST_CODE_BUILD }, - iamRoleArn: TEST_IAM_ROLE_ARN, - zipFilePath: TEST_ZIP_FILE_PATH, - userConfig: { awsRegion: TEST_AWS_REGION, runtime: TEST_RUNTIME, handler: TEST_HANDLER }, - deployState: { lambda: { - arn: TEST_FUNCTION_ARN, - lastModified: TEST_LAST_MODIFIED, - revisionId: TEST_REVISION_ID - } } - }; - const TEST_CREATE_DATA = { - FunctionArn: TEST_FUNCTION_ARN - }; - const TEST_GET_DATA = { - Configuration: { - FunctionArn: TEST_FUNCTION_ARN, - LastModified: TEST_LAST_MODIFIED, - RevisionId: TEST_UPDATED_REVISION_ID, - State: TEST_FUNCTION_STATE, - LastUpdateStatus: TEST_LAST_UPDATE_STATUS - } - }; + it("| no IAM role found, create IAM role passes, attach role policy fails, expect an error return", (done) => { + // setup + const TEST_POLICY_ERROR = "attachRolePolicy error message"; + sinon.stub(IAMClient.prototype, "createBasicLambdaRole").callsArgWith(1, null, TEST_ROLE_DATA); + sinon.stub(IAMClient.prototype, "attachBasicLambdaRolePolicy").callsArgWith(1, TEST_POLICY_ERROR); + // call + helper.deployIAMRole(REPORTER, TEST_IAM_CONFIG_NO_ROLE, (err) => { + // verify + expect(err).equal(`Failed to create IAM role before deploying Lambda. ${TEST_POLICY_ERROR}`); + done(); + }); + }); - beforeEach(() => { - new Manifest(FIXTURE_MANIFEST_FILE_PATH); - }); + it("| no IAM role found, create IAM role and attach role policy passes, expect a IAM role arn return.", (done) => { + // setup + sinon.stub(IAMClient.prototype, "createBasicLambdaRole").callsArgWith(1, null, TEST_ROLE_DATA); + sinon.stub(IAMClient.prototype, "attachBasicLambdaRolePolicy").callsArgWith(1, null, TEST_IAM_ROLE_ARN); + // call + helper.deployIAMRole(REPORTER, TEST_IAM_CONFIG_NO_ROLE, (err, res) => { + // verify + expect(res).equal(TEST_IAM_ROLE_ARN); + done(); + }); + }); + }); + + describe("# test class method: deployLambdaFunction", () => { + const TEST_ZIP_FILE_PATH = "zip_file_path"; + const TEST_ZIP_FILE = "zip_file"; + const TEST_CODE_BUILD = "code_build_path"; + const TEST_LAST_MODIFIED = "last_modified_time"; + const TEST_REVISION_ID = "revision_id"; + const TEST_UPDATED_REVISION_ID = "revision id"; + const TEST_FUNCTION_ARN = "lambda function arn"; + const TEST_FUNCTION_STATE = "Active"; + const TEST_LAST_UPDATE_STATUS = "Successful"; + const TEST_RUNTIME = "runtime"; + const TEST_HANDLER = "handler"; + const TEST_CREATE_OPTIONS = { + profile: TEST_PROFILE, + awsProfile: TEST_PROFILE, + alexaRegion: TEST_ALEXA_REGION, + awsRegion: TEST_AWS_REGION, + skillId: TEST_SKILL_ID, + skillName: TEST_SKILL_NAME, + code: {codeBuild: TEST_CODE_BUILD}, + iamRoleArn: TEST_IAM_ROLE_ARN, + zipFilePath: TEST_ZIP_FILE_PATH, + userConfig: {awsRegion: TEST_AWS_REGION}, + deployState: {}, + }; + const TEST_UPDATE_OPTIONS = { + profile: TEST_PROFILE, + awsProfile: TEST_PROFILE, + alexaRegion: TEST_ALEXA_REGION, + awsRegion: TEST_AWS_REGION, + skillId: TEST_SKILL_ID, + skillName: TEST_SKILL_NAME, + code: {codeBuild: TEST_CODE_BUILD}, + iamRoleArn: TEST_IAM_ROLE_ARN, + zipFilePath: TEST_ZIP_FILE_PATH, + userConfig: {awsRegion: TEST_AWS_REGION, runtime: TEST_RUNTIME, handler: TEST_HANDLER}, + deployState: { + lambda: { + arn: TEST_FUNCTION_ARN, + lastModified: TEST_LAST_MODIFIED, + revisionId: TEST_REVISION_ID, + }, + }, + }; + const TEST_CREATE_DATA = { + FunctionArn: TEST_FUNCTION_ARN, + }; + const TEST_GET_DATA = { + Configuration: { + FunctionArn: TEST_FUNCTION_ARN, + LastModified: TEST_LAST_MODIFIED, + RevisionId: TEST_UPDATED_REVISION_ID, + State: TEST_FUNCTION_STATE, + LastUpdateStatus: TEST_LAST_UPDATE_STATUS, + }, + }; - afterEach(() => { - Manifest.dispose(); - sinon.restore(); - }); + beforeEach(() => { + new Manifest(FIXTURE_MANIFEST_FILE_PATH); + }); - it('| no Lambda found, create Lambda function fails, expect an error return.', (done) => { - // setup - const TEST_CREATE_FUNCTION_ERROR = 'createLambdaFunction error'; - sinon.stub(fs, 'readFileSync').withArgs(TEST_ZIP_FILE_PATH).returns(TEST_ZIP_FILE); - sinon.stub(aws, 'Lambda'); - sinon.stub(LambdaClient.prototype, 'createLambdaFunction').callsArgWith(4, TEST_CREATE_FUNCTION_ERROR); - // call - helper.deployLambdaFunction(REPORTER, TEST_CREATE_OPTIONS, (err) => { - // verify - expect(err).equal(TEST_CREATE_FUNCTION_ERROR); - done(); - }); - }); + afterEach(() => { + Manifest.dispose(); + sinon.restore(); + }); - it('| no Lambda found, create Lambda function fails and get retry message, retry passes after one retry,' - + ' add Alexa Permission fails, expect an error return.', (done) => { - // setup - const RETRY_MESSAGE = 'The role defined for the function cannot be assumed by Lambda.'; - const TEST_CREATE_FUNCTION_ERROR = { message: RETRY_MESSAGE }; - const TEST_ADD_PERMISSION_ERROR = 'addAlexaPermissionByDomain error'; - sinon.stub(fs, 'readFileSync').withArgs(TEST_ZIP_FILE_PATH).returns(TEST_ZIP_FILE); - sinon.stub(aws, 'Lambda'); - const stubTestFunc = sinon.stub(LambdaClient.prototype, 'createLambdaFunction'); - stubTestFunc.onCall(0).callsArgWith(4, TEST_CREATE_FUNCTION_ERROR); - stubTestFunc.onCall(1).callsArgWith(4, null, TEST_CREATE_DATA); - sinon.stub(LambdaClient.prototype, 'addAlexaPermissionByDomain').callsArgWith(3, TEST_ADD_PERMISSION_ERROR); - sinon.stub(LambdaClient.prototype, 'getFunction').callsArgWith(1, null, TEST_GET_DATA); - // call - helper.deployLambdaFunction(REPORTER, TEST_CREATE_OPTIONS, (err) => { - // verify - expect(err).equal(TEST_ADD_PERMISSION_ERROR); - done(); - }); - }).timeout(10000); - - it('| no Lambda found, create Lambda function passes but not in active state, expect an error return.', (done) => { - // setup - const TEST_GET_STATE_DATA = { Configuration: { State: 'Inactive' } }; - const TEST_GET_STATE_ERROR = `Function [${TEST_FUNCTION_ARN}] state is Inactive.`; - sinon.stub(fs, 'readFileSync').withArgs(TEST_ZIP_FILE_PATH).returns(TEST_ZIP_FILE); - sinon.stub(aws, 'Lambda'); - sinon.stub(LambdaClient.prototype, 'createLambdaFunction').callsArgWith(4, null, TEST_CREATE_DATA); - sinon.stub(LambdaClient.prototype, 'getFunction').callsArgWith(1, null, TEST_GET_STATE_DATA); - // call - helper.deployLambdaFunction(REPORTER, TEST_CREATE_OPTIONS, (err) => { - // verify - expect(err).equal(TEST_GET_STATE_ERROR); - done(); - }); - }); + it("| no Lambda found, create Lambda function fails, expect an error return.", (done) => { + // setup + const TEST_CREATE_FUNCTION_ERROR = "createLambdaFunction error"; + sinon.stub(fs, "readFileSync").withArgs(TEST_ZIP_FILE_PATH).returns(TEST_ZIP_FILE); + sinon.stub(aws, "Lambda"); + sinon.stub(LambdaClient.prototype, "createLambdaFunction").callsArgWith(4, TEST_CREATE_FUNCTION_ERROR); + // call + helper.deployLambdaFunction(REPORTER, TEST_CREATE_OPTIONS, (err) => { + // verify + expect(err).equal(TEST_CREATE_FUNCTION_ERROR); + done(); + }); + }); - it('| no Lambda found, create Lambda function passes, add Alexa Permission fails, expect an error return.', (done) => { - // setup - const TEST_ADD_PERMISSION_ERROR = 'addAlexaPermissionByDomain error'; - sinon.stub(fs, 'readFileSync').withArgs(TEST_ZIP_FILE_PATH).returns(TEST_ZIP_FILE); - sinon.stub(aws, 'Lambda'); - sinon.stub(LambdaClient.prototype, 'createLambdaFunction').callsArgWith(4, null, TEST_CREATE_DATA); - sinon.stub(LambdaClient.prototype, 'addAlexaPermissionByDomain').callsArgWith(3, TEST_ADD_PERMISSION_ERROR); - sinon.stub(LambdaClient.prototype, 'getFunction').callsArgWith(1, null, TEST_GET_DATA); - // call - helper.deployLambdaFunction(REPORTER, TEST_CREATE_OPTIONS, (err) => { - // verify - expect(err).equal(TEST_ADD_PERMISSION_ERROR); - done(); - }); + it( + "| no Lambda found, create Lambda function fails and get retry message, retry passes after one retry," + + " add Alexa Permission fails, expect an error return.", + (done) => { + // setup + const RETRY_MESSAGE = "The role defined for the function cannot be assumed by Lambda."; + const TEST_CREATE_FUNCTION_ERROR = {message: RETRY_MESSAGE}; + const TEST_ADD_PERMISSION_ERROR = "addAlexaPermissionByDomain error"; + sinon.stub(fs, "readFileSync").withArgs(TEST_ZIP_FILE_PATH).returns(TEST_ZIP_FILE); + sinon.stub(aws, "Lambda"); + const stubTestFunc = sinon.stub(LambdaClient.prototype, "createLambdaFunction"); + stubTestFunc.onCall(0).callsArgWith(4, TEST_CREATE_FUNCTION_ERROR); + stubTestFunc.onCall(1).callsArgWith(4, null, TEST_CREATE_DATA); + sinon.stub(LambdaClient.prototype, "addAlexaPermissionByDomain").callsArgWith(3, TEST_ADD_PERMISSION_ERROR); + sinon.stub(LambdaClient.prototype, "getFunction").callsArgWith(1, null, TEST_GET_DATA); + // call + helper.deployLambdaFunction(REPORTER, TEST_CREATE_OPTIONS, (err) => { + // verify + expect(err).equal(TEST_ADD_PERMISSION_ERROR); + done(); }); + }, + ).timeout(10000); + + it("| no Lambda found, create Lambda function passes but not in active state, expect an error return.", (done) => { + // setup + const TEST_GET_STATE_DATA = {Configuration: {State: "Inactive"}}; + const TEST_GET_STATE_ERROR = `Function [${TEST_FUNCTION_ARN}] state is Inactive.`; + sinon.stub(fs, "readFileSync").withArgs(TEST_ZIP_FILE_PATH).returns(TEST_ZIP_FILE); + sinon.stub(aws, "Lambda"); + sinon.stub(LambdaClient.prototype, "createLambdaFunction").callsArgWith(4, null, TEST_CREATE_DATA); + sinon.stub(LambdaClient.prototype, "getFunction").callsArgWith(1, null, TEST_GET_STATE_DATA); + // call + helper.deployLambdaFunction(REPORTER, TEST_CREATE_OPTIONS, (err) => { + // verify + expect(err).equal(TEST_GET_STATE_ERROR); + done(); + }); + }); - it('| no Lambda found, create Lambda function and add Alexa Permission pass, get Function revisionId fails,' - + ' expect an error return.', (done) => { - // setup - const TEST_REVISION_ID_ERROR = 'getFunctionRevisionId error'; - sinon.stub(fs, 'readFileSync').withArgs(TEST_ZIP_FILE_PATH).returns(TEST_ZIP_FILE); - sinon.stub(aws, 'Lambda'); - sinon.stub(LambdaClient.prototype, 'createLambdaFunction').callsArgWith(4, null, TEST_CREATE_DATA); - sinon.stub(LambdaClient.prototype, 'addAlexaPermissionByDomain').callsArgWith(3, null); - const stubTestFunc = sinon.stub(LambdaClient.prototype, 'getFunction'); - stubTestFunc.onCall(0).callsArgWith(1, null, TEST_GET_DATA); - stubTestFunc.onCall(1).callsArgWith(1, TEST_REVISION_ID_ERROR); - - // call - helper.deployLambdaFunction(REPORTER, TEST_CREATE_OPTIONS, (err) => { - // verify - expect(err).equal(TEST_REVISION_ID_ERROR); - done(); - }); - }); + it("| no Lambda found, create Lambda function passes, add Alexa Permission fails, expect an error return.", (done) => { + // setup + const TEST_ADD_PERMISSION_ERROR = "addAlexaPermissionByDomain error"; + sinon.stub(fs, "readFileSync").withArgs(TEST_ZIP_FILE_PATH).returns(TEST_ZIP_FILE); + sinon.stub(aws, "Lambda"); + sinon.stub(LambdaClient.prototype, "createLambdaFunction").callsArgWith(4, null, TEST_CREATE_DATA); + sinon.stub(LambdaClient.prototype, "addAlexaPermissionByDomain").callsArgWith(3, TEST_ADD_PERMISSION_ERROR); + sinon.stub(LambdaClient.prototype, "getFunction").callsArgWith(1, null, TEST_GET_DATA); + // call + helper.deployLambdaFunction(REPORTER, TEST_CREATE_OPTIONS, (err) => { + // verify + expect(err).equal(TEST_ADD_PERMISSION_ERROR); + done(); + }); + }); - it('| no Lambda found, create Lambda function, add Alexa Permission for target domains' - + ' and get Function revisionId pass, expect Lambda data return.', (done) => { - // setup - sinon.stub(fs, 'readFileSync').withArgs(TEST_ZIP_FILE_PATH).returns(TEST_ZIP_FILE); - sinon.stub(aws, 'Lambda'); - sinon.stub(LambdaClient.prototype, 'createLambdaFunction').callsArgWith(4, null, TEST_CREATE_DATA); - sinon.stub(LambdaClient.prototype, 'addAlexaPermissionByDomain').callsArgWith(3, null); - sinon.stub(LambdaClient.prototype, 'getFunction').callsArgWith(1, null, TEST_GET_DATA); - - // call - helper.deployLambdaFunction(REPORTER, TEST_CREATE_OPTIONS, (err, res) => { - // verify - expect(res).deep.equal({ - isAllStepSuccess: true, - isCodeDeployed: true, - lambdaResponse: { - arn: TEST_FUNCTION_ARN, - lastModified: TEST_LAST_MODIFIED, - revisionId: TEST_UPDATED_REVISION_ID - } - }); - done(); - }); + it( + "| no Lambda found, create Lambda function and add Alexa Permission pass, get Function revisionId fails," + + " expect an error return.", + (done) => { + // setup + const TEST_REVISION_ID_ERROR = "getFunctionRevisionId error"; + sinon.stub(fs, "readFileSync").withArgs(TEST_ZIP_FILE_PATH).returns(TEST_ZIP_FILE); + sinon.stub(aws, "Lambda"); + sinon.stub(LambdaClient.prototype, "createLambdaFunction").callsArgWith(4, null, TEST_CREATE_DATA); + sinon.stub(LambdaClient.prototype, "addAlexaPermissionByDomain").callsArgWith(3, null); + const stubTestFunc = sinon.stub(LambdaClient.prototype, "getFunction"); + stubTestFunc.onCall(0).callsArgWith(1, null, TEST_GET_DATA); + stubTestFunc.onCall(1).callsArgWith(1, TEST_REVISION_ID_ERROR); + + // call + helper.deployLambdaFunction(REPORTER, TEST_CREATE_OPTIONS, (err) => { + // verify + expect(err).equal(TEST_REVISION_ID_ERROR); + done(); }); - - it('| no Lambda found, create Lambda function, add Alexa Permission for domains from skill ' - + 'manifest and get Function revisionId pass, expect Lambda data return.', (done) => { - // setup - sinon.stub(fs, 'readFileSync').withArgs(TEST_ZIP_FILE_PATH).returns(TEST_ZIP_FILE); - sinon.stub(aws, 'Lambda'); - sinon.stub(ResourcesConfig.prototype, 'getTargetEndpoints').returns([]); - sinon.stub(LambdaClient.prototype, 'createLambdaFunction').callsArgWith(4, null, TEST_CREATE_DATA); - sinon.stub(LambdaClient.prototype, 'addAlexaPermissionByDomain').callsArgWith(3, null); - sinon.stub(LambdaClient.prototype, 'getFunction').callsArgWith(1, null, TEST_GET_DATA); - - // call - helper.deployLambdaFunction(REPORTER, TEST_CREATE_OPTIONS, (err, res) => { - // verify - expect(res).deep.equal({ - isAllStepSuccess: true, - isCodeDeployed: true, - lambdaResponse: { - arn: TEST_FUNCTION_ARN, - lastModified: TEST_LAST_MODIFIED, - revisionId: TEST_UPDATED_REVISION_ID - } - }); - done(); - }); + }, + ); + + it( + "| no Lambda found, create Lambda function, add Alexa Permission for target domains" + + " and get Function revisionId pass, expect Lambda data return.", + (done) => { + // setup + sinon.stub(fs, "readFileSync").withArgs(TEST_ZIP_FILE_PATH).returns(TEST_ZIP_FILE); + sinon.stub(aws, "Lambda"); + sinon.stub(LambdaClient.prototype, "createLambdaFunction").callsArgWith(4, null, TEST_CREATE_DATA); + sinon.stub(LambdaClient.prototype, "addAlexaPermissionByDomain").callsArgWith(3, null); + sinon.stub(LambdaClient.prototype, "getFunction").callsArgWith(1, null, TEST_GET_DATA); + + // call + helper.deployLambdaFunction(REPORTER, TEST_CREATE_OPTIONS, (err, res) => { + // verify + expect(res).deep.equal({ + isAllStepSuccess: true, + isCodeDeployed: true, + lambdaResponse: { + arn: TEST_FUNCTION_ARN, + lastModified: TEST_LAST_MODIFIED, + revisionId: TEST_UPDATED_REVISION_ID, + }, + }); + done(); }); - - it('| an existing Lambda found, update function code fails, expect an error return.', (done) => { - // setup - const TEST_UPDATE_CODE_ERROR = 'updateFunctionCode error'; - sinon.stub(fs, 'readFileSync').withArgs(TEST_ZIP_FILE_PATH).returns(TEST_ZIP_FILE); - sinon.stub(aws, 'Lambda'); - sinon.stub(LambdaClient.prototype, 'updateFunctionCode').callsArgWith(3, TEST_UPDATE_CODE_ERROR); - // call - helper.deployLambdaFunction(REPORTER, TEST_UPDATE_OPTIONS, (err) => { - // verify - expect(err).equal(TEST_UPDATE_CODE_ERROR); - done(); - }); + }, + ); + + it( + "| no Lambda found, create Lambda function, add Alexa Permission for domains from skill " + + "manifest and get Function revisionId pass, expect Lambda data return.", + (done) => { + // setup + sinon.stub(fs, "readFileSync").withArgs(TEST_ZIP_FILE_PATH).returns(TEST_ZIP_FILE); + sinon.stub(aws, "Lambda"); + sinon.stub(ResourcesConfig.prototype, "getTargetEndpoints").returns([]); + sinon.stub(LambdaClient.prototype, "createLambdaFunction").callsArgWith(4, null, TEST_CREATE_DATA); + sinon.stub(LambdaClient.prototype, "addAlexaPermissionByDomain").callsArgWith(3, null); + sinon.stub(LambdaClient.prototype, "getFunction").callsArgWith(1, null, TEST_GET_DATA); + + // call + helper.deployLambdaFunction(REPORTER, TEST_CREATE_OPTIONS, (err, res) => { + // verify + expect(res).deep.equal({ + isAllStepSuccess: true, + isCodeDeployed: true, + lambdaResponse: { + arn: TEST_FUNCTION_ARN, + lastModified: TEST_LAST_MODIFIED, + revisionId: TEST_UPDATED_REVISION_ID, + }, + }); + done(); }); + }, + ); + + it("| an existing Lambda found, update function code fails, expect an error return.", (done) => { + // setup + const TEST_UPDATE_CODE_ERROR = "updateFunctionCode error"; + sinon.stub(fs, "readFileSync").withArgs(TEST_ZIP_FILE_PATH).returns(TEST_ZIP_FILE); + sinon.stub(aws, "Lambda"); + sinon.stub(LambdaClient.prototype, "updateFunctionCode").callsArgWith(3, TEST_UPDATE_CODE_ERROR); + // call + helper.deployLambdaFunction(REPORTER, TEST_UPDATE_OPTIONS, (err) => { + // verify + expect(err).equal(TEST_UPDATE_CODE_ERROR); + done(); + }); + }); - it('| an existing Lambda found, update function code passes but last update status failed, expect an error return.', (done) => { - // setup - const TEST_GET_UPDATE_STATUS_DATA = { Configuration: { State: 'Active', LastUpdateStatus: 'Failed' } }; - const TEST_GET_UPDATE_STATUS_ERROR = `Function [${TEST_FUNCTION_ARN}] last update status is Failed.`; - sinon.stub(fs, 'readFileSync').withArgs(TEST_ZIP_FILE_PATH).returns(TEST_ZIP_FILE); - sinon.stub(aws, 'Lambda'); - sinon.stub(LambdaClient.prototype, 'updateFunctionCode').callsArgWith(3, null, { RevisionId: TEST_REVISION_ID }); - sinon.stub(LambdaClient.prototype, 'getFunction').callsArgWith(1, null, TEST_GET_UPDATE_STATUS_DATA); - // call - helper.deployLambdaFunction(REPORTER, TEST_UPDATE_OPTIONS, (err, res) => { - // verify - expect(err).equal(TEST_GET_UPDATE_STATUS_ERROR); - done(); - }); - }); + it("| an existing Lambda found, update function code passes but last update status failed, expect an error return.", (done) => { + // setup + const TEST_GET_UPDATE_STATUS_DATA = {Configuration: {State: "Active", LastUpdateStatus: "Failed"}}; + const TEST_GET_UPDATE_STATUS_ERROR = `Function [${TEST_FUNCTION_ARN}] last update status is Failed.`; + sinon.stub(fs, "readFileSync").withArgs(TEST_ZIP_FILE_PATH).returns(TEST_ZIP_FILE); + sinon.stub(aws, "Lambda"); + sinon.stub(LambdaClient.prototype, "updateFunctionCode").callsArgWith(3, null, {RevisionId: TEST_REVISION_ID}); + sinon.stub(LambdaClient.prototype, "getFunction").callsArgWith(1, null, TEST_GET_UPDATE_STATUS_DATA); + // call + helper.deployLambdaFunction(REPORTER, TEST_UPDATE_OPTIONS, (err, res) => { + // verify + expect(err).equal(TEST_GET_UPDATE_STATUS_ERROR); + done(); + }); + }); - it('| an existing Lambda found, update function code passes, update function configuration fails, expect an error return.', (done) => { - // setup - const TEST_UPDATE_CONFIG_ERROR = 'updateFunctionConfiguration error'; - sinon.stub(fs, 'readFileSync').withArgs(TEST_ZIP_FILE_PATH).returns(TEST_ZIP_FILE); - sinon.stub(aws, 'Lambda'); - sinon.stub(LambdaClient.prototype, 'updateFunctionCode').callsArgWith(3, null, { RevisionId: TEST_REVISION_ID }); - sinon.stub(LambdaClient.prototype, 'updateFunctionConfiguration').callsArgWith(3, TEST_UPDATE_CONFIG_ERROR); - sinon.stub(LambdaClient.prototype, 'getFunction').callsArgWith(1, null, TEST_GET_DATA); - // call - helper.deployLambdaFunction(REPORTER, TEST_UPDATE_OPTIONS, (err, res) => { - // verify - expect(err).equal(null); - expect(res).deep.equal({ - isAllStepSuccess: false, - isCodeDeployed: true, - lambdaResponse: { - arn: TEST_FUNCTION_ARN, - lastModified: TEST_LAST_MODIFIED, - revisionId: TEST_UPDATED_REVISION_ID - }, - resultMessage: TEST_UPDATE_CONFIG_ERROR - }); - done(); - }); + it("| an existing Lambda found, update function code passes, update function configuration fails, expect an error return.", (done) => { + // setup + const TEST_UPDATE_CONFIG_ERROR = "updateFunctionConfiguration error"; + sinon.stub(fs, "readFileSync").withArgs(TEST_ZIP_FILE_PATH).returns(TEST_ZIP_FILE); + sinon.stub(aws, "Lambda"); + sinon.stub(LambdaClient.prototype, "updateFunctionCode").callsArgWith(3, null, {RevisionId: TEST_REVISION_ID}); + sinon.stub(LambdaClient.prototype, "updateFunctionConfiguration").callsArgWith(3, TEST_UPDATE_CONFIG_ERROR); + sinon.stub(LambdaClient.prototype, "getFunction").callsArgWith(1, null, TEST_GET_DATA); + // call + helper.deployLambdaFunction(REPORTER, TEST_UPDATE_OPTIONS, (err, res) => { + // verify + expect(err).equal(null); + expect(res).deep.equal({ + isAllStepSuccess: false, + isCodeDeployed: true, + lambdaResponse: { + arn: TEST_FUNCTION_ARN, + lastModified: TEST_LAST_MODIFIED, + revisionId: TEST_UPDATED_REVISION_ID, + }, + resultMessage: TEST_UPDATE_CONFIG_ERROR, }); + done(); + }); + }); - it('| an existing Lambda found, update function code and update function configuration pass, expect updated lambda data return.', (done) => { - // setup - const TEST_UPDATE_CONFIG_DATA = { - FunctionArn: TEST_FUNCTION_ARN, - LastModified: TEST_LAST_MODIFIED, - RevisionId: TEST_REVISION_ID - }; - sinon.stub(fs, 'readFileSync').withArgs(TEST_ZIP_FILE_PATH).returns(TEST_ZIP_FILE); - sinon.stub(aws, 'Lambda'); - sinon.stub(LambdaClient.prototype, 'updateFunctionCode').callsArgWith(3, null, { RevisionId: TEST_REVISION_ID }); - sinon.stub(LambdaClient.prototype, 'updateFunctionConfiguration').callsArgWith(3, null, TEST_UPDATE_CONFIG_DATA); - sinon.stub(LambdaClient.prototype, 'getFunction').callsArgWith(1, null, TEST_GET_DATA); - // call - helper.deployLambdaFunction(REPORTER, TEST_UPDATE_OPTIONS, (err, data) => { - // verify - expect(data).deep.equal({ - isAllStepSuccess: true, - isCodeDeployed: true, - lambdaResponse: { - arn: TEST_FUNCTION_ARN, - lastModified: TEST_LAST_MODIFIED, - revisionId: TEST_UPDATED_REVISION_ID - } - }); - done(); - }); + it("| an existing Lambda found, update function code and update function configuration pass, expect updated lambda data return.", (done) => { + // setup + const TEST_UPDATE_CONFIG_DATA = { + FunctionArn: TEST_FUNCTION_ARN, + LastModified: TEST_LAST_MODIFIED, + RevisionId: TEST_REVISION_ID, + }; + sinon.stub(fs, "readFileSync").withArgs(TEST_ZIP_FILE_PATH).returns(TEST_ZIP_FILE); + sinon.stub(aws, "Lambda"); + sinon.stub(LambdaClient.prototype, "updateFunctionCode").callsArgWith(3, null, {RevisionId: TEST_REVISION_ID}); + sinon.stub(LambdaClient.prototype, "updateFunctionConfiguration").callsArgWith(3, null, TEST_UPDATE_CONFIG_DATA); + sinon.stub(LambdaClient.prototype, "getFunction").callsArgWith(1, null, TEST_GET_DATA); + // call + helper.deployLambdaFunction(REPORTER, TEST_UPDATE_OPTIONS, (err, data) => { + // verify + expect(data).deep.equal({ + isAllStepSuccess: true, + isCodeDeployed: true, + lambdaResponse: { + arn: TEST_FUNCTION_ARN, + lastModified: TEST_LAST_MODIFIED, + revisionId: TEST_UPDATED_REVISION_ID, + }, }); + done(); + }); }); + }); }); diff --git a/test/unit/builtins/lambda-deployer/index-test.js b/test/unit/builtins/lambda-deployer/index-test.js index 0195ba2c..61a856ea 100644 --- a/test/unit/builtins/lambda-deployer/index-test.js +++ b/test/unit/builtins/lambda-deployer/index-test.js @@ -1,282 +1,289 @@ -const { expect } = require('chai'); -const sinon = require('sinon'); +const {expect} = require("chai"); +const sinon = require("sinon"); -const awsUtil = require('@src/clients/aws-client/aws-util'); -const CONSTANTS = require('@src/utils/constants'); -const helper = require('@src/builtins/deploy-delegates/lambda-deployer/helper'); -const lambdaDeployer = require('@src/builtins/deploy-delegates/lambda-deployer/index'); +const awsUtil = require("../../../../lib/clients/aws-client/aws-util"); +const CONSTANTS = require("../../../../lib/utils/constants"); +const helper = require("../../../../lib/builtins/deploy-delegates/lambda-deployer/helper"); +const lambdaDeployer = require("../../../../lib/builtins/deploy-delegates/lambda-deployer/index"); -describe('Builtins test - lambda-deployer index.js test', () => { - const TEST_PROFILE = 'default'; // test file uses 'default' profile - const TEST_IGNORE_HASH = false; - const TEST_ALEXA_REGION_DEFAULT = 'default'; - const TEST_ALEXA_REGION_NA = 'NA'; - const TEST_AWS_REGION_DEFAULT = 'us-east-1'; - const TEST_AWS_REGION_NA = 'us-east-1'; - const TEST_SKILL_NAME = 'skill_name'; - const TEST_IAM_ROLE_ARN = 'IAM role arn'; - const NULL_PROFILE = 'null'; - const LAMBDA_ARN = 'lambda_arn'; - const LAST_MODIFIED = 'last_modified'; - const REVISION_ID = '1'; +describe("Builtins test - lambda-deployer index.js test", () => { + const TEST_PROFILE = "default"; // test file uses 'default' profile + const TEST_IGNORE_HASH = false; + const TEST_ALEXA_REGION_DEFAULT = "default"; + const TEST_ALEXA_REGION_NA = "NA"; + const TEST_AWS_REGION_DEFAULT = "us-east-1"; + const TEST_AWS_REGION_NA = "us-east-1"; + const TEST_SKILL_NAME = "skill_name"; + const TEST_IAM_ROLE_ARN = "IAM role arn"; + const NULL_PROFILE = "null"; + const LAMBDA_ARN = "lambda_arn"; + const LAST_MODIFIED = "last_modified"; + const REVISION_ID = "1"; - describe('# test class method: bootstrap', () => { - afterEach(() => { - sinon.restore(); - }); + describe("# test class method: bootstrap", () => { + afterEach(() => { + sinon.restore(); + }); - it('| awsProfile and awsDefaultRegion are set, expect config is updated correctly', (done) => { - // set up - const TEST_OPTIONS = { - profile: TEST_PROFILE, - userConfig: {} - }; - sinon.stub(awsUtil, 'getAWSProfile').withArgs(TEST_PROFILE).returns(TEST_PROFILE); - sinon.stub(awsUtil, 'getCLICompatibleDefaultRegion').withArgs(TEST_PROFILE).returns(CONSTANTS.AWS_SKILL_INFRASTRUCTURE_DEFAULT_REGION); - // call - lambdaDeployer.bootstrap(TEST_OPTIONS, (err, res) => { - // verify - expect(err).equal(null); - expect(res).deep.equal({ - userConfig: { awsRegion: CONSTANTS.AWS_SKILL_INFRASTRUCTURE_DEFAULT_REGION } - }); - done(); - }); + it("| awsProfile and awsDefaultRegion are set, expect config is updated correctly", (done) => { + // set up + const TEST_OPTIONS = { + profile: TEST_PROFILE, + userConfig: {}, + }; + sinon.stub(awsUtil, "getAWSProfile").withArgs(TEST_PROFILE).returns(TEST_PROFILE); + sinon + .stub(awsUtil, "getCLICompatibleDefaultRegion") + .withArgs(TEST_PROFILE) + .returns(CONSTANTS.AWS_SKILL_INFRASTRUCTURE_DEFAULT_REGION); + // call + lambdaDeployer.bootstrap(TEST_OPTIONS, (err, res) => { + // verify + expect(err).equal(null); + expect(res).deep.equal({ + userConfig: {awsRegion: CONSTANTS.AWS_SKILL_INFRASTRUCTURE_DEFAULT_REGION}, }); + done(); + }); }); + }); - describe('# test case method: invoke', () => { - const REPORTER = {}; - const TEST_OPTIONS = { - profile: TEST_PROFILE, - ignoreHash: TEST_IGNORE_HASH, - alexaRegion: TEST_ALEXA_REGION_DEFAULT, - skillId: '', - skillName: TEST_SKILL_NAME, - code: {}, - userConfig: {}, - deployState: {}, - deployRegions: { - [TEST_ALEXA_REGION_DEFAULT]: TEST_AWS_REGION_DEFAULT - } - }; - const TEST_VALIDATED_DEPLOY_STATE = { - lambda: {}, - iamRole: {} - }; - - afterEach(() => { - sinon.restore(); - }); + describe("# test case method: invoke", () => { + const REPORTER = {}; + const TEST_OPTIONS = { + profile: TEST_PROFILE, + ignoreHash: TEST_IGNORE_HASH, + alexaRegion: TEST_ALEXA_REGION_DEFAULT, + skillId: "", + skillName: TEST_SKILL_NAME, + code: {}, + userConfig: {}, + deployState: {}, + deployRegions: { + [TEST_ALEXA_REGION_DEFAULT]: TEST_AWS_REGION_DEFAULT, + }, + }; + const TEST_VALIDATED_DEPLOY_STATE = { + lambda: {}, + iamRole: {}, + }; - it('| profile is not set, expect an error return', (done) => { - // setup - const TEST_OPTIONS_WITHOUT_PROFILE = { - profile: null, - }; - const TEST_ERROR = `Profile [${NULL_PROFILE}] doesn't have AWS profile linked to it. \ -Please run "ask configure" to re-configure your porfile.`; - sinon.stub(awsUtil, 'getAWSProfile').withArgs(NULL_PROFILE).returns(NULL_PROFILE); - // call - lambdaDeployer.invoke(REPORTER, TEST_OPTIONS_WITHOUT_PROFILE, (err) => { - // verify - expect(err).equal(TEST_ERROR); - done(); - }); - }); + afterEach(() => { + sinon.restore(); + }); - it('| profile is set, alexaRegion is not set correctly, expect an error return', (done) => { - // setup - const TEST_OPTIONS_WITHOUT_REGION = { - profile: TEST_PROFILE, - alexaRegion: null, - skillId: '', - skillName: TEST_SKILL_NAME, - code: {}, - userConfig: {}, - deployState: {}, - deployRegions: {} - }; - const TEST_ERROR = `Unsupported Alexa region: ${null}. Please check your region name or use "regionalOverrides" to specify AWS region.`; - sinon.stub(awsUtil, 'getAWSProfile').withArgs(TEST_PROFILE).returns(TEST_PROFILE); - // call - lambdaDeployer.invoke(REPORTER, TEST_OPTIONS_WITHOUT_REGION, (err) => { - // verify - expect(err).equal(TEST_ERROR); - done(); - }); - }); + it("| profile is not set, expect an error return", (done) => { + // setup + const TEST_OPTIONS_WITHOUT_PROFILE = { + profile: null, + }; + const TEST_ERROR = `Profile [${NULL_PROFILE}] doesn't have AWS profile linked to it. \ +Please run "ask configure" to re-configure your profile.`; + sinon.stub(awsUtil, "getAWSProfile").withArgs(NULL_PROFILE).returns(NULL_PROFILE); + // call + lambdaDeployer.invoke(REPORTER, TEST_OPTIONS_WITHOUT_PROFILE, (err) => { + // verify + expect(err).equal(TEST_ERROR); + done(); + }); + }); + it("| profile is set, alexaRegion is not set correctly, expect an error return", (done) => { + // setup + const TEST_OPTIONS_WITHOUT_REGION = { + profile: TEST_PROFILE, + alexaRegion: null, + skillId: "", + skillName: TEST_SKILL_NAME, + code: {}, + userConfig: {}, + deployState: {}, + deployRegions: {}, + }; + const TEST_ERROR = `Unsupported Alexa region: ${null}. Please check your region name or use "regionalOverrides" to specify AWS region.`; + sinon.stub(awsUtil, "getAWSProfile").withArgs(TEST_PROFILE).returns(TEST_PROFILE); + // call + lambdaDeployer.invoke(REPORTER, TEST_OPTIONS_WITHOUT_REGION, (err) => { + // verify + expect(err).equal(TEST_ERROR); + done(); + }); + }); - it('| alexaRegion is set correctly, validate Lambda deploy state fails, expect an error message return', (done) => { - // setup - const TEST_ERROR = 'loadLambdaInformation error message'; - const TEST_ERROR_MESSAGE_RESPONSE = `The lambda deploy failed for Alexa region "default": ${TEST_ERROR}`; - sinon.stub(awsUtil, 'getAWSProfile').withArgs(TEST_PROFILE).returns(TEST_PROFILE); - sinon.stub(helper, 'loadLambdaInformation').callsArgWith(2, TEST_ERROR); - // call - lambdaDeployer.invoke(REPORTER, TEST_OPTIONS, (err, res) => { - // verify - expect(res.resultMessage).equal(TEST_ERROR_MESSAGE_RESPONSE); - expect(err).equal(null); - done(); - }); - }); + it("| alexaRegion is set correctly, validate Lambda deploy state fails, expect an error message return", (done) => { + // setup + const TEST_ERROR = "loadLambdaInformation error message"; + const TEST_ERROR_MESSAGE_RESPONSE = `The lambda deploy failed for Alexa region "default": ${TEST_ERROR}`; + sinon.stub(awsUtil, "getAWSProfile").withArgs(TEST_PROFILE).returns(TEST_PROFILE); + sinon.stub(helper, "loadLambdaInformation").callsArgWith(2, TEST_ERROR); + // call + lambdaDeployer.invoke(REPORTER, TEST_OPTIONS, (err, res) => { + // verify + expect(res.resultMessage).equal(TEST_ERROR_MESSAGE_RESPONSE); + expect(err).equal(null); + done(); + }); + }); - it('| validate Lambda deploy state passes, deploy IAM role fails, expect an error message return', (done) => { - // setup - const TEST_ERROR = 'IAMRole error message'; - const TEST_ERROR_MESSAGE_RESPONSE = `The lambda deploy failed for Alexa region "default": ${TEST_ERROR}`; - sinon.stub(awsUtil, 'getAWSProfile').withArgs(TEST_PROFILE).returns(TEST_PROFILE); - sinon.stub(helper, 'loadLambdaInformation').callsArgWith(2, null, TEST_VALIDATED_DEPLOY_STATE); - sinon.stub(helper, 'deployIAMRole').callsArgWith(2, TEST_ERROR); - // call - lambdaDeployer.invoke(REPORTER, TEST_OPTIONS, (err, res) => { - // verify - expect(res.resultMessage).equal(TEST_ERROR_MESSAGE_RESPONSE); - expect(err).equal(null); - done(); - }); - }); + it("| validate Lambda deploy state passes, deploy IAM role fails, expect an error message return", (done) => { + // setup + const TEST_ERROR = "IAMRole error message"; + const TEST_ERROR_MESSAGE_RESPONSE = `The lambda deploy failed for Alexa region "default": ${TEST_ERROR}`; + sinon.stub(awsUtil, "getAWSProfile").withArgs(TEST_PROFILE).returns(TEST_PROFILE); + sinon.stub(helper, "loadLambdaInformation").callsArgWith(2, null, TEST_VALIDATED_DEPLOY_STATE); + sinon.stub(helper, "deployIAMRole").callsArgWith(2, TEST_ERROR); + // call + lambdaDeployer.invoke(REPORTER, TEST_OPTIONS, (err, res) => { + // verify + expect(res.resultMessage).equal(TEST_ERROR_MESSAGE_RESPONSE); + expect(err).equal(null); + done(); + }); + }); - it('| deploy IAM role passes, deploy Lambda Function fails, expect IAM role arn and an error message return', (done) => { - // setup - const TEST_ERROR = 'LambdaFunction error message'; - const TEST_ERROR_MESSAGE_RESPONSE = `The lambda deploy failed for Alexa region "default": ${TEST_ERROR}`; - sinon.stub(awsUtil, 'getAWSProfile').withArgs(TEST_PROFILE).returns(TEST_PROFILE); - sinon.stub(helper, 'loadLambdaInformation').callsArgWith(2, null, TEST_VALIDATED_DEPLOY_STATE); - sinon.stub(helper, 'deployIAMRole').callsArgWith(2, null, TEST_IAM_ROLE_ARN); - sinon.stub(helper, 'deployLambdaFunction').callsArgWith(2, TEST_ERROR); - // call - lambdaDeployer.invoke(REPORTER, TEST_OPTIONS, (err, res) => { - // verify - expect(res.resultMessage).equal(TEST_ERROR_MESSAGE_RESPONSE); - expect(res.deployState.iamRole).equal(TEST_IAM_ROLE_ARN); - expect(err).equal(null); - done(); - }); - }); + it("| deploy IAM role passes, deploy Lambda Function fails, expect IAM role arn and an error message return", (done) => { + // setup + const TEST_ERROR = "LambdaFunction error message"; + const TEST_ERROR_MESSAGE_RESPONSE = `The lambda deploy failed for Alexa region "default": ${TEST_ERROR}`; + sinon.stub(awsUtil, "getAWSProfile").withArgs(TEST_PROFILE).returns(TEST_PROFILE); + sinon.stub(helper, "loadLambdaInformation").callsArgWith(2, null, TEST_VALIDATED_DEPLOY_STATE); + sinon.stub(helper, "deployIAMRole").callsArgWith(2, null, TEST_IAM_ROLE_ARN); + sinon.stub(helper, "deployLambdaFunction").callsArgWith(2, TEST_ERROR); + // call + lambdaDeployer.invoke(REPORTER, TEST_OPTIONS, (err, res) => { + // verify + expect(res.resultMessage).equal(TEST_ERROR_MESSAGE_RESPONSE); + expect(res.deployState.iamRole).equal(TEST_IAM_ROLE_ARN); + expect(err).equal(null); + done(); + }); + }); - it('| deploy IAM role passes, deploy Lambda config fails, expect all data, except endpoint, and an error message returned', (done) => { - // setup - const TEST_ERROR = 'LambdaFunction error message'; - const TEST_ERROR_MESSAGE_RESPONSE = `The lambda deploy failed for Alexa region "default": ${TEST_ERROR}`; - const LAMDBA_RESPONSE = { - arn: LAMBDA_ARN, - lastModified: LAST_MODIFIED, - revisionId: REVISION_ID - }; - const TEST_LAMBDA_RESULT = { - isAllStepSuccess: false, - isCodeDeployed: true, - lambdaResponse: LAMDBA_RESPONSE, - resultMessage: TEST_ERROR - }; - sinon.stub(awsUtil, 'getAWSProfile').withArgs(TEST_PROFILE).returns(TEST_PROFILE); - sinon.stub(helper, 'loadLambdaInformation').callsArgWith(2, null, TEST_VALIDATED_DEPLOY_STATE); - sinon.stub(helper, 'deployIAMRole').callsArgWith(2, null, TEST_IAM_ROLE_ARN); - sinon.stub(helper, 'deployLambdaFunction').callsArgWith(2, null, TEST_LAMBDA_RESULT); - // call - lambdaDeployer.invoke(REPORTER, TEST_OPTIONS, (err, res) => { - // verify - expect(res.endpoint).equal(undefined); - expect(res.deployState.iamRole).equal(TEST_IAM_ROLE_ARN); - expect(res.deployState.lambda).deep.equal(LAMDBA_RESPONSE); - expect(res.resultMessage).equal(TEST_ERROR_MESSAGE_RESPONSE); - expect(err).equal(null); - done(); - }); - }); + it("| deploy IAM role passes, deploy Lambda config fails, expect all data, except endpoint, and an error message returned", (done) => { + // setup + const TEST_ERROR = "LambdaFunction error message"; + const TEST_ERROR_MESSAGE_RESPONSE = `The lambda deploy failed for Alexa region "default": ${TEST_ERROR}`; + const LAMDBA_RESPONSE = { + arn: LAMBDA_ARN, + lastModified: LAST_MODIFIED, + revisionId: REVISION_ID, + }; + const TEST_LAMBDA_RESULT = { + isAllStepSuccess: false, + isCodeDeployed: true, + lambdaResponse: LAMDBA_RESPONSE, + resultMessage: TEST_ERROR, + }; + sinon.stub(awsUtil, "getAWSProfile").withArgs(TEST_PROFILE).returns(TEST_PROFILE); + sinon.stub(helper, "loadLambdaInformation").callsArgWith(2, null, TEST_VALIDATED_DEPLOY_STATE); + sinon.stub(helper, "deployIAMRole").callsArgWith(2, null, TEST_IAM_ROLE_ARN); + sinon.stub(helper, "deployLambdaFunction").callsArgWith(2, null, TEST_LAMBDA_RESULT); + // call + lambdaDeployer.invoke(REPORTER, TEST_OPTIONS, (err, res) => { + // verify + expect(res.endpoint).equal(undefined); + expect(res.deployState.iamRole).equal(TEST_IAM_ROLE_ARN); + expect(res.deployState.lambda).deep.equal(LAMDBA_RESPONSE); + expect(res.resultMessage).equal(TEST_ERROR_MESSAGE_RESPONSE); + expect(err).equal(null); + done(); + }); + }); - it('| deploy IAM role and Lambda Function pass, expect correct data return', (done) => { - // setup - const TEST_SUCCESS_RESPONSE = `The lambda deploy succeeded for Alexa region "${TEST_ALEXA_REGION_DEFAULT}" \ + it("| deploy IAM role and Lambda Function pass, expect correct data return", (done) => { + // setup + const TEST_SUCCESS_RESPONSE = `The lambda deploy succeeded for Alexa region "${TEST_ALEXA_REGION_DEFAULT}" \ with output Lambda ARN: ${LAMBDA_ARN}.`; - const LAMDBA_RESPONSE = { - arn: LAMBDA_ARN, - lastModified: LAST_MODIFIED, - revisionId: REVISION_ID - }; - const TEST_LAMBDA_RESULT = { - isAllStepSuccess: true, - isCodeDeployed: true, - lambdaResponse: LAMDBA_RESPONSE - }; - sinon.stub(awsUtil, 'getAWSProfile').withArgs(TEST_PROFILE).returns(TEST_PROFILE); - sinon.stub(helper, 'loadLambdaInformation').callsArgWith(2, null, TEST_VALIDATED_DEPLOY_STATE); - sinon.stub(helper, 'deployIAMRole').callsArgWith(2, null, TEST_IAM_ROLE_ARN); - sinon.stub(helper, 'deployLambdaFunction').callsArgWith(2, null, TEST_LAMBDA_RESULT); - // call - lambdaDeployer.invoke(REPORTER, TEST_OPTIONS, (err, res) => { - // verify - expect(res.endpoint.uri).equal(LAMBDA_ARN); - expect(res.deployState.iamRole).equal(TEST_IAM_ROLE_ARN); - expect(res.deployState.lambda).deep.equal(LAMDBA_RESPONSE); - expect(res.resultMessage).equal(TEST_SUCCESS_RESPONSE); - expect(err).equal(null); - done(); - }); - }); + const LAMDBA_RESPONSE = { + arn: LAMBDA_ARN, + lastModified: LAST_MODIFIED, + revisionId: REVISION_ID, + }; + const TEST_LAMBDA_RESULT = { + isAllStepSuccess: true, + isCodeDeployed: true, + lambdaResponse: LAMDBA_RESPONSE, + }; + sinon.stub(awsUtil, "getAWSProfile").withArgs(TEST_PROFILE).returns(TEST_PROFILE); + sinon.stub(helper, "loadLambdaInformation").callsArgWith(2, null, TEST_VALIDATED_DEPLOY_STATE); + sinon.stub(helper, "deployIAMRole").callsArgWith(2, null, TEST_IAM_ROLE_ARN); + sinon.stub(helper, "deployLambdaFunction").callsArgWith(2, null, TEST_LAMBDA_RESULT); + // call + lambdaDeployer.invoke(REPORTER, TEST_OPTIONS, (err, res) => { + // verify + expect(res.endpoint.uri).equal(LAMBDA_ARN); + expect(res.deployState.iamRole).equal(TEST_IAM_ROLE_ARN); + expect(res.deployState.lambda).deep.equal(LAMDBA_RESPONSE); + expect(res.resultMessage).equal(TEST_SUCCESS_RESPONSE); + expect(err).equal(null); + done(); + }); + }); - it('| not primary deployRegion in multi-regions environment, expect deploy skipped message return', (done) => { - // setup - const TEST_OPTIONS_WITH_MULTI_REGIONS = { - ...TEST_OPTIONS, - alexaRegion: TEST_ALEXA_REGION_NA, - deployRegions: { - [TEST_ALEXA_REGION_DEFAULT]: TEST_AWS_REGION_DEFAULT, - [TEST_ALEXA_REGION_NA]: TEST_AWS_REGION_NA - } - }; - const TEST_SKIPPED_RESPONSE = `The lambda deploy for Alexa region "${TEST_ALEXA_REGION_NA}" is same as "${TEST_ALEXA_REGION_DEFAULT}"`; - sinon.stub(awsUtil, 'getAWSProfile').withArgs(TEST_PROFILE).returns(TEST_PROFILE); - // call - lambdaDeployer.invoke(REPORTER, TEST_OPTIONS_WITH_MULTI_REGIONS, (err, res) => { - // verify - expect(res.isDeploySkipped).equal(true); - expect(res.deployRegion).equal(TEST_ALEXA_REGION_DEFAULT); - expect(res.resultMessage).equal(TEST_SKIPPED_RESPONSE); - expect(err).equal(null); - done(); - }); - }); + it("| not primary deployRegion in multi-regions environment, expect deploy skipped message return", (done) => { + // setup + const TEST_OPTIONS_WITH_MULTI_REGIONS = { + ...TEST_OPTIONS, + alexaRegion: TEST_ALEXA_REGION_NA, + deployRegions: { + [TEST_ALEXA_REGION_DEFAULT]: TEST_AWS_REGION_DEFAULT, + [TEST_ALEXA_REGION_NA]: TEST_AWS_REGION_NA, + }, + }; + const TEST_SKIPPED_RESPONSE = `The lambda deploy for Alexa region "${TEST_ALEXA_REGION_NA}" is same as "${TEST_ALEXA_REGION_DEFAULT}"`; + sinon.stub(awsUtil, "getAWSProfile").withArgs(TEST_PROFILE).returns(TEST_PROFILE); + // call + lambdaDeployer.invoke(REPORTER, TEST_OPTIONS_WITH_MULTI_REGIONS, (err, res) => { + // verify + expect(res.isDeploySkipped).equal(true); + expect(res.deployRegion).equal(TEST_ALEXA_REGION_DEFAULT); + expect(res.resultMessage).equal(TEST_SKIPPED_RESPONSE); + expect(err).equal(null); + done(); + }); + }); - it('| not primary deployRegion in multi-regions setup but different current deploy state, expect deploy not to be skipped', (done) => { - // setup - const TEST_OPTIONS_WITH_MULTI_REGIONS = { - ...TEST_OPTIONS, - alexaRegion: TEST_ALEXA_REGION_NA, - deployState: { - [TEST_ALEXA_REGION_DEFAULT]: 'deploy_state_default', - [TEST_ALEXA_REGION_NA]: 'deploy_state_na' - }, - deployRegions: { - [TEST_ALEXA_REGION_DEFAULT]: TEST_AWS_REGION_DEFAULT, - [TEST_ALEXA_REGION_NA]: TEST_AWS_REGION_NA - } - }; - const TEST_SUCCESS_RESPONSE = `The lambda deploy succeeded for Alexa region "${TEST_ALEXA_REGION_NA}" \ + it("| not primary deployRegion in multi-regions setup but different current deploy state, expect deploy not to be skipped", (done) => { + // setup + const TEST_OPTIONS_WITH_MULTI_REGIONS = { + ...TEST_OPTIONS, + alexaRegion: TEST_ALEXA_REGION_NA, + deployState: { + [TEST_ALEXA_REGION_DEFAULT]: { + property: "1" + }, + [TEST_ALEXA_REGION_NA]: { + property: "2" + }, + }, + deployRegions: { + [TEST_ALEXA_REGION_DEFAULT]: TEST_AWS_REGION_DEFAULT, + [TEST_ALEXA_REGION_NA]: TEST_AWS_REGION_NA, + }, + }; + const TEST_SUCCESS_RESPONSE = `The lambda deploy succeeded for Alexa region "${TEST_ALEXA_REGION_NA}" \ with output Lambda ARN: ${LAMBDA_ARN}.`; - const TEST_LAMBDA_RESULT = { - isAllStepSuccess: true, - isCodeDeployed: true, - lambdaResponse: { arn: LAMBDA_ARN } - }; - sinon.stub(awsUtil, 'getAWSProfile').withArgs(TEST_PROFILE).returns(TEST_PROFILE); - sinon.stub(helper, 'loadLambdaInformation').callsArgWith(2, null, TEST_VALIDATED_DEPLOY_STATE); - sinon.stub(helper, 'deployIAMRole').callsArgWith(2, null, TEST_IAM_ROLE_ARN); - sinon.stub(helper, 'deployLambdaFunction').callsArgWith(2, null, TEST_LAMBDA_RESULT); - // call - lambdaDeployer.invoke(REPORTER, TEST_OPTIONS_WITH_MULTI_REGIONS, (err, res) => { - // verify - expect(res.isAllStepSuccess).equal(true); - expect(res.isCodeDeployed).equal(true); - expect(res.isDeploySkipped).equal(undefined); - expect(res.deployRegion).equal(undefined); - expect(res.resultMessage).equal(TEST_SUCCESS_RESPONSE); - expect(err).equal(null); - done(); - }); - }); + const TEST_LAMBDA_RESULT = { + isAllStepSuccess: true, + isCodeDeployed: true, + lambdaResponse: {arn: LAMBDA_ARN}, + }; + sinon.stub(awsUtil, "getAWSProfile").withArgs(TEST_PROFILE).returns(TEST_PROFILE); + sinon.stub(helper, "loadLambdaInformation").callsArgWith(2, null, TEST_VALIDATED_DEPLOY_STATE); + sinon.stub(helper, "deployIAMRole").callsArgWith(2, null, TEST_IAM_ROLE_ARN); + sinon.stub(helper, "deployLambdaFunction").callsArgWith(2, null, TEST_LAMBDA_RESULT); + // call + lambdaDeployer.invoke(REPORTER, TEST_OPTIONS_WITH_MULTI_REGIONS, (err, res) => { + // verify + console.log(res); + expect(res.isAllStepSuccess).equal(true); + expect(res.isCodeDeployed).equal(true); + expect(res.isDeploySkipped).equal(undefined); + expect(res.deployRegion).equal(undefined); + expect(res.resultMessage).equal(TEST_SUCCESS_RESPONSE); + expect(err).equal(null); + done(); + }); }); + }); }); diff --git a/test/unit/clients/aws-client/abstract-aws-client-test.js b/test/unit/clients/aws-client/abstract-aws-client-test.js index 7391eca1..0e260bac 100644 --- a/test/unit/clients/aws-client/abstract-aws-client-test.js +++ b/test/unit/clients/aws-client/abstract-aws-client-test.js @@ -1,49 +1,49 @@ -const { expect } = require('chai'); -const aws = require('aws-sdk'); -const CONSTANTS = require('@src/utils/constants'); +const {expect} = require("chai"); +const aws = require("aws-sdk"); +const CONSTANTS = require("../../../../lib/utils/constants"); -const AbstractAwsClient = require('@src/clients/aws-client/abstract-aws-client'); +const AbstractAwsClient = require("../../../../lib/clients/aws-client/abstract-aws-client"); -describe('Clients test - abstract client test', () => { - const TEST_AWS_PROFILE = 'TEST_AWS_PROFILE'; - const TEST_AWS_REGION = 'TEST_AWS_REGION'; - let configuration; - beforeEach(() => { - aws.config.credentials.profile = null; - configuration = { - awsProfile: TEST_AWS_PROFILE, - awsRegion: TEST_AWS_REGION - }; - }); +describe("Clients test - abstract client test", () => { + const TEST_AWS_PROFILE = "TEST_AWS_PROFILE"; + const TEST_AWS_REGION = "TEST_AWS_REGION"; + let configuration; + beforeEach(() => { + aws.config.credentials.profile = null; + configuration = { + awsProfile: TEST_AWS_PROFILE, + awsRegion: TEST_AWS_REGION, + }; + }); - describe('# constructor tests', () => { - it('| should set region and credentials profile', () => { - const client = new AbstractAwsClient(configuration); - expect(client).to.be.instanceof(AbstractAwsClient); - expect(client.awsRegion).eql(TEST_AWS_REGION); - expect(client.awsProfile).eql(TEST_AWS_PROFILE); - expect(aws.config.region).eql(TEST_AWS_REGION); - expect(aws.config.credentials.profile).eql(TEST_AWS_PROFILE); - }); + describe("# constructor tests", () => { + it("| should set region and credentials profile", () => { + const client = new AbstractAwsClient(configuration); + expect(client).to.be.instanceof(AbstractAwsClient); + expect(client.awsRegion).eql(TEST_AWS_REGION); + expect(client.awsProfile).eql(TEST_AWS_PROFILE); + expect(aws.config.region).eql(TEST_AWS_REGION); + expect(aws.config.credentials.profile).eql(TEST_AWS_PROFILE); + }); - it('| should not set credentials profile since using env variables', () => { - configuration.awsProfile = CONSTANTS.PLACEHOLDER.ENVIRONMENT_VAR.AWS_CREDENTIALS; - const client = new AbstractAwsClient(configuration); - expect(client).to.be.instanceof(AbstractAwsClient); - expect(client.awsRegion).eql(TEST_AWS_REGION); - expect(client.awsProfile).eql(CONSTANTS.PLACEHOLDER.ENVIRONMENT_VAR.AWS_CREDENTIALS); - expect(aws.config.region).eql(TEST_AWS_REGION); - expect(aws.config.credentials.profile).eql(null); - }); + it("| should not set credentials profile since using env variables", () => { + configuration.awsProfile = CONSTANTS.PLACEHOLDER.ENVIRONMENT_VAR.AWS_CREDENTIALS; + const client = new AbstractAwsClient(configuration); + expect(client).to.be.instanceof(AbstractAwsClient); + expect(client.awsRegion).eql(TEST_AWS_REGION); + expect(client.awsProfile).eql(CONSTANTS.PLACEHOLDER.ENVIRONMENT_VAR.AWS_CREDENTIALS); + expect(aws.config.region).eql(TEST_AWS_REGION); + expect(aws.config.credentials.profile).eql(null); + }); - it('| should throw error when aws profile is not specified ', () => { - configuration.awsProfile = null; - expect(() => new AbstractAwsClient(configuration)).to.throw('Invalid awsProfile or Invalid awsRegion'); - }); + it("| should throw error when aws profile is not specified ", () => { + configuration.awsProfile = null; + expect(() => new AbstractAwsClient(configuration)).to.throw("Invalid awsProfile or Invalid awsRegion"); + }); - it('| should throw error when aws region is not specified ', () => { - configuration.awsRegion = null; - expect(() => new AbstractAwsClient(configuration)).to.throw('Invalid awsProfile or Invalid awsRegion'); - }); + it("| should throw error when aws region is not specified ", () => { + configuration.awsRegion = null; + expect(() => new AbstractAwsClient(configuration)).to.throw("Invalid awsProfile or Invalid awsRegion"); }); + }); }); diff --git a/test/unit/clients/aws-client/cloudformation-client-test.js b/test/unit/clients/aws-client/cloudformation-client-test.js index 80fedca4..035a5ace 100644 --- a/test/unit/clients/aws-client/cloudformation-client-test.js +++ b/test/unit/clients/aws-client/cloudformation-client-test.js @@ -1,387 +1,382 @@ -const { expect } = require('chai'); -const sinon = require('sinon'); -const aws = require('aws-sdk'); +const {expect} = require("chai"); +const sinon = require("sinon"); +const aws = require("aws-sdk"); -const CloudformationClient = require('@src/clients/aws-client/cloudformation-client'); +const CloudformationClient = require("../../../../lib/clients/aws-client/cloudformation-client"); const noop = () => {}; -describe('Clients test - cloudformation client test', () => { - const TEST_AWS_PROFILE = 'AWS_PROFILE'; - const TEST_AWS_REGION = 'AWS_REGION'; - const TEST_CLIENT_ERROR = 'CLIENT_ERR'; - const TEST_CLIENT_RESPONSE = 'CLIENT_RESPONSE'; - const TEST_CONFIGURATION = { - awsProfile: TEST_AWS_PROFILE, - awsRegion: TEST_AWS_REGION - }; - const TEST_CREATE_RESPONSE = { - StackId: 'someId' +describe("Clients test - cloudformation client test", () => { + const TEST_AWS_PROFILE = "AWS_PROFILE"; + const TEST_AWS_REGION = "AWS_REGION"; + const TEST_CLIENT_ERROR = "CLIENT_ERR"; + const TEST_CLIENT_RESPONSE = "CLIENT_RESPONSE"; + const TEST_CONFIGURATION = { + awsProfile: TEST_AWS_PROFILE, + awsRegion: TEST_AWS_REGION, + }; + const TEST_CREATE_RESPONSE = { + StackId: "someId", + }; + const TEST_UPDATE_RESPONSE = { + StackId: "someId", + }; + let createStackStub, updateStackStub, describeStackStub, describeStackResourceStub, describeStackResourcesStub; + + beforeEach(() => { + createStackStub = sinon.stub().returns({promise: sinon.stub().resolves({...TEST_CREATE_RESPONSE})}); + updateStackStub = sinon.stub().returns({promise: sinon.stub().resolves({...TEST_UPDATE_RESPONSE})}); + describeStackStub = sinon.stub(); + describeStackResourceStub = sinon.stub(); + describeStackResourcesStub = sinon.stub(); + sinon.stub(aws, "CloudFormation").returns({ + createStack: createStackStub, + updateStack: updateStackStub, + describeStacks: describeStackStub, + describeStackResource: describeStackResourceStub, + describeStackResources: describeStackResourcesStub, + }); + }); + + afterEach(() => { + sinon.restore(); + }); + + describe("Check correctness for constructor function", () => { + it("| inspect correctness for constructor when awsRegion is set in configuration", () => { + const cfnClient = new CloudformationClient(TEST_CONFIGURATION); + expect(cfnClient).to.be.instanceof(CloudformationClient); + expect(cfnClient.awsRegion).equal(TEST_AWS_REGION); + expect(aws.config.region).equal(TEST_AWS_REGION); + expect(aws.config.credentials).deep.equal(new aws.SharedIniFileCredentials({profile: TEST_AWS_PROFILE})); + }); + + it("| throw error when awsProfile or awsRegion is not passed in", () => { + try { + new CloudformationClient({}); + } catch (e) { + expect(e.message).equal("Invalid awsProfile or Invalid awsRegion"); + } + }); + }); + + describe("Test client method - createStack()", () => { + const TEST_STACK_NAME = "STACK"; + const TEST_TEMPLATE = "TEMPLATE_CONTENT"; + const TEST_PARAMETERS = { + key: "value", }; - const TEST_UPDATE_RESPONSE = { - StackId: 'someId' + + it("| call aws-sdk createStack method with same params from input", () => { + // setup + const cfnClient = new CloudformationClient(TEST_CONFIGURATION); + // call + cfnClient.createStack(TEST_STACK_NAME, TEST_TEMPLATE, TEST_PARAMETERS); + // verify + expect(createStackStub.args[0][0].StackName).equal(TEST_STACK_NAME); + expect(createStackStub.args[0][0].TemplateBody).equal(TEST_TEMPLATE); + expect(createStackStub.args[0][0].Capabilities).deep.equal(["CAPABILITY_IAM"]); + expect(createStackStub.args[0][0].Parameters).deep.equal(TEST_PARAMETERS); + }); + + it("| call aws-sdk createStack method with same params from input without parameters", () => { + // setup + const cfnClient = new CloudformationClient(TEST_CONFIGURATION); + // call + cfnClient.createStack(TEST_STACK_NAME, TEST_TEMPLATE, {}); + // verify + expect(createStackStub.args[0][0].StackName).equal(TEST_STACK_NAME); + expect(createStackStub.args[0][0].TemplateBody).equal(TEST_TEMPLATE); + expect(createStackStub.args[0][0].Capabilities).deep.equal(["CAPABILITY_IAM"]); + expect(createStackStub.args[0][0].Parameters).equal(undefined); + }); + + it("| createStack returns response when client request succeeds", async () => { + // setup + const cfnClient = new CloudformationClient(TEST_CONFIGURATION); + + // call + const res = await cfnClient.createStack(TEST_STACK_NAME, TEST_TEMPLATE, TEST_PARAMETERS); + + expect(res).eql(TEST_CREATE_RESPONSE); + }); + }); + + describe("Test client method - updateStack()", () => { + const TEST_STACK_NAME = "STACK"; + const TEST_TEMPLATE = "TEMPLATE_CONTENT"; + const TEST_PARAMETERS = { + key: "value", }; - let createStackStub, - updateStackStub, - describeStackStub, - describeStackResourceStub, - describeStackResourcesStub; - - beforeEach(() => { - createStackStub = sinon.stub().returns({ promise: sinon.stub().resolves({ ...TEST_CREATE_RESPONSE }) }); - updateStackStub = sinon.stub().returns({ promise: sinon.stub().resolves({ ...TEST_UPDATE_RESPONSE }) }); - describeStackStub = sinon.stub(); - describeStackResourceStub = sinon.stub(); - describeStackResourcesStub = sinon.stub(); - sinon.stub(aws, 'CloudFormation').returns({ - createStack: createStackStub, - updateStack: updateStackStub, - describeStacks: describeStackStub, - describeStackResource: describeStackResourceStub, - describeStackResources: describeStackResourcesStub - }); + + it("| call aws-sdk updateStack method with same params from input", () => { + // setup + const cfnClient = new CloudformationClient(TEST_CONFIGURATION); + // call + cfnClient.updateStack(TEST_STACK_NAME, TEST_TEMPLATE, TEST_PARAMETERS, noop); + // verify + expect(updateStackStub.args[0][0].StackName).equal(TEST_STACK_NAME); + expect(updateStackStub.args[0][0].TemplateBody).equal(TEST_TEMPLATE); + expect(updateStackStub.args[0][0].Capabilities).deep.equal(["CAPABILITY_IAM"]); + expect(updateStackStub.args[0][0].Parameters).deep.equal(TEST_PARAMETERS); }); - afterEach(() => { - sinon.restore(); + it("| call aws-sdk updateStack method with same params from input without parameters", () => { + // setup + const cfnClient = new CloudformationClient(TEST_CONFIGURATION); + // call + cfnClient.updateStack(TEST_STACK_NAME, TEST_TEMPLATE, {}, noop); + // verify + expect(updateStackStub.args[0][0].StackName).equal(TEST_STACK_NAME); + expect(updateStackStub.args[0][0].TemplateBody).equal(TEST_TEMPLATE); + expect(updateStackStub.args[0][0].Capabilities).deep.equal(["CAPABILITY_IAM"]); + expect(updateStackStub.args[0][0].Parameters).equal(undefined); }); - describe('Check correctness for constructor function', () => { - it('| inspect correctness for constructor when awsRegion is set in configuration', () => { - const cfnClient = new CloudformationClient(TEST_CONFIGURATION); - expect(cfnClient).to.be.instanceof(CloudformationClient); - expect(cfnClient.awsRegion).equal(TEST_AWS_REGION); - expect(aws.config.region).equal(TEST_AWS_REGION); - expect(aws.config.credentials).deep.equal(new aws.SharedIniFileCredentials({ profile: TEST_AWS_PROFILE })); - }); - - it('| throw error when awsProfile or awsRegion is not passed in', () => { - try { - new CloudformationClient({}); - } catch (e) { - expect(e.message).equal('Invalid awsProfile or Invalid awsRegion'); - } - }); + it("| updateStack method returns error when client request fails", () => { + // setup + const cfnClient = new CloudformationClient(TEST_CONFIGURATION); + updateStackStub.returns({promise: sinon.stub().rejects(TEST_CLIENT_ERROR)}); + // call + return cfnClient.updateStack(TEST_STACK_NAME, TEST_TEMPLATE, TEST_PARAMETERS).catch((err) => { + expect(err.name).eql(TEST_CLIENT_ERROR); + }); }); - describe('Test client method - createStack()', () => { - const TEST_STACK_NAME = 'STACK'; - const TEST_TEMPLATE = 'TEMPLATE_CONTENT'; - const TEST_PARAMETERS = { - key: 'value' - }; - - it('| call aws-sdk createStack method with same params from input', () => { - // setup - const cfnClient = new CloudformationClient(TEST_CONFIGURATION); - // call - cfnClient.createStack(TEST_STACK_NAME, TEST_TEMPLATE, TEST_PARAMETERS); - // verify - expect(createStackStub.args[0][0].StackName).equal(TEST_STACK_NAME); - expect(createStackStub.args[0][0].TemplateBody).equal(TEST_TEMPLATE); - expect(createStackStub.args[0][0].Capabilities).deep.equal(['CAPABILITY_IAM']); - expect(createStackStub.args[0][0].Parameters).deep.equal(TEST_PARAMETERS); - }); - - it('| call aws-sdk createStack method with same params from input without parameters', () => { - // setup - const cfnClient = new CloudformationClient(TEST_CONFIGURATION); - // call - cfnClient.createStack(TEST_STACK_NAME, TEST_TEMPLATE, {}); - // verify - expect(createStackStub.args[0][0].StackName).equal(TEST_STACK_NAME); - expect(createStackStub.args[0][0].TemplateBody).equal(TEST_TEMPLATE); - expect(createStackStub.args[0][0].Capabilities).deep.equal(['CAPABILITY_IAM']); - expect(createStackStub.args[0][0].Parameters).equal(undefined); - }); - - - it('| createStack returns response when client request succeeds', async () => { - // setup - const cfnClient = new CloudformationClient(TEST_CONFIGURATION); - - // call - const res = await cfnClient.createStack(TEST_STACK_NAME, TEST_TEMPLATE, TEST_PARAMETERS); - - expect(res).eql(TEST_CREATE_RESPONSE); - }); + it("| updateStack returns with response string when no update to be performed", async () => { + // setup + const NO_UPDATE_ERROR = { + code: "ValidationError", + message: "No updates are to be performed.", + }; + const cfnClient = new CloudformationClient(TEST_CONFIGURATION); + updateStackStub.returns({promise: sinon.stub().rejects(NO_UPDATE_ERROR)}); + // call + const res = await cfnClient.updateStack(TEST_STACK_NAME, TEST_TEMPLATE, TEST_PARAMETERS); + // verify + expect(res).eql("No updates are to be performed."); }); - describe('Test client method - updateStack()', () => { - const TEST_STACK_NAME = 'STACK'; - const TEST_TEMPLATE = 'TEMPLATE_CONTENT'; - const TEST_PARAMETERS = { - key: 'value' - }; - - it('| call aws-sdk updateStack method with same params from input', () => { - // setup - const cfnClient = new CloudformationClient(TEST_CONFIGURATION); - // call - cfnClient.updateStack(TEST_STACK_NAME, TEST_TEMPLATE, TEST_PARAMETERS, noop); - // verify - expect(updateStackStub.args[0][0].StackName).equal(TEST_STACK_NAME); - expect(updateStackStub.args[0][0].TemplateBody).equal(TEST_TEMPLATE); - expect(updateStackStub.args[0][0].Capabilities).deep.equal(['CAPABILITY_IAM']); - expect(updateStackStub.args[0][0].Parameters).deep.equal(TEST_PARAMETERS); - }); - - it('| call aws-sdk updateStack method with same params from input without parameters', () => { - // setup - const cfnClient = new CloudformationClient(TEST_CONFIGURATION); - // call - cfnClient.updateStack(TEST_STACK_NAME, TEST_TEMPLATE, {}, noop); - // verify - expect(updateStackStub.args[0][0].StackName).equal(TEST_STACK_NAME); - expect(updateStackStub.args[0][0].TemplateBody).equal(TEST_TEMPLATE); - expect(updateStackStub.args[0][0].Capabilities).deep.equal(['CAPABILITY_IAM']); - expect(updateStackStub.args[0][0].Parameters).equal(undefined); - }); - - it('| updateStack method returns error when client request fails', () => { - // setup - const cfnClient = new CloudformationClient(TEST_CONFIGURATION); - updateStackStub.returns({ promise: sinon.stub().rejects(TEST_CLIENT_ERROR) }); - // call - return cfnClient.updateStack(TEST_STACK_NAME, TEST_TEMPLATE, TEST_PARAMETERS).catch(err => { - expect(err.name).eql(TEST_CLIENT_ERROR); - }); - }); - - it('| updateStack returns with response string when no update to be performed', async () => { - // setup - const NO_UPDATE_ERROR = { - code: 'ValidationError', - message: 'No updates are to be performed.' - }; - const cfnClient = new CloudformationClient(TEST_CONFIGURATION); - updateStackStub.returns({ promise: sinon.stub().rejects(NO_UPDATE_ERROR) }); - // call - const res = await cfnClient.updateStack(TEST_STACK_NAME, TEST_TEMPLATE, TEST_PARAMETERS); - // verify - expect(res).eql('No updates are to be performed.'); - }); - - it('| updateStack returns response when client request succeeds', async () => { - // setup - const cfnClient = new CloudformationClient(TEST_CONFIGURATION); - // call - const res = await cfnClient.updateStack(TEST_STACK_NAME, TEST_TEMPLATE, TEST_PARAMETERS); - - expect(res).eql(TEST_UPDATE_RESPONSE); - }); + it("| updateStack returns response when client request succeeds", async () => { + // setup + const cfnClient = new CloudformationClient(TEST_CONFIGURATION); + // call + const res = await cfnClient.updateStack(TEST_STACK_NAME, TEST_TEMPLATE, TEST_PARAMETERS); + + expect(res).eql(TEST_UPDATE_RESPONSE); }); + }); - describe('Test client method - stackExists()', () => { - it('| returns false when stack id is undefined', async () => { - const cfnClient = new CloudformationClient(TEST_CONFIGURATION); + describe("Test client method - stackExists()", () => { + it("| returns false when stack id is undefined", async () => { + const cfnClient = new CloudformationClient(TEST_CONFIGURATION); - const exists = await cfnClient.stackExists(); + const exists = await cfnClient.stackExists(); - expect(exists).eql(false); - }); + expect(exists).eql(false); + }); - it('| returns false when stack status is delete complete', async () => { - const cfnClient = new CloudformationClient(TEST_CONFIGURATION); - describeStackStub.returns({ promise: sinon.stub().resolves({ Stacks: [{ StackStatus: 'DELETE_COMPLETE' }] }) }); + it("| returns false when stack status is delete complete", async () => { + const cfnClient = new CloudformationClient(TEST_CONFIGURATION); + describeStackStub.returns({promise: sinon.stub().resolves({Stacks: [{StackStatus: "DELETE_COMPLETE"}]})}); - const exists = await cfnClient.stackExists('someId'); + const exists = await cfnClient.stackExists("someId"); - expect(exists).eql(false); - }); + expect(exists).eql(false); + }); - it('| returns false when when getting stack status fails', async () => { - const cfnClient = new CloudformationClient(TEST_CONFIGURATION); - describeStackStub.returns({ promise: sinon.stub().rejects() }); + it("| returns false when when getting stack status fails", async () => { + const cfnClient = new CloudformationClient(TEST_CONFIGURATION); + describeStackStub.returns({promise: sinon.stub().rejects()}); - const exists = await cfnClient.stackExists('someId'); + const exists = await cfnClient.stackExists("someId"); - expect(exists).eql(false); - }); + expect(exists).eql(false); + }); - it('| returns true when request succeeds', async () => { - const cfnClient = new CloudformationClient(TEST_CONFIGURATION); - describeStackStub.returns({ promise: sinon.stub().resolves({ Stacks: [{ StackStatus: 'test' }] }) }); + it("| returns true when request succeeds", async () => { + const cfnClient = new CloudformationClient(TEST_CONFIGURATION); + describeStackStub.returns({promise: sinon.stub().resolves({Stacks: [{StackStatus: "test"}]})}); - const exists = await cfnClient.stackExists('someId'); + const exists = await cfnClient.stackExists("someId"); - expect(exists).eql(true); - }); + expect(exists).eql(true); }); - describe('Test client method - describeStack()', () => { - const TEST_STACK_NAME = 'STACK'; - - it('| call aws-sdk describeStack method with same params from input', () => { - // setup - const cfnClient = new CloudformationClient(TEST_CONFIGURATION); - // call - cfnClient.describeStack(TEST_STACK_NAME, noop); - // verify - expect(describeStackStub.args[0][0].StackName).equal(TEST_STACK_NAME); - }); - - it('| describeStack method callback with error when stackId not provided', (done) => { - // setup - const cfnClient = new CloudformationClient(TEST_CONFIGURATION); - // call - cfnClient.describeStack('', (err, res) => { - // verify - expect(err).equal('Stack ID must be set to further describe'); - expect(res).equal(undefined); - done(); - }); - }); - - it('| describeStack method callback with error when client request fails', (done) => { - // setup - const cfnClient = new CloudformationClient(TEST_CONFIGURATION); - describeStackStub.callsArgWith(1, TEST_CLIENT_ERROR, null); - // call - cfnClient.describeStack(TEST_STACK_NAME, (err, res) => { - // verify - expect(err).equal(TEST_CLIENT_ERROR); - expect(res).equal(null); - done(); - }); - }); - - it('| describeStack method callback with response when client request succeeds', (done) => { - // setup - const cfnClient = new CloudformationClient(TEST_CONFIGURATION); - const TEST_DESCRIBE_RESPONSE = { - Stacks: [TEST_CLIENT_RESPONSE] - }; - describeStackStub.callsArgWith(1, null, TEST_DESCRIBE_RESPONSE); - // call - cfnClient.describeStack(TEST_STACK_NAME, (err, res) => { - // verify - expect(err).equal(null); - expect(res).equal(TEST_CLIENT_RESPONSE); - done(); - }); - }); + }); + describe("Test client method - describeStack()", () => { + const TEST_STACK_NAME = "STACK"; + + it("| call aws-sdk describeStack method with same params from input", () => { + // setup + const cfnClient = new CloudformationClient(TEST_CONFIGURATION); + // call + cfnClient.describeStack(TEST_STACK_NAME, noop); + // verify + expect(describeStackStub.args[0][0].StackName).equal(TEST_STACK_NAME); }); - // expect(err).equal('Logical ID must be set to describe the resource') - - describe('Test client method - describeStackResource()', () => { - const TEST_STACK_NAME = 'STACK'; - const TEST_LOGICAL_ID = 'LOGICAL_ID'; - - it('| call aws-sdk describeStackResource method with same params from input', () => { - // setup - const cfnClient = new CloudformationClient(TEST_CONFIGURATION); - // call - cfnClient.describeStackResource(TEST_STACK_NAME, TEST_LOGICAL_ID, noop); - // verify - expect(describeStackResourceStub.args[0][0].StackName).equal(TEST_STACK_NAME); - expect(describeStackResourceStub.args[0][0].LogicalResourceId).equal(TEST_LOGICAL_ID); - }); - - it('| describeStackResource method callback error when stackId not set', (done) => { - // setup - const cfnClient = new CloudformationClient(TEST_CONFIGURATION); - // call - cfnClient.describeStackResource('', TEST_LOGICAL_ID, (err, res) => { - // verify - expect(err).equal('Stack ID must be set to describe its resources'); - expect(res).equal(undefined); - done(); - }); - }); - - it('| describeStackResource method callback error when logicalId not set', (done) => { - // setup - const cfnClient = new CloudformationClient(TEST_CONFIGURATION); - // call - cfnClient.describeStackResource(TEST_STACK_NAME, '', (err, res) => { - // verify - expect(err).equal('Logical ID must be set to describe its resources'); - expect(res).equal(undefined); - done(); - }); - }); - - it('| describeStackResource method callback error when client request fails', (done) => { - // setup - const cfnClient = new CloudformationClient(TEST_CONFIGURATION); - describeStackResourceStub.callsArgWith(1, TEST_CLIENT_ERROR, null); - // call - cfnClient.describeStackResource(TEST_STACK_NAME, TEST_LOGICAL_ID, (err, res) => { - // verify - expect(err).equal(TEST_CLIENT_ERROR); - expect(res).equal(null); - done(); - }); - }); - - it('| describeStackResource method callback response when client request succeeds', (done) => { - // setup - const cfnClient = new CloudformationClient(TEST_CONFIGURATION); - const TEST_DESCRIBE_RESPONSE = { - StackResourceDetail: TEST_CLIENT_RESPONSE - }; - describeStackResourceStub.callsArgWith(1, null, TEST_DESCRIBE_RESPONSE); - // call - cfnClient.describeStackResource(TEST_STACK_NAME, TEST_LOGICAL_ID, (err, res) => { - // verify - expect(err).equal(null); - expect(res).equal(TEST_CLIENT_RESPONSE); - done(); - }); - }); + + it("| describeStack method callback with error when stackId not provided", (done) => { + // setup + const cfnClient = new CloudformationClient(TEST_CONFIGURATION); + // call + cfnClient.describeStack("", (err, res) => { + // verify + expect(err).equal("Stack ID must be set to further describe"); + expect(res).equal(undefined); + done(); + }); + }); + + it("| describeStack method callback with error when client request fails", (done) => { + // setup + const cfnClient = new CloudformationClient(TEST_CONFIGURATION); + describeStackStub.callsArgWith(1, TEST_CLIENT_ERROR, null); + // call + cfnClient.describeStack(TEST_STACK_NAME, (err, res) => { + // verify + expect(err).equal(TEST_CLIENT_ERROR); + expect(res).equal(null); + done(); + }); + }); + + it("| describeStack method callback with response when client request succeeds", (done) => { + // setup + const cfnClient = new CloudformationClient(TEST_CONFIGURATION); + const TEST_DESCRIBE_RESPONSE = { + Stacks: [TEST_CLIENT_RESPONSE], + }; + describeStackStub.callsArgWith(1, null, TEST_DESCRIBE_RESPONSE); + // call + cfnClient.describeStack(TEST_STACK_NAME, (err, res) => { + // verify + expect(err).equal(null); + expect(res).equal(TEST_CLIENT_RESPONSE); + done(); + }); + }); + }); + // expect(err).equal('Logical ID must be set to describe the resource') + + describe("Test client method - describeStackResource()", () => { + const TEST_STACK_NAME = "STACK"; + const TEST_LOGICAL_ID = "LOGICAL_ID"; + + it("| call aws-sdk describeStackResource method with same params from input", () => { + // setup + const cfnClient = new CloudformationClient(TEST_CONFIGURATION); + // call + cfnClient.describeStackResource(TEST_STACK_NAME, TEST_LOGICAL_ID, noop); + // verify + expect(describeStackResourceStub.args[0][0].StackName).equal(TEST_STACK_NAME); + expect(describeStackResourceStub.args[0][0].LogicalResourceId).equal(TEST_LOGICAL_ID); + }); + + it("| describeStackResource method callback error when stackId not set", (done) => { + // setup + const cfnClient = new CloudformationClient(TEST_CONFIGURATION); + // call + cfnClient.describeStackResource("", TEST_LOGICAL_ID, (err, res) => { + // verify + expect(err).equal("Stack ID must be set to describe its resources"); + expect(res).equal(undefined); + done(); + }); + }); + + it("| describeStackResource method callback error when logicalId not set", (done) => { + // setup + const cfnClient = new CloudformationClient(TEST_CONFIGURATION); + // call + cfnClient.describeStackResource(TEST_STACK_NAME, "", (err, res) => { + // verify + expect(err).equal("Logical ID must be set to describe its resources"); + expect(res).equal(undefined); + done(); + }); + }); + + it("| describeStackResource method callback error when client request fails", (done) => { + // setup + const cfnClient = new CloudformationClient(TEST_CONFIGURATION); + describeStackResourceStub.callsArgWith(1, TEST_CLIENT_ERROR, null); + // call + cfnClient.describeStackResource(TEST_STACK_NAME, TEST_LOGICAL_ID, (err, res) => { + // verify + expect(err).equal(TEST_CLIENT_ERROR); + expect(res).equal(null); + done(); + }); + }); + + it("| describeStackResource method callback response when client request succeeds", (done) => { + // setup + const cfnClient = new CloudformationClient(TEST_CONFIGURATION); + const TEST_DESCRIBE_RESPONSE = { + StackResourceDetail: TEST_CLIENT_RESPONSE, + }; + describeStackResourceStub.callsArgWith(1, null, TEST_DESCRIBE_RESPONSE); + // call + cfnClient.describeStackResource(TEST_STACK_NAME, TEST_LOGICAL_ID, (err, res) => { + // verify + expect(err).equal(null); + expect(res).equal(TEST_CLIENT_RESPONSE); + done(); + }); + }); + }); + + describe("Test client method - describeStackResources()", () => { + const TEST_STACK_NAME = "STACK"; + + it("| call aws-sdk describeStackResources method with same params from input", () => { + // setup + const cfnClient = new CloudformationClient(TEST_CONFIGURATION); + // call + cfnClient.describeStackResources(TEST_STACK_NAME, noop); + // verify + expect(describeStackResourcesStub.args[0][0].StackName).equal(TEST_STACK_NAME); + }); + + it("| describeStackResources method callback error when stackId not set", (done) => { + // setup + const cfnClient = new CloudformationClient(TEST_CONFIGURATION); + // call + cfnClient.describeStackResources("", (err, res) => { + // verify + expect(err).equal("Stack ID must be set to describe its resources"); + expect(res).equal(); + done(); + }); + }); + + it("| describeStackResources method callback error when client request fails", (done) => { + // setup + const cfnClient = new CloudformationClient(TEST_CONFIGURATION); + describeStackResourcesStub.callsArgWith(1, TEST_CLIENT_ERROR, null); + // call + cfnClient.describeStackResources(TEST_STACK_NAME, (err, res) => { + // verify + expect(err).equal(TEST_CLIENT_ERROR); + expect(res).equal(null); + done(); + }); }); - describe('Test client method - describeStackResources()', () => { - const TEST_STACK_NAME = 'STACK'; - - it('| call aws-sdk describeStackResources method with same params from input', () => { - // setup - const cfnClient = new CloudformationClient(TEST_CONFIGURATION); - // call - cfnClient.describeStackResources(TEST_STACK_NAME, noop); - // verify - expect(describeStackResourcesStub.args[0][0].StackName).equal(TEST_STACK_NAME); - }); - - it('| describeStackResources method callback error when stackId not set', (done) => { - // setup - const cfnClient = new CloudformationClient(TEST_CONFIGURATION); - // call - cfnClient.describeStackResources('', (err, res) => { - // verify - expect(err).equal('Stack ID must be set to describe its resources'); - expect(res).equal(); - done(); - }); - }); - - it('| describeStackResources method callback error when client request fails', (done) => { - // setup - const cfnClient = new CloudformationClient(TEST_CONFIGURATION); - describeStackResourcesStub.callsArgWith(1, TEST_CLIENT_ERROR, null); - // call - cfnClient.describeStackResources(TEST_STACK_NAME, (err, res) => { - // verify - expect(err).equal(TEST_CLIENT_ERROR); - expect(res).equal(null); - done(); - }); - }); - - it('| describeStackResources method callback response when client request succeeds', (done) => { - // setup - const cfnClient = new CloudformationClient(TEST_CONFIGURATION); - const TEST_DESCRIBE_RESPONSE = { - StackResources: TEST_CLIENT_RESPONSE - }; - describeStackResourcesStub.callsArgWith(1, null, TEST_DESCRIBE_RESPONSE); - // call - cfnClient.describeStackResources(TEST_STACK_NAME, (err, res) => { - // verify - expect(err).equal(null); - expect(res).equal(TEST_CLIENT_RESPONSE); - done(); - }); - }); + it("| describeStackResources method callback response when client request succeeds", (done) => { + // setup + const cfnClient = new CloudformationClient(TEST_CONFIGURATION); + const TEST_DESCRIBE_RESPONSE = { + StackResources: TEST_CLIENT_RESPONSE, + }; + describeStackResourcesStub.callsArgWith(1, null, TEST_DESCRIBE_RESPONSE); + // call + cfnClient.describeStackResources(TEST_STACK_NAME, (err, res) => { + // verify + expect(err).equal(null); + expect(res).equal(TEST_CLIENT_RESPONSE); + done(); + }); }); + }); }); diff --git a/test/unit/clients/aws-client/iam-client-test.js b/test/unit/clients/aws-client/iam-client-test.js index e6ad9e58..fc30c569 100644 --- a/test/unit/clients/aws-client/iam-client-test.js +++ b/test/unit/clients/aws-client/iam-client-test.js @@ -1,146 +1,146 @@ -const aws = require('aws-sdk'); -const { expect } = require('chai'); -const sinon = require('sinon'); +const aws = require("aws-sdk"); +const {expect} = require("chai"); +const sinon = require("sinon"); -const IAMClient = require('@src/clients/aws-client/iam-client'); +const IAMClient = require("../../../../lib/clients/aws-client/iam-client"); -describe('Clients test - iam client test', () => { - const TEST_AWS_PROFILE = 'TEST_AWS_PROFILE'; - const TEST_AWS_REGION = 'TEST_AWS_REGION'; - const TEST_CONFIGURATION = { - awsProfile: TEST_AWS_PROFILE, - awsRegion: TEST_AWS_REGION - }; - const TEST_ROLE_ARN = 'iam_role_arn'; - const TEST_ROLE_NAME = 'iam_role_name'; +describe("Clients test - iam client test", () => { + const TEST_AWS_PROFILE = "TEST_AWS_PROFILE"; + const TEST_AWS_REGION = "TEST_AWS_REGION"; + const TEST_CONFIGURATION = { + awsProfile: TEST_AWS_PROFILE, + awsRegion: TEST_AWS_REGION, + }; + const TEST_ROLE_ARN = "iam_role_arn"; + const TEST_ROLE_NAME = "iam_role_name"; - afterEach(() => { - sinon.restore(); - }); + afterEach(() => { + sinon.restore(); + }); - describe('# constructor tests', () => { - it('| inspect correctness for constructor when awsRegion is set in configuration.', () => { - const iamClient = new IAMClient(TEST_CONFIGURATION); - expect(iamClient).to.be.instanceOf(IAMClient); - expect(iamClient.awsRegion).equal(TEST_AWS_REGION); - expect(aws.config.region).equal(TEST_AWS_REGION); - expect(aws.config.credentials).deep.equal(new aws.SharedIniFileCredentials({ profile: TEST_AWS_PROFILE })); - }); + describe("# constructor tests", () => { + it("| inspect correctness for constructor when awsRegion is set in configuration.", () => { + const iamClient = new IAMClient(TEST_CONFIGURATION); + expect(iamClient).to.be.instanceOf(IAMClient); + expect(iamClient.awsRegion).equal(TEST_AWS_REGION); + expect(aws.config.region).equal(TEST_AWS_REGION); + expect(aws.config.credentials).deep.equal(new aws.SharedIniFileCredentials({profile: TEST_AWS_PROFILE})); + }); - it('| inspect an error for constructor when awsRegion is null in configuration.', () => { - const configuration = { - awsProfile: TEST_AWS_PROFILE, - awsRegion: null - }; - try { - new IAMClient(configuration); - } catch (e) { - expect(e.message).equal('Invalid awsProfile or Invalid awsRegion'); - } - }); - it('| inspect an error for constructor when awsRegion is blank in configuration.', () => { - const configuration = { - awsProfile: ' ', - awsRegion: TEST_AWS_REGION - }; - try { - new IAMClient(configuration); - } catch (e) { - expect(e.message).equal('Invalid awsProfile or Invalid awsRegion'); - } - }); + it("| inspect an error for constructor when awsRegion is null in configuration.", () => { + const configuration = { + awsProfile: TEST_AWS_PROFILE, + awsRegion: null, + }; + try { + new IAMClient(configuration); + } catch (e) { + expect(e.message).equal("Invalid awsProfile or Invalid awsRegion"); + } }); + it("| inspect an error for constructor when awsRegion is blank in configuration.", () => { + const configuration = { + awsProfile: " ", + awsRegion: TEST_AWS_REGION, + }; + try { + new IAMClient(configuration); + } catch (e) { + expect(e.message).equal("Invalid awsProfile or Invalid awsRegion"); + } + }); + }); - describe('# function getIAMRole tests', () => { - it('| iamClient get IAM role request fails, expect an error return.', (done) => { - // setup - const iamClient = new IAMClient(TEST_CONFIGURATION); - const TEST_GET_ROLE_ERR = 'GET_ROLE_ERROR'; - sinon.stub(iamClient.client, 'getRole').callsArgWith(1, TEST_GET_ROLE_ERR); - // call - iamClient.getIAMRole(TEST_ROLE_ARN, (err) => { - // verify - expect(err).equal(TEST_GET_ROLE_ERR); - done(); - }); - }); + describe("# function getIAMRole tests", () => { + it("| iamClient get IAM role request fails, expect an error return.", (done) => { + // setup + const iamClient = new IAMClient(TEST_CONFIGURATION); + const TEST_GET_ROLE_ERR = "GET_ROLE_ERROR"; + sinon.stub(iamClient.client, "getRole").callsArgWith(1, TEST_GET_ROLE_ERR); + // call + iamClient.getIAMRole(TEST_ROLE_ARN, (err) => { + // verify + expect(err).equal(TEST_GET_ROLE_ERR); + done(); + }); + }); - it('| iamClient get IAM role request passes, expect role data return.', (done) => { - // setup - const iamClient = new IAMClient(TEST_CONFIGURATION); - const TEST_GET_ROLE_RESPONSE = { - Role: { - Arn: TEST_ROLE_ARN - } - }; - sinon.stub(iamClient.client, 'getRole').callsArgWith(1, null, TEST_GET_ROLE_RESPONSE); - // call - iamClient.getIAMRole(TEST_ROLE_ARN, (err, data) => { - // verify - expect(data.Role.Arn).equal(TEST_ROLE_ARN); - expect(err).equal(null); - done(); - }); - }); + it("| iamClient get IAM role request passes, expect role data return.", (done) => { + // setup + const iamClient = new IAMClient(TEST_CONFIGURATION); + const TEST_GET_ROLE_RESPONSE = { + Role: { + Arn: TEST_ROLE_ARN, + }, + }; + sinon.stub(iamClient.client, "getRole").callsArgWith(1, null, TEST_GET_ROLE_RESPONSE); + // call + iamClient.getIAMRole(TEST_ROLE_ARN, (err, data) => { + // verify + expect(data.Role.Arn).equal(TEST_ROLE_ARN); + expect(err).equal(null); + done(); + }); }); + }); - describe('# function createBasicLambdaRole tests', () => { - it('| iamClient create basic Lambda role request fails, expect an error return.', (done) => { - // setup - const iamClient = new IAMClient(TEST_CONFIGURATION); - const TEST_CREATE_ROLE_ERR = 'CREATE_ROLE_ERROR'; - sinon.stub(iamClient.client, 'createRole').callsArgWith(1, TEST_CREATE_ROLE_ERR); - // call - iamClient.createBasicLambdaRole(TEST_ROLE_NAME, (err) => { - // verify - expect(err).equal(TEST_CREATE_ROLE_ERR); - done(); - }); - }); + describe("# function createBasicLambdaRole tests", () => { + it("| iamClient create basic Lambda role request fails, expect an error return.", (done) => { + // setup + const iamClient = new IAMClient(TEST_CONFIGURATION); + const TEST_CREATE_ROLE_ERR = "CREATE_ROLE_ERROR"; + sinon.stub(iamClient.client, "createRole").callsArgWith(1, TEST_CREATE_ROLE_ERR); + // call + iamClient.createBasicLambdaRole(TEST_ROLE_NAME, (err) => { + // verify + expect(err).equal(TEST_CREATE_ROLE_ERR); + done(); + }); + }); - it('| iamClient create basic Lambda role request passes, expect role data return.', (done) => { - // setup - const iamClient = new IAMClient(TEST_CONFIGURATION); - const TEST_CREATE_ROLE_RESPONSE = { - Role: { - Arn: TEST_ROLE_ARN - } - }; - sinon.stub(iamClient.client, 'createRole').callsArgWith(1, null, TEST_CREATE_ROLE_RESPONSE); - // call - iamClient.createBasicLambdaRole(TEST_ROLE_NAME, (err, data) => { - // verify - expect(data.Role.Arn).equal(TEST_ROLE_ARN); - expect(err).equal(null); - done(); - }); - }); + it("| iamClient create basic Lambda role request passes, expect role data return.", (done) => { + // setup + const iamClient = new IAMClient(TEST_CONFIGURATION); + const TEST_CREATE_ROLE_RESPONSE = { + Role: { + Arn: TEST_ROLE_ARN, + }, + }; + sinon.stub(iamClient.client, "createRole").callsArgWith(1, null, TEST_CREATE_ROLE_RESPONSE); + // call + iamClient.createBasicLambdaRole(TEST_ROLE_NAME, (err, data) => { + // verify + expect(data.Role.Arn).equal(TEST_ROLE_ARN); + expect(err).equal(null); + done(); + }); }); + }); - describe('# function attachBasicLambdaRolePolicy tests', () => { - it('| iamClient attach basic Lambda role policy request fails, expect an error return.', (done) => { - // setup - const iamClient = new IAMClient(TEST_CONFIGURATION); - const TEST_ATTACH_POLICY_ERR = 'ATTACH_POLICY_ERROR'; - sinon.stub(iamClient.client, 'attachRolePolicy').callsArgWith(1, TEST_ATTACH_POLICY_ERR); - // call - iamClient.attachBasicLambdaRolePolicy(TEST_ROLE_ARN, (err) => { - // verify - expect(err).equal(TEST_ATTACH_POLICY_ERR); - done(); - }); - }); + describe("# function attachBasicLambdaRolePolicy tests", () => { + it("| iamClient attach basic Lambda role policy request fails, expect an error return.", (done) => { + // setup + const iamClient = new IAMClient(TEST_CONFIGURATION); + const TEST_ATTACH_POLICY_ERR = "ATTACH_POLICY_ERROR"; + sinon.stub(iamClient.client, "attachRolePolicy").callsArgWith(1, TEST_ATTACH_POLICY_ERR); + // call + iamClient.attachBasicLambdaRolePolicy(TEST_ROLE_ARN, (err) => { + // verify + expect(err).equal(TEST_ATTACH_POLICY_ERR); + done(); + }); + }); - it('| iamClient attach basic Lambda role policy request passes, expect null error return.', (done) => { - // setup - const iamClient = new IAMClient(TEST_CONFIGURATION); - sinon.stub(iamClient.client, 'attachRolePolicy').callsArgWith(1, null); - // call - iamClient.attachBasicLambdaRolePolicy(TEST_ROLE_ARN, (err) => { - // verify - expect(err).equal(null); - done(); - }); - }); + it("| iamClient attach basic Lambda role policy request passes, expect null error return.", (done) => { + // setup + const iamClient = new IAMClient(TEST_CONFIGURATION); + sinon.stub(iamClient.client, "attachRolePolicy").callsArgWith(1, null); + // call + iamClient.attachBasicLambdaRolePolicy(TEST_ROLE_ARN, (err) => { + // verify + expect(err).equal(null); + done(); + }); }); + }); }); diff --git a/test/unit/clients/aws-client/lambda-client-test.js b/test/unit/clients/aws-client/lambda-client-test.js index 941adf6c..37e7faa4 100644 --- a/test/unit/clients/aws-client/lambda-client-test.js +++ b/test/unit/clients/aws-client/lambda-client-test.js @@ -1,236 +1,236 @@ -const aws = require('aws-sdk'); -const { expect } = require('chai'); -const sinon = require('sinon'); - -const LambdaClient = require('@src/clients/aws-client/lambda-client'); +const aws = require("aws-sdk"); +const {expect} = require("chai"); +const sinon = require("sinon"); + +const LambdaClient = require("../../../../lib/clients/aws-client/lambda-client"); + +describe("Clients test - lambda client test", () => { + const TEST_AWS_PROFILE = "TEST_AWS_PROFILE"; + const TEST_AWS_REGION = "TEST_AWS_REGION"; + const TEST_CONFIGURATION = { + awsProfile: TEST_AWS_PROFILE, + awsRegion: TEST_AWS_REGION, + }; + const TEST_FUNCTION_ARN = "function_arn"; + const TEST_SKILL_ID = "skill_id"; + const TEST_REVISION_ID = "revision_id"; + const TEST_ZIPFILE = "zipfile_path"; + const TEST_FUNCTION_NAME = "function_name"; + const TEST_FUNCTION_CONFIG = "function_config"; + + afterEach(() => { + sinon.restore(); + }); + + describe("# constructor tests", () => { + it("| inspect correctness for constructor when awsRegion is set in configuration.", () => { + const lambdaClient = new LambdaClient(TEST_CONFIGURATION); + expect(lambdaClient).to.be.instanceOf(LambdaClient); + expect(lambdaClient.awsRegion).equal(TEST_AWS_REGION); + expect(aws.config.region).equal(TEST_AWS_REGION); + expect(aws.config.credentials).deep.equal(new aws.SharedIniFileCredentials({profile: TEST_AWS_PROFILE})); + }); -describe('Clients test - lambda client test', () => { - const TEST_AWS_PROFILE = 'TEST_AWS_PROFILE'; - const TEST_AWS_REGION = 'TEST_AWS_REGION'; - const TEST_CONFIGURATION = { + it("| inspect an error for constructor when awsRegion is null in configuration.", () => { + const configuration = { awsProfile: TEST_AWS_PROFILE, - awsRegion: TEST_AWS_REGION - }; - const TEST_FUNCTION_ARN = 'function_arn'; - const TEST_SKILL_ID = 'skill_id'; - const TEST_REVISION_ID = 'revision_id'; - const TEST_ZIPFILE = 'zipfile_path'; - const TEST_FUNCTION_NAME = 'function_name'; - const TEST_FUNCTION_CONFIG = 'function_config'; - - afterEach(() => { - sinon.restore(); + awsRegion: null, + }; + try { + new LambdaClient(configuration); + } catch (e) { + expect(e.message).equal("Invalid awsProfile or Invalid awsRegion"); + } + }); + it("| inspect an error for constructor when awsRegion is blank in configuration.", () => { + const configuration = { + awsProfile: " ", + awsRegion: TEST_AWS_REGION, + }; + try { + new LambdaClient(configuration); + } catch (e) { + expect(e.message).equal("Invalid awsProfile or Invalid awsRegion"); + } + }); + }); + + describe("# function createLambdaFunction tests", () => { + const TEST_IAM_ROLE = "iam_role"; + + it("| iamClient create Lambda function request fails, expect an error return.", (done) => { + // setup + const lambdaClient = new LambdaClient(TEST_CONFIGURATION); + const TEST_CREATE_FUNCTION_ERR = "create_function_error"; + sinon.stub(lambdaClient.client, "createFunction").callsArgWith(1, TEST_CREATE_FUNCTION_ERR); + // call + lambdaClient.createLambdaFunction(TEST_FUNCTION_NAME, TEST_FUNCTION_CONFIG, TEST_IAM_ROLE, TEST_ZIPFILE, (err) => { + // verify + expect(err).equal(TEST_CREATE_FUNCTION_ERR); + done(); + }); + }); + + it("| iamClient create Lambda function request passes, expect role data return.", (done) => { + // setup + const lambdaClient = new LambdaClient(TEST_CONFIGURATION); + const TEST_CREATE_FUNCTION_RESPONSE = { + FunctionArn: TEST_FUNCTION_ARN, + }; + sinon.stub(lambdaClient.client, "createFunction").callsArgWith(1, null, TEST_CREATE_FUNCTION_RESPONSE); + // call + lambdaClient.createLambdaFunction(TEST_FUNCTION_NAME, TEST_FUNCTION_CONFIG, TEST_IAM_ROLE, TEST_ZIPFILE, (err, data) => { + // verify + expect(data.FunctionArn).equal(TEST_FUNCTION_ARN); + done(); + }); + }); + }); + + describe("# function addAlexaPermissionByDomain tests", () => { + it("| iamClient add Alexa permission by custom domain request fails, expect an error return.", (done) => { + // setup + const lambdaClient = new LambdaClient(TEST_CONFIGURATION); + const TEST_DOMAIN = "custom"; + const TEST_ADD_PERMISSION_ERR = "ADD_PERMISSION_ERROR"; + sinon.stub(lambdaClient.client, "addPermission").callsArgWith(1, TEST_ADD_PERMISSION_ERR); + // call + lambdaClient.addAlexaPermissionByDomain(TEST_DOMAIN, TEST_SKILL_ID, TEST_FUNCTION_ARN, (err) => { + // verify + expect(err).equal(TEST_ADD_PERMISSION_ERR); + done(); + }); }); - describe('# constructor tests', () => { - it('| inspect correctness for constructor when awsRegion is set in configuration.', () => { - const lambdaClient = new LambdaClient(TEST_CONFIGURATION); - expect(lambdaClient).to.be.instanceOf(LambdaClient); - expect(lambdaClient.awsRegion).equal(TEST_AWS_REGION); - expect(aws.config.region).equal(TEST_AWS_REGION); - expect(aws.config.credentials).deep.equal(new aws.SharedIniFileCredentials({ profile: TEST_AWS_PROFILE })); - }); - - it('| inspect an error for constructor when awsRegion is null in configuration.', () => { - const configuration = { - awsProfile: TEST_AWS_PROFILE, - awsRegion: null - }; - try { - new LambdaClient(configuration); - } catch (e) { - expect(e.message).equal('Invalid awsProfile or Invalid awsRegion'); - } - }); - it('| inspect an error for constructor when awsRegion is blank in configuration.', () => { - const configuration = { - awsProfile: ' ', - awsRegion: TEST_AWS_REGION - }; - try { - new LambdaClient(configuration); - } catch (e) { - expect(e.message).equal('Invalid awsProfile or Invalid awsRegion'); - } - }); + it("| iamClient add Alexa permission by smartHome domain request fails, expect an error return.", (done) => { + // setup + const lambdaClient = new LambdaClient(TEST_CONFIGURATION); + const TEST_DOMAIN = "smartHome"; + const TEST_ADD_PERMISSION_ERR = "ADD_PERMISSION_ERROR"; + sinon.stub(lambdaClient.client, "addPermission").callsArgWith(1, TEST_ADD_PERMISSION_ERR); + // call + lambdaClient.addAlexaPermissionByDomain(TEST_DOMAIN, TEST_SKILL_ID, TEST_FUNCTION_ARN, (err) => { + // verify + expect(err).equal(TEST_ADD_PERMISSION_ERR); + done(); + }); }); - describe('# function createLambdaFunction tests', () => { - const TEST_IAM_ROLE = 'iam_role'; - - it('| iamClient create Lambda function request fails, expect an error return.', (done) => { - // setup - const lambdaClient = new LambdaClient(TEST_CONFIGURATION); - const TEST_CREATE_FUNCTION_ERR = 'create_function_error'; - sinon.stub(lambdaClient.client, 'createFunction').callsArgWith(1, TEST_CREATE_FUNCTION_ERR); - // call - lambdaClient.createLambdaFunction(TEST_FUNCTION_NAME, TEST_FUNCTION_CONFIG, TEST_IAM_ROLE, TEST_ZIPFILE, (err) => { - // verify - expect(err).equal(TEST_CREATE_FUNCTION_ERR); - done(); - }); - }); - - it('| iamClient create Lambda function request passes, expect role data return.', (done) => { - // setup - const lambdaClient = new LambdaClient(TEST_CONFIGURATION); - const TEST_CREATE_FUNCTION_RESPONSE = { - FunctionArn: TEST_FUNCTION_ARN - }; - sinon.stub(lambdaClient.client, 'createFunction').callsArgWith(1, null, TEST_CREATE_FUNCTION_RESPONSE); - // call - lambdaClient.createLambdaFunction(TEST_FUNCTION_NAME, TEST_FUNCTION_CONFIG, TEST_IAM_ROLE, TEST_ZIPFILE, (err, data) => { - // verify - expect(data.FunctionArn).equal(TEST_FUNCTION_ARN); - done(); - }); - }); + it("| iamClient add Alexa permission by domain request passes, expect null error return.", (done) => { + // setup + const lambdaClient = new LambdaClient(TEST_CONFIGURATION); + const TEST_DOMAIN = "video"; + sinon.stub(lambdaClient.client, "addPermission").callsArgWith(1, null); + // call + lambdaClient.addAlexaPermissionByDomain(TEST_DOMAIN, TEST_SKILL_ID, TEST_FUNCTION_ARN, (err) => { + // verify + expect(err).equal(null); + done(); + }); }); - describe('# function addAlexaPermissionByDomain tests', () => { - it('| iamClient add Alexa permission by custom domain request fails, expect an error return.', (done) => { - // setup - const lambdaClient = new LambdaClient(TEST_CONFIGURATION); - const TEST_DOMAIN = 'custom'; - const TEST_ADD_PERMISSION_ERR = 'ADD_PERMISSION_ERROR'; - sinon.stub(lambdaClient.client, 'addPermission').callsArgWith(1, TEST_ADD_PERMISSION_ERR); - // call - lambdaClient.addAlexaPermissionByDomain(TEST_DOMAIN, TEST_SKILL_ID, TEST_FUNCTION_ARN, (err) => { - // verify - expect(err).equal(TEST_ADD_PERMISSION_ERR); - done(); - }); - }); - - it('| iamClient add Alexa permission by smartHome domain request fails, expect an error return.', (done) => { - // setup - const lambdaClient = new LambdaClient(TEST_CONFIGURATION); - const TEST_DOMAIN = 'smartHome'; - const TEST_ADD_PERMISSION_ERR = 'ADD_PERMISSION_ERROR'; - sinon.stub(lambdaClient.client, 'addPermission').callsArgWith(1, TEST_ADD_PERMISSION_ERR); - // call - lambdaClient.addAlexaPermissionByDomain(TEST_DOMAIN, TEST_SKILL_ID, TEST_FUNCTION_ARN, (err) => { - // verify - expect(err).equal(TEST_ADD_PERMISSION_ERR); - done(); - }); - }); - - it('| iamClient add Alexa permission by domain request passes, expect null error return.', (done) => { - // setup - const lambdaClient = new LambdaClient(TEST_CONFIGURATION); - const TEST_DOMAIN = 'video'; - sinon.stub(lambdaClient.client, 'addPermission').callsArgWith(1, null); - // call - lambdaClient.addAlexaPermissionByDomain(TEST_DOMAIN, TEST_SKILL_ID, TEST_FUNCTION_ARN, (err) => { - // verify - expect(err).equal(null); - done(); - }); - }); - - it('| iamClient add Alexa permission by domain no permission needed for domain, expect undefined return.', (done) => { - // setup - const lambdaClient = new LambdaClient(TEST_CONFIGURATION); - const TEST_DOMAIN = 'non-existing'; - // call - lambdaClient.addAlexaPermissionByDomain(TEST_DOMAIN, TEST_SKILL_ID, TEST_FUNCTION_ARN, (err) => { - // verify - expect(err).equal(undefined); - done(); - }); - }); + it("| iamClient add Alexa permission by domain no permission needed for domain, expect undefined return.", (done) => { + // setup + const lambdaClient = new LambdaClient(TEST_CONFIGURATION); + const TEST_DOMAIN = "non-existing"; + // call + lambdaClient.addAlexaPermissionByDomain(TEST_DOMAIN, TEST_SKILL_ID, TEST_FUNCTION_ARN, (err) => { + // verify + expect(err).equal(undefined); + done(); + }); + }); + }); + + describe("# function getFunction tests", () => { + it("| iamClient get Function request fails, expect an error return.", (done) => { + // setup + const lambdaClient = new LambdaClient(TEST_CONFIGURATION); + const TEST_GET_FUNCTION_ERR = "GET_FUNCTION_ERROR"; + sinon.stub(lambdaClient.client, "getFunction").callsArgWith(1, TEST_GET_FUNCTION_ERR); + // call + lambdaClient.getFunction(TEST_FUNCTION_ARN, (err) => { + // verify + expect(err).equal(TEST_GET_FUNCTION_ERR); + done(); + }); }); - describe('# function getFunction tests', () => { - it('| iamClient get Function request fails, expect an error return.', (done) => { - // setup - const lambdaClient = new LambdaClient(TEST_CONFIGURATION); - const TEST_GET_FUNCTION_ERR = 'GET_FUNCTION_ERROR'; - sinon.stub(lambdaClient.client, 'getFunction').callsArgWith(1, TEST_GET_FUNCTION_ERR); - // call - lambdaClient.getFunction(TEST_FUNCTION_ARN, (err) => { - // verify - expect(err).equal(TEST_GET_FUNCTION_ERR); - done(); - }); - }); - - it('| iamClient get Function request passes, expect a revision id return.', (done) => { - // setup - const lambdaClient = new LambdaClient(TEST_CONFIGURATION); - const TEST_GET_FUNCTION_RESPONSE = { - Configuration: { - RevisionId: TEST_REVISION_ID - } - }; - sinon.stub(lambdaClient.client, 'getFunction').callsArgWith(1, null, TEST_GET_FUNCTION_RESPONSE); - // call - lambdaClient.getFunction(TEST_FUNCTION_ARN, (err, data) => { - // verify - expect(data.Configuration.RevisionId).equal(TEST_REVISION_ID); - done(); - }); - }); + it("| iamClient get Function request passes, expect a revision id return.", (done) => { + // setup + const lambdaClient = new LambdaClient(TEST_CONFIGURATION); + const TEST_GET_FUNCTION_RESPONSE = { + Configuration: { + RevisionId: TEST_REVISION_ID, + }, + }; + sinon.stub(lambdaClient.client, "getFunction").callsArgWith(1, null, TEST_GET_FUNCTION_RESPONSE); + // call + lambdaClient.getFunction(TEST_FUNCTION_ARN, (err, data) => { + // verify + expect(data.Configuration.RevisionId).equal(TEST_REVISION_ID); + done(); + }); + }); + }); + + describe("# function updateFunctionCode tests", () => { + it("| iamClient update function code request fails, expect an error return.", (done) => { + // setup + const lambdaClient = new LambdaClient(TEST_CONFIGURATION); + const TEST_UPDATE_CODE_ERR = "UPDATE_CODE_ERROR"; + sinon.stub(lambdaClient.client, "updateFunctionCode").callsArgWith(1, TEST_UPDATE_CODE_ERR); + // call + lambdaClient.updateFunctionCode(TEST_ZIPFILE, TEST_FUNCTION_ARN, TEST_REVISION_ID, (err) => { + // verify + expect(err).equal(TEST_UPDATE_CODE_ERR); + done(); + }); }); - describe('# function updateFunctionCode tests', () => { - it('| iamClient update function code request fails, expect an error return.', (done) => { - // setup - const lambdaClient = new LambdaClient(TEST_CONFIGURATION); - const TEST_UPDATE_CODE_ERR = 'UPDATE_CODE_ERROR'; - sinon.stub(lambdaClient.client, 'updateFunctionCode').callsArgWith(1, TEST_UPDATE_CODE_ERR); - // call - lambdaClient.updateFunctionCode(TEST_ZIPFILE, TEST_FUNCTION_ARN, TEST_REVISION_ID, (err) => { - // verify - expect(err).equal(TEST_UPDATE_CODE_ERR); - done(); - }); - }); - - it('| iamClient update function code request passes, expect function data return.', (done) => { - // setup - const lambdaClient = new LambdaClient(TEST_CONFIGURATION); - const TEST_UPDATE_CODE_RESPONSE = { - FunctionArn: TEST_FUNCTION_ARN - }; - sinon.stub(lambdaClient.client, 'updateFunctionCode').callsArgWith(1, null, TEST_UPDATE_CODE_RESPONSE); - // call - lambdaClient.updateFunctionCode(TEST_ZIPFILE, TEST_FUNCTION_ARN, TEST_REVISION_ID, (err, data) => { - // verify - expect(data.FunctionArn).equal(TEST_FUNCTION_ARN); - done(); - }); - }); + it("| iamClient update function code request passes, expect function data return.", (done) => { + // setup + const lambdaClient = new LambdaClient(TEST_CONFIGURATION); + const TEST_UPDATE_CODE_RESPONSE = { + FunctionArn: TEST_FUNCTION_ARN, + }; + sinon.stub(lambdaClient.client, "updateFunctionCode").callsArgWith(1, null, TEST_UPDATE_CODE_RESPONSE); + // call + lambdaClient.updateFunctionCode(TEST_ZIPFILE, TEST_FUNCTION_ARN, TEST_REVISION_ID, (err, data) => { + // verify + expect(data.FunctionArn).equal(TEST_FUNCTION_ARN); + done(); + }); + }); + }); + + describe("# function update function configuration tests", () => { + it("| iamClient update function configuration request fails, expect an error return.", (done) => { + // setup + const lambdaClient = new LambdaClient(TEST_CONFIGURATION); + const TEST_UPDATE_CONFIG_ERR = "UPDATE_CONFIG_ERROR"; + sinon.stub(lambdaClient.client, "updateFunctionConfiguration").callsArgWith(1, TEST_UPDATE_CONFIG_ERR); + // call + lambdaClient.updateFunctionConfiguration(TEST_FUNCTION_ARN, TEST_FUNCTION_CONFIG, TEST_REVISION_ID, (err) => { + // verify + expect(err).equal(TEST_UPDATE_CONFIG_ERR); + done(); + }); }); - describe('# function update function configuration tests', () => { - it('| iamClient update function configuration request fails, expect an error return.', (done) => { - // setup - const lambdaClient = new LambdaClient(TEST_CONFIGURATION); - const TEST_UPDATE_CONFIG_ERR = 'UPDATE_CONFIG_ERROR'; - sinon.stub(lambdaClient.client, 'updateFunctionConfiguration').callsArgWith(1, TEST_UPDATE_CONFIG_ERR); - // call - lambdaClient.updateFunctionConfiguration(TEST_FUNCTION_ARN, TEST_FUNCTION_CONFIG, TEST_REVISION_ID, (err) => { - // verify - expect(err).equal(TEST_UPDATE_CONFIG_ERR); - done(); - }); - }); - - it('| iamClient update function configuration request passes, expect null error return.', (done) => { - // setup - const lambdaClient = new LambdaClient(TEST_CONFIGURATION); - const TEST_UPDATE_CONFIG_RESPONSE = { - RevisionId: TEST_REVISION_ID - }; - sinon.stub(lambdaClient.client, 'updateFunctionConfiguration').callsArgWith(1, null, TEST_UPDATE_CONFIG_RESPONSE); - // call - lambdaClient.updateFunctionConfiguration(TEST_FUNCTION_ARN, TEST_FUNCTION_CONFIG, TEST_REVISION_ID, (err, data) => { - // verify - expect(data.RevisionId).equal(TEST_REVISION_ID); - done(); - }); - }); + it("| iamClient update function configuration request passes, expect null error return.", (done) => { + // setup + const lambdaClient = new LambdaClient(TEST_CONFIGURATION); + const TEST_UPDATE_CONFIG_RESPONSE = { + RevisionId: TEST_REVISION_ID, + }; + sinon.stub(lambdaClient.client, "updateFunctionConfiguration").callsArgWith(1, null, TEST_UPDATE_CONFIG_RESPONSE); + // call + lambdaClient.updateFunctionConfiguration(TEST_FUNCTION_ARN, TEST_FUNCTION_CONFIG, TEST_REVISION_ID, (err, data) => { + // verify + expect(data.RevisionId).equal(TEST_REVISION_ID); + done(); + }); }); + }); }); diff --git a/test/unit/clients/aws-client/s3-client-test.js b/test/unit/clients/aws-client/s3-client-test.js index f09e132c..421e33ea 100644 --- a/test/unit/clients/aws-client/s3-client-test.js +++ b/test/unit/clients/aws-client/s3-client-test.js @@ -1,590 +1,623 @@ -const { expect } = require('chai'); -const sinon = require('sinon'); -const aws = require('aws-sdk'); -const path = require('path'); -const proxyquire = require('proxyquire'); -const fs = require('fs'); - -const S3Client = require('@src/clients/aws-client/s3-client'); - -describe('Clients test - s3 client test', () => { - const TEST_AWS_PROFILE = 'TEST_AWS_PROFILE'; - const TEST_AWS_REGION = 'TEST_AWS_REGION'; - const TEST_CONFIGURATION = { - awsProfile: TEST_AWS_PROFILE, - awsRegion: TEST_AWS_REGION - }; - const TEST_BUCKET_NAME = 'BUCKET_NAME'; - const TEST_BUCKET_KEY = 'BUCKET_KEY'; - const TEST_BUCKET_BODY = 'BUCKET_BODY'; - const TEST_HEAD_ERROR = 'HEAD_ERROR'; - const TEST_CREATE_ERROR = 'HEAD_ERROR'; - const TEST_PUTVERSION_ERROR = 'HEAD_ERROR'; - const TEST_WAITFOR_ERROR = 'WAITFOR_ERROR'; - const TEST_PUTOBJECT_ERROR = 'PUTOBJECT_ERROR'; - const TEST_GETVERSION_ERROR = 'GETVERSION_ERROR'; - const TEST_RESPONSE = 'RESPONSE'; - - describe('# constructor tests', () => { - it('| inspect correctness for constructor when awsRegion is set in configuration', () => { - const s3Client = new S3Client(TEST_CONFIGURATION); - expect(s3Client).to.be.instanceof(S3Client); - expect(s3Client.awsRegion).equal(TEST_AWS_REGION); - expect(aws.config.region).equal(TEST_AWS_REGION); - expect(aws.config.credentials).deep.equal(new aws.SharedIniFileCredentials({ profile: TEST_AWS_PROFILE })); - }); - - it('| inspect correctness for constructor when awsRegion is null in configuration', () => { - const configuration = { - awsProfile: TEST_AWS_PROFILE, - awsRegion: null - }; - try { - new S3Client(configuration); - } catch (e) { - expect(e.message).equal('Invalid awsProfile or Invalid awsRegion'); - } - }); - - it('| inspect correctness for constructor when awsProfile is blank in configuration', () => { - const configuration = { - awsProfile: ' ', - awsRegion: TEST_AWS_REGION - }; - try { - new S3Client(configuration); - } catch (e) { - expect(e.message).equal('Invalid awsProfile or Invalid awsRegion'); - } - }); +const {expect} = require("chai"); +const sinon = require("sinon"); +const aws = require("aws-sdk"); +const path = require("path"); +const proxyquire = require("proxyquire"); +const fs = require("fs"); + +const S3Client = require("../../../../lib/clients/aws-client/s3-client"); + +describe("Clients test - s3 client test", () => { + const TEST_AWS_PROFILE = "TEST_AWS_PROFILE"; + const TEST_AWS_REGION = "TEST_AWS_REGION"; + const TEST_CONFIGURATION = { + awsProfile: TEST_AWS_PROFILE, + awsRegion: TEST_AWS_REGION, + }; + const TEST_BUCKET_NAME = "BUCKET_NAME"; + const TEST_BUCKET_KEY = "BUCKET_KEY"; + const TEST_BUCKET_BODY = "BUCKET_BODY"; + const TEST_HEAD_ERROR = "HEAD_ERROR"; + const TEST_CREATE_ERROR = "HEAD_ERROR"; + const TEST_PUTVERSION_ERROR = "HEAD_ERROR"; + const TEST_WAITFOR_ERROR = "WAITFOR_ERROR"; + const TEST_PUTOBJECT_ERROR = "PUTOBJECT_ERROR"; + const TEST_GETVERSION_ERROR = "GETVERSION_ERROR"; + const TEST_RESPONSE = "RESPONSE"; + + describe("# constructor tests", () => { + it("| inspect correctness for constructor when awsRegion is set in configuration", () => { + const s3Client = new S3Client(TEST_CONFIGURATION); + expect(s3Client).to.be.instanceof(S3Client); + expect(s3Client.awsRegion).equal(TEST_AWS_REGION); + expect(aws.config.region).equal(TEST_AWS_REGION); + expect(aws.config.credentials).deep.equal(new aws.SharedIniFileCredentials({profile: TEST_AWS_PROFILE})); }); - describe('# function preSignedPutObject tests', () => { - let proxyClient; - let stubRequest; - let putStub; - const TEST_OPTION = {}; - beforeEach(() => { - putStub = sinon.stub(); - stubRequest = { - put: putStub - }; - proxyClient = proxyquire('@src/clients/aws-client/s3-client', { - request: stubRequest - }); - }); - - afterEach(() => { - sinon.restore(); - }); - - it('| input pre-signed S3 url is not string, expect error thrown ', (done) => { - // setup - const TEST_URL = {}; - // call - proxyClient.preSignedPutObject(TEST_URL, TEST_OPTION, (err) => { - // verify - expect(err).equal('[Error]: The url for the S3 presigned URL upload must not be blank.'); - done(); - }); - }); - - it('| input pre-signed S3 url is empty sting, expect error thrown ', (done) => { - // setup - const TEST_URL = ''; - // call - proxyClient.preSignedPutObject(TEST_URL, TEST_OPTION, (err) => { - // verify - expect(err).equal('[Error]: The url for the S3 presigned URL upload must not be blank.'); - done(); - }); - }); - - it('| input pre-signed S3 url is empty, expect error thrown ', (done) => { - // setup - const TEST_URL = 'pre-signed_S3_url'; - putStub.callsArgWith(2, null); - // call - proxyClient.preSignedPutObject(TEST_URL, TEST_OPTION, (err) => { - // verify - expect(err).equal(null); - done(); - }); - }); + it("| inspect correctness for constructor when awsRegion is null in configuration", () => { + const configuration = { + awsProfile: TEST_AWS_PROFILE, + awsRegion: null, + }; + try { + new S3Client(configuration); + } catch (e) { + expect(e.message).equal("Invalid awsProfile or Invalid awsRegion"); + } }); - describe('# function putObject tests', () => { - it('| s3Client putObject method correctly pass params to S3 pubObject method, and callback error when pubObject callback error', (done) => { - // setup - const s3Client = new S3Client(TEST_CONFIGURATION); - const expectedParams = { - Body: TEST_BUCKET_BODY, - Bucket: TEST_BUCKET_NAME, - Key: TEST_BUCKET_KEY - }; - sinon.stub(s3Client.client, 'putObject').withArgs(expectedParams, sinon.match.func).callsArgWith(1, TEST_PUTOBJECT_ERROR); - // call - s3Client.putObject(TEST_BUCKET_NAME, TEST_BUCKET_KEY, TEST_BUCKET_BODY, (err, response) => { - // verify - expect(s3Client.client.putObject.args[0][0]).deep.equal(expectedParams); - expect(err).equal(TEST_PUTOBJECT_ERROR); - expect(response).equal(null); - done(); - }); - }); - - it('| s3Client putObject method correctly pass params to S3 pubObject method, and callback response when S3 pubObject succeed', (done) => { - // setup - const s3Client = new S3Client(TEST_CONFIGURATION); - const expectedParams = { - Body: TEST_BUCKET_BODY, - Bucket: TEST_BUCKET_NAME, - Key: TEST_BUCKET_KEY - }; - sinon.stub(s3Client.client, 'putObject').withArgs(expectedParams, sinon.match.func).callsArgWith(1, null, TEST_RESPONSE); - // call - s3Client.putObject(TEST_BUCKET_NAME, TEST_BUCKET_KEY, TEST_BUCKET_BODY, (error, response) => { - // verify - expect(s3Client.client.putObject.args[0][0]).deep.equal(expectedParams); - expect(error).equal(null); - expect(response).equal(TEST_RESPONSE); - done(); - }); - }); + it("| inspect correctness for constructor when awsProfile is blank in configuration", () => { + const configuration = { + awsProfile: " ", + awsRegion: TEST_AWS_REGION, + }; + try { + new S3Client(configuration); + } catch (e) { + expect(e.message).equal("Invalid awsProfile or Invalid awsRegion"); + } }); - - describe('# function waitForBucketExists tests', () => { - it('| s3Client waitfor bucketExists event and s3client request fails, expect error callback', (done) => { - // setup - const s3Client = new S3Client(TEST_CONFIGURATION); - const expectedParams = { - Bucket: TEST_BUCKET_NAME - }; - sinon.stub(s3Client.client, 'waitFor').withArgs('bucketExists', expectedParams, sinon.match.func).callsArgWith(2, TEST_WAITFOR_ERROR); - // call - s3Client.waitForBucketExists(TEST_BUCKET_NAME, (error, response) => { - // verify - expect(error).equal(TEST_WAITFOR_ERROR); - expect(response).equal(null); - done(); - }); - }); - - it('| s3Client waitfor bucketExists event and s3client request pass, expect callback response', (done) => { - // setup - const s3Client = new S3Client(TEST_CONFIGURATION); - const expectedParams = { - Bucket: TEST_BUCKET_NAME - }; - sinon.stub(s3Client.client, 'waitFor').withArgs('bucketExists', expectedParams, sinon.match.func).callsArgWith(2, null, TEST_RESPONSE); - // call - s3Client.waitForBucketExists(TEST_BUCKET_NAME, (error, response) => { - // verify - expect(error).equal(null); - expect(response).equal(TEST_RESPONSE); - done(); - }); - }); + }); + + describe("# function preSignedPutObject tests", () => { + let proxyClient; + let stubRequest; + let putStub; + const TEST_OPTION = {}; + beforeEach(() => { + putStub = sinon.stub(); + stubRequest = { + put: putStub, + }; + proxyClient = proxyquire("../../../../lib/clients/aws-client/s3-client", { + request: stubRequest, + }); }); - // TODO fix the unit test of this function - describe.skip('# function putBucketVersioning tests', () => { - it('| s3Client putBucketVersioning method correctly pass params to S3 putBucketVersioning method, ' - + 'and callback error when S3 pubBucketVersioning callback error', (done) => { - // setup - const s3Client = new S3Client(TEST_CONFIGURATION); - const MFADelete = 'Disabled'; - const Status = 'Enabled'; - const expectedParams = { - Bucket: TEST_BUCKET_NAME, - VersioningConfiguration: { - MFADelete, - Status - } - }; - sinon.stub(s3Client.client, 'putBucketVersioning').withArgs(expectedParams, sinon.match.func).callsArgWith(1, TEST_PUTVERSION_ERROR); - // call - s3Client.putBucketVersioning(TEST_BUCKET_NAME, MFADelete, Status, (error, response) => { - // verify - expect(s3Client.client.putBucketVersioning.args[0][0]).deep.equal(expectedParams); - expect(error).equal(TEST_PUTVERSION_ERROR); - expect(response).equal(null); - done(); - }); - }); - - it('| s3Client putBucketVersioning method can correctly pass params to aws S3 putBucketVersioning method, ' - + 'and callback response when S3 putBucketVersioning is executed correctly', (done) => { - // setup - const s3Client = new S3Client(TEST_CONFIGURATION); - const expectedParams = { - Bucket: TEST_BUCKET_NAME, - VersioningConfiguration: { - MFADelete: 'Disabled', - Status: 'Enabled' - } - }; - sinon.stub(s3Client.client, 'putBucketVersioning').withArgs(expectedParams, sinon.match.func).callsArgWith(1, null, TEST_RESPONSE); - // call - s3Client.putBucketVersioning(TEST_BUCKET_NAME, 'Disabled', 'Enabled', (error, response) => { - // verify - expect(s3Client.client.putBucketVersioning.args[0][0]).deep.equal(expectedParams); - expect(error).equal(null); - expect(response).equal(TEST_RESPONSE); - done(); - }); - }); + afterEach(() => { + sinon.restore(); }); - describe('# function createBucket tests', () => { - it('| s3Client createBucket method can correctly pass params to aws S3 createBucket method when region is us-east-1, ' - + 'and callback error when S3 createBucket callback error', (done) => { - // setup - const s3Client = new S3Client(TEST_CONFIGURATION); - const expectedParams = { - Bucket: TEST_BUCKET_NAME - }; - sinon.stub(s3Client.client, 'createBucket').withArgs(expectedParams, sinon.match.func).callsArgWith(1, TEST_CREATE_ERROR); - // call - s3Client.createBucket(TEST_BUCKET_NAME, 'us-east-1', (error, response) => { - // verify - expect(s3Client.client.createBucket.args[0][0]).deep.equal(expectedParams); - expect(error).equal(TEST_CREATE_ERROR); - expect(response).equal(null); - done(); - }); - }); - - it('| s3Client createBucket method can correctly pass params to aws S3 createBucket method when region is not us-east-1,' - + ' and callback response when S3 createBucket is executed correctly', (done) => { - // setup - const s3Client = new S3Client(TEST_CONFIGURATION); - const expectedParams = { - Bucket: TEST_BUCKET_NAME, - CreateBucketConfiguration: { - LocationConstraint: TEST_AWS_REGION - } - }; - sinon.stub(s3Client.client, 'createBucket').withArgs(expectedParams, sinon.match.func).callsArgWith(1, null, TEST_RESPONSE); - // call - s3Client.createBucket(TEST_BUCKET_NAME, TEST_AWS_REGION, (error, response) => { - // verify - expect(s3Client.client.createBucket.args[0][0]).deep.equal(expectedParams); - expect(error).equal(null); - expect(response).equal(TEST_RESPONSE); - done(); - }); - }); + it("| input pre-signed S3 url is not string, expect error thrown ", (done) => { + // setup + const TEST_URL = {}; + // call + proxyClient.preSignedPutObject(TEST_URL, TEST_OPTION, (err) => { + // verify + expect(err).equal("[Error]: The url for the S3 presigned URL upload must not be blank."); + done(); + }); }); - describe('# function headBucket tests', () => { - it('| s3Client headBucket method can correctly pass params to aws S3 headBucket method, ' - + 'and callback error when S3 headBucket callback error', (done) => { - // setup - const s3Client = new S3Client(TEST_CONFIGURATION); - const expectedParams = { - Bucket: TEST_BUCKET_NAME - }; - sinon.stub(s3Client.client, 'headBucket').withArgs(expectedParams, sinon.match.func).callsArgWith(1, TEST_HEAD_ERROR); - // call - s3Client.headBucket(TEST_BUCKET_NAME, (error, response) => { - // verify - expect(s3Client.client.headBucket.args[0][0]).deep.equal(expectedParams); - expect(error).equal(TEST_HEAD_ERROR); - expect(response).equal(null); - done(); - }); - }); - - it('| s3Client headBucket method can correctly pass params to aws S3 headBucket method, ' - + 'and callback response when S3 headBucket is executed correctly', (done) => { - // setup - const s3Client = new S3Client(TEST_CONFIGURATION); - const expectedParams = { - Bucket: TEST_BUCKET_NAME - }; - sinon.stub(s3Client.client, 'headBucket').withArgs(expectedParams, sinon.match.func).callsArgWith(1, null, TEST_RESPONSE); - // call - s3Client.headBucket(TEST_BUCKET_NAME, (error, response) => { - // verify - expect(s3Client.client.headBucket.args[0][0]).deep.equal(expectedParams); - expect(error).equal(null); - expect(response).equal(TEST_RESPONSE); - done(); - }); - }); + it("| input pre-signed S3 url is empty sting, expect error thrown ", (done) => { + // setup + const TEST_URL = ""; + // call + proxyClient.preSignedPutObject(TEST_URL, TEST_OPTION, (err) => { + // verify + expect(err).equal("[Error]: The url for the S3 presigned URL upload must not be blank."); + done(); + }); }); - // TODO fix the unit test of this function - describe.skip('# function getBucketVersioning tests', () => { - it('| s3Client getBucketVersioning method, can correctly pass params to aws S3 getBucketVersioning method, ' - + 'and callback error when S3 getBucketVersioning callback error ', (done) => { - // setup - const s3Client = new S3Client(TEST_CONFIGURATION); - const expectedParams = { - Bucket: TEST_BUCKET_NAME - }; - sinon.stub(s3Client.client, 'getBucketVersioning').withArgs(expectedParams, sinon.match.func).callsArgWith(1, TEST_GETVERSION_ERROR); - // call - s3Client.getBucketVersioning(TEST_BUCKET_NAME, (error, response) => { - // verify - expect(s3Client.client.getBucketVersioning.args[0][0]).deep.equal(expectedParams); - expect(error).equal(TEST_GETVERSION_ERROR); - expect(response).equal(null); - done(); - }); - }); + it("| input pre-signed S3 url is empty, expect error thrown ", (done) => { + // setup + const TEST_URL = "pre-signed_S3_url"; + putStub.callsArgWith(2, null); + // call + proxyClient.preSignedPutObject(TEST_URL, TEST_OPTION, (err) => { + // verify + expect(err).equal(null); + done(); + }); + }); + }); + + describe("# function putObject tests", () => { + it("| s3Client putObject method correctly pass params to S3 pubObject method, and callback error when pubObject callback error", (done) => { + // setup + const s3Client = new S3Client(TEST_CONFIGURATION); + const expectedParams = { + Body: TEST_BUCKET_BODY, + Bucket: TEST_BUCKET_NAME, + Key: TEST_BUCKET_KEY, + }; + sinon.stub(s3Client.client, "putObject").withArgs(expectedParams, sinon.match.func).callsArgWith(1, TEST_PUTOBJECT_ERROR); + // call + s3Client.putObject(TEST_BUCKET_NAME, TEST_BUCKET_KEY, TEST_BUCKET_BODY, (err, response) => { + // verify + expect(s3Client.client.putObject.args[0][0]).deep.equal(expectedParams); + expect(err).equal(TEST_PUTOBJECT_ERROR); + expect(response).equal(null); + done(); + }); + }); - it('| s3Client getBucketVersioning method, can correctly pass params to aws S3 getBucketVersioning method, ' - + 'and callback response when S3 getBucketVersioning is executed correctly', (done) => { - // setup - const s3Client = new S3Client(TEST_CONFIGURATION); - const expectedParams = { - Bucket: TEST_BUCKET_NAME - }; - sinon.stub(s3Client.client, 'getBucketVersioning').withArgs(expectedParams, sinon.match.func).callsArgWith(1, null, TEST_RESPONSE); - // call - s3Client.getBucketVersioning(TEST_BUCKET_NAME, (error, response) => { - // verify - expect(s3Client.client.getBucketVersioning.args[0][0]).deep.equal(expectedParams); - expect(error).equal(null); - expect(response).equal(TEST_RESPONSE); - done(); - }); - }); + it("| s3Client putObject method correctly pass params to S3 pubObject method, and callback response when S3 pubObject succeed", (done) => { + // setup + const s3Client = new S3Client(TEST_CONFIGURATION); + const expectedParams = { + Body: TEST_BUCKET_BODY, + Bucket: TEST_BUCKET_NAME, + Key: TEST_BUCKET_KEY, + }; + sinon.stub(s3Client.client, "putObject").withArgs(expectedParams, sinon.match.func).callsArgWith(1, null, TEST_RESPONSE); + // call + s3Client.putObject(TEST_BUCKET_NAME, TEST_BUCKET_KEY, TEST_BUCKET_BODY, (error, response) => { + // verify + expect(s3Client.client.putObject.args[0][0]).deep.equal(expectedParams); + expect(error).equal(null); + expect(response).equal(TEST_RESPONSE); + done(); + }); + }); + }); + + describe("# function waitForBucketExists tests", () => { + it("| s3Client waitfor bucketExists event and s3client request fails, expect error callback", (done) => { + // setup + const s3Client = new S3Client(TEST_CONFIGURATION); + const expectedParams = { + Bucket: TEST_BUCKET_NAME, + }; + sinon.stub(s3Client.client, "waitFor").withArgs("bucketExists", expectedParams, sinon.match.func).callsArgWith(2, TEST_WAITFOR_ERROR); + // call + s3Client.waitForBucketExists(TEST_BUCKET_NAME, (error, response) => { + // verify + expect(error).equal(TEST_WAITFOR_ERROR); + expect(response).equal(null); + done(); + }); }); - describe('# function createBucketIfNotExist tests', () => { + it("| s3Client waitfor bucketExists event and s3client request pass, expect callback response", (done) => { + // setup + const s3Client = new S3Client(TEST_CONFIGURATION); + const expectedParams = { + Bucket: TEST_BUCKET_NAME, + }; + sinon + .stub(s3Client.client, "waitFor") + .withArgs("bucketExists", expectedParams, sinon.match.func) + .callsArgWith(2, null, TEST_RESPONSE); + // call + s3Client.waitForBucketExists(TEST_BUCKET_NAME, (error, response) => { + // verify + expect(error).equal(null); + expect(response).equal(TEST_RESPONSE); + done(); + }); + }); + }); + + // TODO fix the unit test of this function + describe.skip("# function putBucketVersioning tests", () => { + it( + "| s3Client putBucketVersioning method correctly pass params to S3 putBucketVersioning method, " + + "and callback error when S3 pubBucketVersioning callback error", + (done) => { + // setup const s3Client = new S3Client(TEST_CONFIGURATION); - it('| when headBucket return error, provisionBucket can correctly callback error message', (done) => { - // setup - sinon.stub(s3Client, 'headBucket').callsArgWith(1, TEST_HEAD_ERROR); - - // call - s3Client.createBucketIfNotExist(TEST_BUCKET_NAME, TEST_AWS_REGION, (error) => { - // verify - expect(error).equal(TEST_HEAD_ERROR); - done(); - }); - }); - - it('| when headBucket return response without error, directly callback with no argument', (done) => { - // setup - sinon.stub(s3Client, 'headBucket').callsArgWith(1, null, TEST_RESPONSE); - sinon.stub(s3Client, 'createBucket'); - sinon.stub(s3Client, 'putBucketVersioningIfUninitialized'); - // call - s3Client.createBucketIfNotExist(TEST_BUCKET_NAME, TEST_AWS_REGION, (error) => { - // verify - expect(s3Client.createBucket.calledOnce).equal(false); - expect(error).equal(undefined); - done(); - }); - }); - - it('| when headBucket callback NotFound error, createBucketIfNotExist can handle error from createBucket', (done) => { - // setup - sinon.stub(s3Client, 'headBucket').callsArgWith(1, { code: 'NotFound' }); - sinon.stub(s3Client, 'createBucket').callsArgWith(2, TEST_CREATE_ERROR, null); - // call - s3Client.createBucketIfNotExist(TEST_BUCKET_NAME, TEST_AWS_REGION, (error) => { - // verify - expect(error).equal(TEST_CREATE_ERROR); - done(); - }); - }); - - it('| when waitFor return with error, callback with the error', (done) => { - // setup - sinon.stub(s3Client, 'headBucket').callsArgWith(1, { code: 'NotFound' }); - sinon.stub(s3Client, 'createBucket').callsArgWith(2, null, TEST_RESPONSE); - sinon.stub(s3Client, 'waitForBucketExists').callsArgWith(1, TEST_WAITFOR_ERROR); - sinon.stub(s3Client, 'putBucketVersioningIfUninitialized'); - // call - s3Client.createBucketIfNotExist(TEST_BUCKET_NAME, TEST_AWS_REGION, (error) => { - // verify - expect(error).equal(TEST_WAITFOR_ERROR); - done(); - }); - }); - - it('| when create bucket succeeds, callback directly callback without error', (done) => { - // setup - sinon.stub(s3Client, 'headBucket').callsArgWith(1, { code: 'NotFound' }); - sinon.stub(s3Client, 'createBucket').callsArgWith(2, null, TEST_RESPONSE); - sinon.stub(s3Client, 'waitForBucketExists').callsArgWith(1); - sinon.stub(s3Client, 'putBucketVersioningIfUninitialized'); - // call - s3Client.createBucketIfNotExist(TEST_BUCKET_NAME, TEST_AWS_REGION, (error) => { - // verify - expect(s3Client.createBucket.calledOnce).equal(true); - expect(s3Client.waitForBucketExists.calledOnce).equal(true); - expect(error).equal(undefined); - done(); - }); - }); + const MFADelete = "Disabled"; + const Status = "Enabled"; + const expectedParams = { + Bucket: TEST_BUCKET_NAME, + VersioningConfiguration: { + MFADelete, + Status, + }, + }; + sinon + .stub(s3Client.client, "putBucketVersioning") + .withArgs(expectedParams, sinon.match.func) + .callsArgWith(1, TEST_PUTVERSION_ERROR); + // call + s3Client.putBucketVersioning(TEST_BUCKET_NAME, MFADelete, Status, (error, response) => { + // verify + expect(s3Client.client.putBucketVersioning.args[0][0]).deep.equal(expectedParams); + expect(error).equal(TEST_PUTVERSION_ERROR); + expect(response).equal(null); + done(); + }); + }, + ); + + it( + "| s3Client putBucketVersioning method can correctly pass params to aws S3 putBucketVersioning method, " + + "and callback response when S3 putBucketVersioning is executed correctly", + (done) => { + // setup + const s3Client = new S3Client(TEST_CONFIGURATION); + const expectedParams = { + Bucket: TEST_BUCKET_NAME, + VersioningConfiguration: { + MFADelete: "Disabled", + Status: "Enabled", + }, + }; + sinon.stub(s3Client.client, "putBucketVersioning").withArgs(expectedParams, sinon.match.func).callsArgWith(1, null, TEST_RESPONSE); + // call + s3Client.putBucketVersioning(TEST_BUCKET_NAME, "Disabled", "Enabled", (error, response) => { + // verify + expect(s3Client.client.putBucketVersioning.args[0][0]).deep.equal(expectedParams); + expect(error).equal(null); + expect(response).equal(TEST_RESPONSE); + done(); + }); + }, + ); + }); + + describe("# function createBucket tests", () => { + it( + "| s3Client createBucket method can correctly pass params to aws S3 createBucket method when region is us-east-1, " + + "and callback error when S3 createBucket callback error", + (done) => { + // setup + const s3Client = new S3Client(TEST_CONFIGURATION); + const expectedParams = { + Bucket: TEST_BUCKET_NAME, + }; + sinon.stub(s3Client.client, "createBucket").withArgs(expectedParams, sinon.match.func).callsArgWith(1, TEST_CREATE_ERROR); + // call + s3Client.createBucket(TEST_BUCKET_NAME, "us-east-1", (error, response) => { + // verify + expect(s3Client.client.createBucket.args[0][0]).deep.equal(expectedParams); + expect(error).equal(TEST_CREATE_ERROR); + expect(response).equal(null); + done(); + }); + }, + ); + + it( + "| s3Client createBucket method can correctly pass params to aws S3 createBucket method when region is not us-east-1," + + " and callback response when S3 createBucket is executed correctly", + (done) => { + // setup + const s3Client = new S3Client(TEST_CONFIGURATION); + const expectedParams = { + Bucket: TEST_BUCKET_NAME, + CreateBucketConfiguration: { + LocationConstraint: TEST_AWS_REGION, + }, + }; + sinon.stub(s3Client.client, "createBucket").withArgs(expectedParams, sinon.match.func).callsArgWith(1, null, TEST_RESPONSE); + // call + s3Client.createBucket(TEST_BUCKET_NAME, TEST_AWS_REGION, (error, response) => { + // verify + expect(s3Client.client.createBucket.args[0][0]).deep.equal(expectedParams); + expect(error).equal(null); + expect(response).equal(TEST_RESPONSE); + done(); + }); + }, + ); + }); + + describe("# function headBucket tests", () => { + it( + "| s3Client headBucket method can correctly pass params to aws S3 headBucket method, " + + "and callback error when S3 headBucket callback error", + (done) => { + // setup + const s3Client = new S3Client(TEST_CONFIGURATION); + const expectedParams = { + Bucket: TEST_BUCKET_NAME, + }; + sinon.stub(s3Client.client, "headBucket").withArgs(expectedParams, sinon.match.func).callsArgWith(1, TEST_HEAD_ERROR); + // call + s3Client.headBucket(TEST_BUCKET_NAME, (error, response) => { + // verify + expect(s3Client.client.headBucket.args[0][0]).deep.equal(expectedParams); + expect(error).equal(TEST_HEAD_ERROR); + expect(response).equal(null); + done(); + }); + }, + ); + + it( + "| s3Client headBucket method can correctly pass params to aws S3 headBucket method, " + + "and callback response when S3 headBucket is executed correctly", + (done) => { + // setup + const s3Client = new S3Client(TEST_CONFIGURATION); + const expectedParams = { + Bucket: TEST_BUCKET_NAME, + }; + sinon.stub(s3Client.client, "headBucket").withArgs(expectedParams, sinon.match.func).callsArgWith(1, null, TEST_RESPONSE); + // call + s3Client.headBucket(TEST_BUCKET_NAME, (error, response) => { + // verify + expect(s3Client.client.headBucket.args[0][0]).deep.equal(expectedParams); + expect(error).equal(null); + expect(response).equal(TEST_RESPONSE); + done(); + }); + }, + ); + }); + + // TODO fix the unit test of this function + describe.skip("# function getBucketVersioning tests", () => { + it( + "| s3Client getBucketVersioning method, can correctly pass params to aws S3 getBucketVersioning method, " + + "and callback error when S3 getBucketVersioning callback error ", + (done) => { + // setup + const s3Client = new S3Client(TEST_CONFIGURATION); + const expectedParams = { + Bucket: TEST_BUCKET_NAME, + }; + sinon + .stub(s3Client.client, "getBucketVersioning") + .withArgs(expectedParams, sinon.match.func) + .callsArgWith(1, TEST_GETVERSION_ERROR); + // call + s3Client.getBucketVersioning(TEST_BUCKET_NAME, (error, response) => { + // verify + expect(s3Client.client.getBucketVersioning.args[0][0]).deep.equal(expectedParams); + expect(error).equal(TEST_GETVERSION_ERROR); + expect(response).equal(null); + done(); + }); + }, + ); + + it( + "| s3Client getBucketVersioning method, can correctly pass params to aws S3 getBucketVersioning method, " + + "and callback response when S3 getBucketVersioning is executed correctly", + (done) => { + // setup + const s3Client = new S3Client(TEST_CONFIGURATION); + const expectedParams = { + Bucket: TEST_BUCKET_NAME, + }; + sinon.stub(s3Client.client, "getBucketVersioning").withArgs(expectedParams, sinon.match.func).callsArgWith(1, null, TEST_RESPONSE); + // call + s3Client.getBucketVersioning(TEST_BUCKET_NAME, (error, response) => { + // verify + expect(s3Client.client.getBucketVersioning.args[0][0]).deep.equal(expectedParams); + expect(error).equal(null); + expect(response).equal(TEST_RESPONSE); + done(); + }); + }, + ); + }); + + describe("# function createBucketIfNotExist tests", () => { + const s3Client = new S3Client(TEST_CONFIGURATION); + it("| when headBucket return error, provisionBucket can correctly callback error message", (done) => { + // setup + sinon.stub(s3Client, "headBucket").callsArgWith(1, TEST_HEAD_ERROR); + + // call + s3Client.createBucketIfNotExist(TEST_BUCKET_NAME, TEST_AWS_REGION, (error) => { + // verify + expect(error).equal(TEST_HEAD_ERROR); + done(); + }); }); - describe('# function provisionBucketAndPutObject tests', () => { - const TEST_PROVISIONBUCKET_ERROR = 'PROVISIONBUCKET_ERROR'; - const TEST_LAMBDA_REGION = 'LAMBDA_REGION'; - const TEST_FILE_PATH = 'FILE_PATH'; - - const s3Client = new S3Client(TEST_CONFIGURATION); + it("| when headBucket return response without error, directly callback with no argument", (done) => { + // setup + sinon.stub(s3Client, "headBucket").callsArgWith(1, null, TEST_RESPONSE); + sinon.stub(s3Client, "createBucket"); + sinon.stub(s3Client, "putBucketVersioningIfUninitialized"); + // call + s3Client.createBucketIfNotExist(TEST_BUCKET_NAME, TEST_AWS_REGION, (error) => { + // verify + expect(s3Client.createBucket.calledOnce).equal(false); + expect(error).equal(undefined); + done(); + }); + }); - it('| callback createErr when createBucketIfNotExist function return error', (done) => { - // setup - sinon.stub(s3Client, 'createBucketIfNotExist').callsArgWith(2, TEST_CREATE_ERROR); - // call - s3Client.provisionBucketAndPutObject(TEST_BUCKET_NAME, TEST_BUCKET_KEY, TEST_LAMBDA_REGION, TEST_FILE_PATH, (error) => { - // verify - expect(error).equal(TEST_CREATE_ERROR); - done(); - }); - }); + it("| when headBucket callback NotFound error, createBucketIfNotExist can handle error from createBucket", (done) => { + // setup + sinon.stub(s3Client, "headBucket").callsArgWith(1, {code: "NotFound"}); + sinon.stub(s3Client, "createBucket").callsArgWith(2, TEST_CREATE_ERROR, null); + // call + s3Client.createBucketIfNotExist(TEST_BUCKET_NAME, TEST_AWS_REGION, (error) => { + // verify + expect(error).equal(TEST_CREATE_ERROR); + done(); + }); + }); - it('| callback provisionErr when provisionBucket function return error', (done) => { - // setup - sinon.stub(s3Client, 'createBucketIfNotExist').callsArgWith(2); - sinon.stub(s3Client, 'putBucketVersioningIfUninitialized').callsArgWith(1, TEST_PROVISIONBUCKET_ERROR); - // call - s3Client.provisionBucketAndPutObject(TEST_BUCKET_NAME, TEST_BUCKET_KEY, TEST_LAMBDA_REGION, TEST_FILE_PATH, (error) => { - // verify - expect(error).equal(TEST_PROVISIONBUCKET_ERROR); - done(); - }); - }); + it("| when waitFor return with error, callback with the error", (done) => { + // setup + sinon.stub(s3Client, "headBucket").callsArgWith(1, {code: "NotFound"}); + sinon.stub(s3Client, "createBucket").callsArgWith(2, null, TEST_RESPONSE); + sinon.stub(s3Client, "waitForBucketExists").callsArgWith(1, TEST_WAITFOR_ERROR); + sinon.stub(s3Client, "putBucketVersioningIfUninitialized"); + // call + s3Client.createBucketIfNotExist(TEST_BUCKET_NAME, TEST_AWS_REGION, (error) => { + // verify + expect(error).equal(TEST_WAITFOR_ERROR); + done(); + }); + }); - it('| callback putErr when putObject function return error', (done) => { - // setup - sinon.stub(fs, 'readFileSync'); - sinon.stub(s3Client, 'createBucketIfNotExist').callsArgWith(2); - sinon.stub(s3Client, 'putBucketVersioningIfUninitialized').callsArgWith(1); - sinon.stub(s3Client, 'putObject').callsArgWith(3, TEST_PUTOBJECT_ERROR); - // call - s3Client.provisionBucketAndPutObject(TEST_BUCKET_NAME, TEST_BUCKET_KEY, TEST_LAMBDA_REGION, TEST_FILE_PATH, (error) => { - // verify - expect(error).equal(TEST_PUTOBJECT_ERROR); - done(); - }); - }); + it("| when create bucket succeeds, callback directly callback without error", (done) => { + // setup + sinon.stub(s3Client, "headBucket").callsArgWith(1, {code: "NotFound"}); + sinon.stub(s3Client, "createBucket").callsArgWith(2, null, TEST_RESPONSE); + sinon.stub(s3Client, "waitForBucketExists").callsArgWith(1); + sinon.stub(s3Client, "putBucketVersioningIfUninitialized"); + // call + s3Client.createBucketIfNotExist(TEST_BUCKET_NAME, TEST_AWS_REGION, (error) => { + // verify + expect(s3Client.createBucket.calledOnce).equal(true); + expect(s3Client.waitForBucketExists.calledOnce).equal(true); + expect(error).equal(undefined); + done(); + }); + }); + }); + + describe("# function provisionBucketAndPutObject tests", () => { + const TEST_PROVISIONBUCKET_ERROR = "PROVISIONBUCKET_ERROR"; + const TEST_LAMBDA_REGION = "LAMBDA_REGION"; + const TEST_FILE_PATH = "FILE_PATH"; + + const s3Client = new S3Client(TEST_CONFIGURATION); + + it("| callback createErr when createBucketIfNotExist function return error", (done) => { + // setup + sinon.stub(s3Client, "createBucketIfNotExist").callsArgWith(2, TEST_CREATE_ERROR); + // call + s3Client.provisionBucketAndPutObject(TEST_BUCKET_NAME, TEST_BUCKET_KEY, TEST_LAMBDA_REGION, TEST_FILE_PATH, (error) => { + // verify + expect(error).equal(TEST_CREATE_ERROR); + done(); + }); + }); - it('| callback putResponse when putObject function is executed correctly', (done) => { - // setup - sinon.stub(fs, 'readFileSync'); - sinon.stub(s3Client, 'createBucketIfNotExist').callsArgWith(2); - sinon.stub(s3Client, 'putBucketVersioningIfUninitialized').callsArgWith(1); - sinon.stub(s3Client, 'putObject').callsArgWith(3, null, TEST_RESPONSE); - // call - s3Client.provisionBucketAndPutObject(TEST_BUCKET_NAME, TEST_BUCKET_KEY, TEST_LAMBDA_REGION, TEST_FILE_PATH, (error, response) => { - // verify - expect(error).equal(null); - expect(response).equal(TEST_RESPONSE); - done(); - }); - }); + it("| callback provisionErr when provisionBucket function return error", (done) => { + // setup + sinon.stub(s3Client, "createBucketIfNotExist").callsArgWith(2); + sinon.stub(s3Client, "putBucketVersioningIfUninitialized").callsArgWith(1, TEST_PROVISIONBUCKET_ERROR); + // call + s3Client.provisionBucketAndPutObject(TEST_BUCKET_NAME, TEST_BUCKET_KEY, TEST_LAMBDA_REGION, TEST_FILE_PATH, (error) => { + // verify + expect(error).equal(TEST_PROVISIONBUCKET_ERROR); + done(); + }); }); - describe('# function putBucketVersioningIfUninitialized tests', () => { - const s3Client = new S3Client(TEST_CONFIGURATION); + it("| callback putErr when putObject function return error", (done) => { + // setup + sinon.stub(fs, "readFileSync"); + sinon.stub(s3Client, "createBucketIfNotExist").callsArgWith(2); + sinon.stub(s3Client, "putBucketVersioningIfUninitialized").callsArgWith(1); + sinon.stub(s3Client, "putObject").callsArgWith(3, TEST_PUTOBJECT_ERROR); + // call + s3Client.provisionBucketAndPutObject(TEST_BUCKET_NAME, TEST_BUCKET_KEY, TEST_LAMBDA_REGION, TEST_FILE_PATH, (error) => { + // verify + expect(error).equal(TEST_PUTOBJECT_ERROR); + done(); + }); + }); - it('| callback error when getBucketVersioning return error', (done) => { - // setup - sinon.stub(s3Client, 'getBucketVersioning').callsArgWith(1, TEST_GETVERSION_ERROR); - // call - s3Client.putBucketVersioningIfUninitialized(TEST_BUCKET_NAME, (error) => { - // verify - expect(error).equal(TEST_GETVERSION_ERROR); - done(); - }); - }); + it("| callback putResponse when putObject function is executed correctly", (done) => { + // setup + sinon.stub(fs, "readFileSync"); + sinon.stub(s3Client, "createBucketIfNotExist").callsArgWith(2); + sinon.stub(s3Client, "putBucketVersioningIfUninitialized").callsArgWith(1); + sinon.stub(s3Client, "putObject").callsArgWith(3, null, TEST_RESPONSE); + // call + s3Client.provisionBucketAndPutObject(TEST_BUCKET_NAME, TEST_BUCKET_KEY, TEST_LAMBDA_REGION, TEST_FILE_PATH, (error, response) => { + // verify + expect(error).equal(null); + expect(response).equal(TEST_RESPONSE); + done(); + }); + }); + }); + + describe("# function putBucketVersioningIfUninitialized tests", () => { + const s3Client = new S3Client(TEST_CONFIGURATION); + + it("| callback error when getBucketVersioning return error", (done) => { + // setup + sinon.stub(s3Client, "getBucketVersioning").callsArgWith(1, TEST_GETVERSION_ERROR); + // call + s3Client.putBucketVersioningIfUninitialized(TEST_BUCKET_NAME, (error) => { + // verify + expect(error).equal(TEST_GETVERSION_ERROR); + done(); + }); + }); - it('| callback error when getBucketVersioning return empty object and putBucketVersioning return error', (done) => { - // setup - sinon.stub(s3Client, 'getBucketVersioning').callsArgWith(1, null, {}); - sinon.stub(s3Client, 'putBucketVersioning').callsArgWith(3, TEST_PUTVERSION_ERROR); - // call - s3Client.putBucketVersioningIfUninitialized(TEST_BUCKET_NAME, (error) => { - // verify - expect(error).equal(TEST_PUTVERSION_ERROR); - done(); - }); - }); + it("| callback error when getBucketVersioning return empty object and putBucketVersioning return error", (done) => { + // setup + sinon.stub(s3Client, "getBucketVersioning").callsArgWith(1, null, {}); + sinon.stub(s3Client, "putBucketVersioning").callsArgWith(3, TEST_PUTVERSION_ERROR); + // call + s3Client.putBucketVersioningIfUninitialized(TEST_BUCKET_NAME, (error) => { + // verify + expect(error).equal(TEST_PUTVERSION_ERROR); + done(); + }); + }); - it('| callback with no argument when getBucketVersioning return empty object and putBucketVersioning is executed correctly', (done) => { - // setup - sinon.stub(s3Client, 'getBucketVersioning').callsArgWith(1, null, {}); - sinon.stub(s3Client, 'putBucketVersioning').callsArgWith(3, null, TEST_RESPONSE); - // call - s3Client.putBucketVersioningIfUninitialized(TEST_BUCKET_NAME, (error) => { - // verify - expect(error).equal(undefined); - done(); - }); - }); + it("| callback with no argument when getBucketVersioning return empty object and putBucketVersioning is executed correctly", (done) => { + // setup + sinon.stub(s3Client, "getBucketVersioning").callsArgWith(1, null, {}); + sinon.stub(s3Client, "putBucketVersioning").callsArgWith(3, null, TEST_RESPONSE); + // call + s3Client.putBucketVersioningIfUninitialized(TEST_BUCKET_NAME, (error) => { + // verify + expect(error).equal(undefined); + done(); + }); + }); - it('| callback with no argument when getBucketVersioning return non-empty object', (done) => { - // setup - sinon.stub(s3Client, 'getBucketVersioning').callsArgWith(1, null, { a: 'b' }); - sinon.stub(s3Client, 'putBucketVersioning'); - // call - s3Client.putBucketVersioningIfUninitialized(TEST_BUCKET_NAME, (error) => { - // verify - expect(s3Client.putBucketVersioning.calledOnce).equal(false); - expect(error).equal(undefined); - done(); - }); - }); + it("| callback with no argument when getBucketVersioning return non-empty object", (done) => { + // setup + sinon.stub(s3Client, "getBucketVersioning").callsArgWith(1, null, {a: "b"}); + sinon.stub(s3Client, "putBucketVersioning"); + // call + s3Client.putBucketVersioningIfUninitialized(TEST_BUCKET_NAME, (error) => { + // verify + expect(s3Client.putBucketVersioning.calledOnce).equal(false); + expect(error).equal(undefined); + done(); + }); }); + }); - describe('# function generateBucketName tests', () => { - const TEST_REAL_AWS_REGION = 'ap-northeast-1'; - const TEST_PROFILE_NAME = '1234567890'; + describe("# function generateBucketName tests", () => { + const TEST_REAL_AWS_REGION = "ap-northeast-1"; + const TEST_PROFILE_NAME = "1234567890"; - beforeEach(() => { - sinon.useFakeTimers(Date.UTC(2016, 2, 15)); - }); + beforeEach(() => { + sinon.useFakeTimers(Date.UTC(2016, 2, 15)); + }); - it('| when user project name is longer than 22 characters and profile name is longer than 9 characters', () => { - sinon.stub(path, 'basename').callsFake(() => '123456789012345678901234'); - const expectedName = 'ask-1234567890123456789012-123456789-apnortheast1-1458000000000'; - expect(S3Client.generateBucketName(TEST_PROFILE_NAME, TEST_REAL_AWS_REGION)).equal(expectedName); - }); + it("| when user project name is longer than 22 characters and profile name is longer than 9 characters", () => { + sinon.stub(path, "basename").callsFake(() => "123456789012345678901234"); + const expectedName = "ask-1234567890123456789012-123456789-apnortheast1-1458000000000"; + expect(S3Client.generateBucketName(TEST_PROFILE_NAME, TEST_REAL_AWS_REGION)).equal(expectedName); + }); - it('| when user project name and profile name contain special characters which are not allowed', () => { - sinon.stub(path, 'basename').callsFake(() => ';:,/ +=*&^%$#@test-name!~-.'); - const profileName = 'foo|{}[]?<>_'; - const expectedName = 'ask-test-name-.-foo-apnortheast1-1458000000000'; - expect(S3Client.generateBucketName(profileName, TEST_REAL_AWS_REGION)).equal(expectedName); - }); + it("| when user project name and profile name contain special characters which are not allowed", () => { + sinon.stub(path, "basename").callsFake(() => ";:,/ +=*&^%$#@test-name!~-."); + const profileName = "foo|{}[]?<>_"; + const expectedName = "ask-test-name-.-foo-apnortheast1-1458000000000"; + expect(S3Client.generateBucketName(profileName, TEST_REAL_AWS_REGION)).equal(expectedName); + }); - it('| when user project name and profile name contain Capital characters', () => { - sinon.stub(path, 'basename').callsFake(() => 'TESTPROJECTNAME'); - const profileName = 'PROFILE'; - const expectedName = 'ask-testprojectname-profile-apnortheast1-1458000000000'; - expect(S3Client.generateBucketName(profileName, TEST_REAL_AWS_REGION)).equal(expectedName); - }); + it("| when user project name and profile name contain Capital characters", () => { + sinon.stub(path, "basename").callsFake(() => "TESTPROJECTNAME"); + const profileName = "PROFILE"; + const expectedName = "ask-testprojectname-profile-apnortheast1-1458000000000"; + expect(S3Client.generateBucketName(profileName, TEST_REAL_AWS_REGION)).equal(expectedName); }); + }); - describe('# function retryBucketVersionOperations tests', () => { - it('| when status code 404 should set retryable property to true', () => { - const response = { httpResponse: { statusCode: 404 }, error: {} }; - const s3Client = new S3Client(TEST_CONFIGURATION); + describe("# function retryBucketVersionOperations tests", () => { + it("| when status code 404 should set retryable property to true", () => { + const response = {httpResponse: {statusCode: 404}, error: {}}; + const s3Client = new S3Client(TEST_CONFIGURATION); - s3Client.retryBucketVersionOperations(response); - expect(response.error.retryable).equal(true); - }); + s3Client.retryBucketVersionOperations(response); + expect(response.error.retryable).equal(true); + }); - it('| when status code is not 404 should not set retryable property to true', () => { - const response = { httpResponse: { statusCode: 200 }, error: {} }; - const s3Client = new S3Client(TEST_CONFIGURATION); + it("| when status code is not 404 should not set retryable property to true", () => { + const response = {httpResponse: {statusCode: 200}, error: {}}; + const s3Client = new S3Client(TEST_CONFIGURATION); - s3Client.retryBucketVersionOperations(response); - expect(response.error.retryable).equal(undefined); - }); + s3Client.retryBucketVersionOperations(response); + expect(response.error.retryable).equal(undefined); }); + }); - afterEach(() => { - sinon.restore(); - }); + afterEach(() => { + sinon.restore(); + }); }); diff --git a/test/unit/clients/git-client-test.js b/test/unit/clients/git-client-test.js index 060df47c..3a1eed86 100644 --- a/test/unit/clients/git-client-test.js +++ b/test/unit/clients/git-client-test.js @@ -1,435 +1,441 @@ +const {expect} = require("chai"); +const fs = require("fs-extra"); +const sinon = require("sinon"); +const path = require("path"); +const proxyquire = require("proxyquire"); + +const GitClient = require("../../../lib/clients/git-client"); +const CLiError = require("../../../lib/exceptions/cli-error"); +const Messenger = require("../../../lib/view/messenger"); + +describe("Clients test - cli git client", () => { + const TEST_ERROR = "TEST_ERROR"; + const TEST_PROJECT_PATH = "TEST_PROJECT_PATH"; + const TEST_VERBOSITY_OPTIONS = { + showOutput: false, + showCommand: false, + showStdErr: false, + workingDir: TEST_PROJECT_PATH, + }; + const TEST_VERBOSITY_OPTIONS_DEBUG = { + showOutput: true, + showCommand: true, + showStdErr: true, + }; + + describe("# inspect correctness for constructor", () => { + it("| initiate as a GitClient class", () => { + // call + const gitClient = new GitClient(TEST_PROJECT_PATH, TEST_VERBOSITY_OPTIONS); + // verify + expect(gitClient).to.be.instanceOf(GitClient); + expect(gitClient.projectPath).equal(TEST_PROJECT_PATH); + expect(gitClient.verbosityOptions.showOutput).equal(false); + expect(gitClient.verbosityOptions.showCommand).equal(false); + }); + }); + + describe("# test init", () => { + afterEach(() => { + sinon.restore(); + }); + + it("| test git init fails", () => { + // setup + const gitClient = new GitClient(TEST_PROJECT_PATH, TEST_VERBOSITY_OPTIONS); + sinon.stub(gitClient, "_execChildProcessSync").throws(new CLiError(TEST_ERROR)); + // call & verify + expect(() => gitClient.init()).throw(CLiError, `CliError: ${TEST_ERROR}`); + }); + + it("| test git init succeed", () => { + // setup + const TEST_COMMAND = `git init "${TEST_PROJECT_PATH}"${TEST_VERBOSITY_OPTIONS_DEBUG.showOutput === false ? " --quiet" : ""}`; + const gitClient = new GitClient(TEST_PROJECT_PATH, TEST_VERBOSITY_OPTIONS_DEBUG); + sinon.stub(gitClient, "_execChildProcessSync"); + // call + gitClient.init(); + // verify + expect(gitClient._execChildProcessSync.args[0][0]).eq(TEST_COMMAND); + }); + }); + + describe("# test configureCredentialHelper", () => { + const TEST_CREDENTIAL_SCRIPT_EXECUTION = "TEST_CREDENTIAL_SCRIPT_EXECUTION"; + const TEST_GIT_HOST_URL = "SOME_URL"; + const TEST_COMMAND = [ + `git config --local credential.${TEST_GIT_HOST_URL}.helper ""`, + `git config --local --add credential.${TEST_GIT_HOST_URL}.helper "!${TEST_CREDENTIAL_SCRIPT_EXECUTION}"`, + `git config --local credential.${TEST_GIT_HOST_URL}.UseHttpPath true`, + ]; + + afterEach(() => { + sinon.restore(); + }); + + it("| test git configureCredentialHelper execute commands correctly ", () => { + // setup + const gitClient = new GitClient(TEST_PROJECT_PATH, TEST_VERBOSITY_OPTIONS); + sinon.stub(gitClient, "_execChildProcessSync"); + // call + gitClient.configureCredentialHelper(TEST_CREDENTIAL_SCRIPT_EXECUTION, TEST_GIT_HOST_URL); + // verify + expect(gitClient._execChildProcessSync.callCount).eq(3); + expect(gitClient._execChildProcessSync.args[0][0]).eq(TEST_COMMAND[0]); + expect(gitClient._execChildProcessSync.args[1][0]).eq(TEST_COMMAND[1]); + expect(gitClient._execChildProcessSync.args[2][0]).eq(TEST_COMMAND[2]); + }); + + it("| test git configureCredentialHelper fails", () => { + // setup + const gitClient = new GitClient(TEST_PROJECT_PATH, TEST_VERBOSITY_OPTIONS_DEBUG); + sinon.stub(gitClient, "_execChildProcessSync").throws(new CLiError(`${TEST_ERROR}`)); + // call & verify + expect(() => gitClient.configureCredentialHelper(TEST_CREDENTIAL_SCRIPT_EXECUTION, TEST_GIT_HOST_URL)).throw( + CLiError, + `CliError: ${TEST_ERROR}`, + ); + }); + }); + + describe("# test addOrigin", () => { + const TEST_REPO_URL = "TEST_REPO_URL"; + const TEST_COMMAND = [`git remote add origin ${TEST_REPO_URL}`]; + + afterEach(() => { + sinon.restore(); + }); + + it("| test git addOrigin execute commands correctly ", () => { + // setup + const gitClient = new GitClient(TEST_PROJECT_PATH, TEST_VERBOSITY_OPTIONS); + sinon.stub(gitClient, "_execChildProcessSync"); + // call + gitClient.addOrigin(TEST_REPO_URL); + // verify + expect(gitClient._execChildProcessSync.callCount).eq(1); + expect(gitClient._execChildProcessSync.args[0][0]).eq(TEST_COMMAND[0]); + }); + + it("| test git addOrigin fails", () => { + // setup + const gitClient = new GitClient(TEST_PROJECT_PATH, TEST_VERBOSITY_OPTIONS_DEBUG); + sinon.stub(gitClient, "_execChildProcessSync").throws(new CLiError(`${TEST_ERROR}`)); + // call & verify + expect(() => gitClient.addOrigin(TEST_REPO_URL)).throw(CLiError, `CliError: ${TEST_ERROR}`); + }); + }); + + describe("# test fetchAll", () => { + const TEST_COMMAND = [`git fetch --all${TEST_VERBOSITY_OPTIONS.showOutput === false ? " --quiet" : ""}`]; + + afterEach(() => { + sinon.restore(); + }); + + it("| test git fetchAll execute commands correctly ", () => { + // setup + const gitClient = new GitClient(TEST_PROJECT_PATH, TEST_VERBOSITY_OPTIONS); + sinon.stub(gitClient, "_execChildProcessSync"); + // call + gitClient.fetchAll(); + // verify + expect(gitClient._execChildProcessSync.callCount).eq(1); + expect(gitClient._execChildProcessSync.args[0][0]).eq(TEST_COMMAND[0]); + }); + + it("| test git fetchAll fails", () => { + // setup + const gitClient = new GitClient(TEST_PROJECT_PATH, TEST_VERBOSITY_OPTIONS_DEBUG); + sinon.stub(gitClient, "_execChildProcessSync").throws(new CLiError(`${TEST_ERROR}`)); + // call & verify + expect(() => gitClient.fetchAll()).throw(CLiError, `CliError: ${TEST_ERROR}`); + }); + }); + + describe("# test checkoutBranch", () => { + const TEST_BRANCH = "ASK-CLI"; + const TEST_COMMAND = [`git checkout ${TEST_BRANCH}${TEST_VERBOSITY_OPTIONS.showOutput === false ? " --quiet" : ""}`]; + + afterEach(() => { + sinon.restore(); + }); + + it("| test git checkoutBranch execute commands correctly ", () => { + // setup + const gitClient = new GitClient(TEST_PROJECT_PATH, TEST_VERBOSITY_OPTIONS); + sinon.stub(gitClient, "_execChildProcessSync"); + // call + gitClient.checkoutBranch(TEST_BRANCH); + // verify + expect(gitClient._execChildProcessSync.callCount).eq(1); + expect(gitClient._execChildProcessSync.args[0][0]).eq(TEST_COMMAND[0]); + }); + + it("| test git checkoutBranch fails", () => { + // setup + const gitClient = new GitClient(TEST_PROJECT_PATH, TEST_VERBOSITY_OPTIONS_DEBUG); + sinon.stub(gitClient, "_execChildProcessSync").throws(new CLiError(`${TEST_ERROR}`)); + // call & verify + expect(() => gitClient.checkoutBranch(TEST_BRANCH)).throw(CLiError, `CliError: ${TEST_ERROR}`); + }); + }); + + describe("# git clone", () => { + const TEST_FOLDER_NAME = "TEST_FOLDER_NAME"; + const TEST_CLONE_URL = "https://test.git"; + const TEST_BRANCH = "ASK-CLI"; + const TEST_COMMAND = [ + `git clone --branch ${TEST_BRANCH} ${TEST_CLONE_URL} "${TEST_FOLDER_NAME}" ` + + `${TEST_VERBOSITY_OPTIONS.showOutput === false ? " --quiet" : ""}`, + ]; + + afterEach(() => { + sinon.restore(); + }); + + it("| test git clone execute commands correctly ", () => { + // setup + const gitClient = new GitClient(TEST_PROJECT_PATH, TEST_VERBOSITY_OPTIONS); + sinon.stub(gitClient, "_execChildProcessSync"); + // call + gitClient.clone(TEST_CLONE_URL, TEST_BRANCH, TEST_FOLDER_NAME); + // verify + expect(gitClient._execChildProcessSync.callCount).eq(1); + expect(gitClient._execChildProcessSync.args[0][0]).eq(TEST_COMMAND[0]); + }); + + it("| test git clone fails", () => { + // setup + const gitClient = new GitClient(TEST_PROJECT_PATH, TEST_VERBOSITY_OPTIONS_DEBUG); + sinon.stub(gitClient, "_execChildProcessSync").throws(new CLiError(`${TEST_ERROR}`)); + // call & verify + expect(() => gitClient.clone(TEST_CLONE_URL, TEST_BRANCH, TEST_FOLDER_NAME)).throw(CLiError, `CliError: ${TEST_ERROR}`); + }); + }); + + describe("# git add", () => { + const TEST_REPO_DIR = "repoDir"; + const TEST_COMMAND = [`git add "${TEST_REPO_DIR}"`]; + + afterEach(() => { + sinon.restore(); + }); + + it("| test git add execute commands correctly ", () => { + // setup + const gitClient = new GitClient(TEST_PROJECT_PATH, TEST_VERBOSITY_OPTIONS); + sinon.stub(gitClient, "_execChildProcessSync"); + // call + gitClient.add(TEST_REPO_DIR); + // verify + expect(gitClient._execChildProcessSync.callCount).eq(1); + expect(gitClient._execChildProcessSync.args[0][0]).eq(TEST_COMMAND[0]); + }); + + it("| test git add fails", () => { + // setup + const gitClient = new GitClient(TEST_PROJECT_PATH, TEST_VERBOSITY_OPTIONS_DEBUG); + sinon.stub(gitClient, "_execChildProcessSync").throws(new CLiError(`${TEST_ERROR}`)); + // call & verify + expect(() => gitClient.add(TEST_REPO_DIR)).throw(CLiError, `CliError: ${TEST_ERROR}`); + }); + }); + + describe("# git deleteBranch", () => { + const TEST_BRANCH = "dev"; + const TEST_COMMAND = [`git branch -d ${TEST_BRANCH}`]; + + afterEach(() => { + sinon.restore(); + }); + + it("| test git delete execute commands correctly ", () => { + // setup + const gitClient = new GitClient(TEST_PROJECT_PATH, TEST_VERBOSITY_OPTIONS); + sinon.stub(gitClient, "_execChildProcessSync"); + // call + gitClient.deleteBranch(TEST_BRANCH); + // verify + expect(gitClient._execChildProcessSync.callCount).eq(1); + expect(gitClient._execChildProcessSync.args[0][0]).eq(TEST_COMMAND[0]); + }); + + it("| test git add fails", () => { + // setup + const gitClient = new GitClient(TEST_PROJECT_PATH, TEST_VERBOSITY_OPTIONS_DEBUG); + sinon.stub(gitClient, "_execChildProcessSync").throws(new CLiError(`${TEST_ERROR}`)); + // call & verify + expect(() => gitClient.deleteBranch(TEST_BRANCH)).throw(CLiError, `CliError: ${TEST_ERROR}`); + }); + }); + + describe("# git merge", () => { + const TEST_BRANCH = "dev"; + const TEST_COMMAND = [`git merge ${TEST_BRANCH}`]; + + afterEach(() => { + sinon.restore(); + }); + + it("| test git merge execute commands correctly ", () => { + // setup + const gitClient = new GitClient(TEST_PROJECT_PATH, TEST_VERBOSITY_OPTIONS); + sinon.stub(gitClient, "_execChildProcessSync"); + // call + gitClient.merge(TEST_BRANCH); + // verify + expect(gitClient._execChildProcessSync.callCount).eq(1); + expect(gitClient._execChildProcessSync.args[0][0]).eq(TEST_COMMAND[0]); + }); + + it("| test git merge fails", () => { + // setup + const gitClient = new GitClient(TEST_PROJECT_PATH, TEST_VERBOSITY_OPTIONS_DEBUG); + sinon.stub(gitClient, "_execChildProcessSync").throws(new CLiError(`${TEST_ERROR}`)); + // call & verify + expect(() => gitClient.merge(TEST_BRANCH)).throw(CLiError, `CliError: ${TEST_ERROR}`); + }); + }); + + describe("# git shortStatus", () => { + const TEST_COMMAND = "git status -s"; + + afterEach(() => { + sinon.restore(); + }); + + it("| test git status execute commands correctly ", () => { + // setup + const gitClient = new GitClient(TEST_PROJECT_PATH, TEST_VERBOSITY_OPTIONS); + const TEST_STDOUT = "stdout"; + sinon.stub(gitClient, "_execChildProcessSync").returns(TEST_STDOUT); + // call + const res = gitClient.shortStatus(); + // verify + expect(res).equal(TEST_STDOUT); + expect(gitClient._execChildProcessSync.callCount).eq(1); + expect(gitClient._execChildProcessSync.args[0][0]).eq(TEST_COMMAND); + }); + + it("| test git status fails", () => { + // setup + const gitClient = new GitClient(TEST_PROJECT_PATH, TEST_VERBOSITY_OPTIONS); + sinon.stub(gitClient, "_execChildProcessSync").throws(new CLiError(`${TEST_ERROR}`)); + // call & verify + expect(() => gitClient.shortStatus()).throw(CLiError, `CliError: ${TEST_ERROR}`); + }); + }); + + describe("# git countCommitDifference", () => { + const COMMIT1 = "origin/dev"; + const COMMIT2 = "dev"; + const TEST_COMMAND = `git rev-list --count ${COMMIT1}...${COMMIT2}`; + + afterEach(() => { + sinon.restore(); + }); + + it("| test git rev-list --count execute commands correctly ", () => { + // setup + const gitClient = new GitClient(TEST_PROJECT_PATH, TEST_VERBOSITY_OPTIONS); + const TEST_STDOUT = "stdout"; + sinon.stub(gitClient, "_execChildProcessSync").returns(TEST_STDOUT); + // call + const res = gitClient.countCommitDifference(COMMIT1, COMMIT2); + // verify + expect(res).equal(TEST_STDOUT); + expect(gitClient._execChildProcessSync.callCount).eq(1); + expect(gitClient._execChildProcessSync.args[0][0]).eq(TEST_COMMAND); + }); + + it("| test git rev-list --count fails", () => { + // setup + const gitClient = new GitClient(TEST_PROJECT_PATH, TEST_VERBOSITY_OPTIONS_DEBUG); + sinon.stub(gitClient, "_execChildProcessSync").throws(new CLiError(`${TEST_ERROR}`)); + // call & verify + expect(() => gitClient.countCommitDifference(COMMIT1, COMMIT2)).throw(CLiError, `CliError: ${TEST_ERROR}`); + }); + }); + + describe("# test setupGitIgnore", () => { + const TEST_FILES_TO_IGNORE = [".file_one", ".file_two"]; + const TEST_GIT_IGNORE = "TEST_GIT_IGNORE"; + const gitClient = new GitClient(TEST_PROJECT_PATH, TEST_VERBOSITY_OPTIONS); + + afterEach(() => { + sinon.restore(); + }); + + it("| test .gitignore file does not exist ", () => { + // setup + sinon.stub(path, "join").returns(TEST_GIT_IGNORE); + sinon.stub(fs, "existsSync").returns(false); + const writeFileStub = sinon.stub(fs, "writeFileSync"); + sinon.stub(gitClient, "add"); + // call + gitClient.setupGitIgnore(TEST_FILES_TO_IGNORE); + // verify + expect(writeFileStub.args[0][0]).eq(TEST_GIT_IGNORE); + expect(writeFileStub.args[0][1]).eq(".file_one\n.file_two"); + }); + + it("| test .gitignore file not exists ", () => { + // setup + sinon.stub(path, "join").returns(TEST_GIT_IGNORE); + sinon.stub(fs, "existsSync").returns(true); + const writeFileStub = sinon.stub(fs, "readFileSync").returns(".file_one"); + const appendFileStub = sinon.stub(fs, "appendFileSync"); + sinon.stub(gitClient, "add"); + // call + gitClient.setupGitIgnore(TEST_FILES_TO_IGNORE); + // verify + expect(writeFileStub.callCount).eq(1); + expect(appendFileStub.args[0][0]).eq(TEST_GIT_IGNORE); + }); + }); + + describe("# test _execChildProcessSync", () => { + let infoStub; + const TEST_COMMAND = "TEST_COMMAND"; + + beforeEach(() => { + infoStub = sinon.stub(); + sinon.stub(Messenger, "getInstance").returns({ + info: infoStub, + }); + }); + + afterEach(() => { + sinon.restore(); + }); + + it("| test _execChildProcessSync succeeds ", () => { + // setup + const childProcessStub = { + execSync: () => {}, + }; + const proxyHelper = proxyquire("../../../lib/clients/git-client", { + child_process: childProcessStub, + }); + // call + proxyHelper.prototype._execChildProcessSync(TEST_COMMAND, TEST_VERBOSITY_OPTIONS_DEBUG); + // verify + expect(infoStub.args[0][0]).eq(TEST_COMMAND); + }); -const { expect } = require('chai'); -const fs = require('fs-extra'); -const sinon = require('sinon'); -const path = require('path'); -const proxyquire = require('proxyquire'); - -const GitClient = require('@src/clients/git-client'); -const CLiError = require('@src/exceptions/cli-error'); -const Messenger = require('@src/view/messenger'); - -describe('Clients test - cli git client', () => { - const TEST_ERROR = 'TEST_ERROR'; - const TEST_PROJECT_PATH = 'TEST_PROJECT_PATH'; - const TEST_VERBOSITY_OPTIONS = { - showOutput: false, - showCommand: false, - showStdErr: false, - workingDir: TEST_PROJECT_PATH - }; - const TEST_VERBOSITY_OPTIONS_DEBUG = { - showOutput: true, - showCommand: true, - showStdErr: true - }; - - describe('# inspect correctness for constructor', () => { - it('| initiate as a GitClient class', () => { - // call - const gitClient = new GitClient(TEST_PROJECT_PATH, TEST_VERBOSITY_OPTIONS); - // verify - expect(gitClient).to.be.instanceOf(GitClient); - expect(gitClient.projectPath).equal(TEST_PROJECT_PATH); - expect(gitClient.verbosityOptions.showOutput).equal(false); - expect(gitClient.verbosityOptions.showCommand).equal(false); - }); - }); - - describe('# test init', () => { - afterEach(() => { - sinon.restore(); - }); - - it('| test git init fails', () => { - // setup - const gitClient = new GitClient(TEST_PROJECT_PATH, TEST_VERBOSITY_OPTIONS); - sinon.stub(gitClient, '_execChildProcessSync').throws(new CLiError(TEST_ERROR)); - // call & verify - expect(() => gitClient.init()).throw(CLiError, `CliError: ${TEST_ERROR}`); - }); - - it('| test git init succeed', () => { - // setup - const TEST_COMMAND = `git init "${TEST_PROJECT_PATH}"${TEST_VERBOSITY_OPTIONS_DEBUG.showOutput === false ? ' --quiet' : ''}`; - const gitClient = new GitClient(TEST_PROJECT_PATH, TEST_VERBOSITY_OPTIONS_DEBUG); - sinon.stub(gitClient, '_execChildProcessSync'); - // call - gitClient.init(); - // verify - expect(gitClient._execChildProcessSync.args[0][0]).eq(TEST_COMMAND); - }); - }); - - describe('# test configureCredentialHelper', () => { - const TEST_CREDENTIAL_SCRIPT_EXECUTION = 'TEST_CREDENTIAL_SCRIPT_EXECUTION'; - const TEST_GIT_HOST_URL = 'SOME_URL'; - const TEST_COMMAND = [ - `git config --local credential.${TEST_GIT_HOST_URL}.helper ""`, - `git config --local --add credential.${TEST_GIT_HOST_URL}.helper "!${TEST_CREDENTIAL_SCRIPT_EXECUTION}"`, - `git config --local credential.${TEST_GIT_HOST_URL}.UseHttpPath true`]; - - afterEach(() => { - sinon.restore(); - }); - - it('| test git configureCredentialHelper execute commands correctly ', () => { - // setup - const gitClient = new GitClient(TEST_PROJECT_PATH, TEST_VERBOSITY_OPTIONS); - sinon.stub(gitClient, '_execChildProcessSync'); - // call - gitClient.configureCredentialHelper(TEST_CREDENTIAL_SCRIPT_EXECUTION, TEST_GIT_HOST_URL); - // verify - expect(gitClient._execChildProcessSync.callCount).eq(3); - expect(gitClient._execChildProcessSync.args[0][0]).eq(TEST_COMMAND[0]); - expect(gitClient._execChildProcessSync.args[1][0]).eq(TEST_COMMAND[1]); - expect(gitClient._execChildProcessSync.args[2][0]).eq(TEST_COMMAND[2]); - }); - - it('| test git configureCredentialHelper fails', () => { - // setup - const gitClient = new GitClient(TEST_PROJECT_PATH, TEST_VERBOSITY_OPTIONS_DEBUG); - sinon.stub(gitClient, '_execChildProcessSync').throws(new CLiError(`${TEST_ERROR}`)); - // call & verify - expect(() => gitClient.configureCredentialHelper(TEST_CREDENTIAL_SCRIPT_EXECUTION, TEST_GIT_HOST_URL)).throw(CLiError, `CliError: ${TEST_ERROR}`); - }); - }); - - describe('# test addOrigin', () => { - const TEST_REPO_URL = 'TEST_REPO_URL'; - const TEST_COMMAND = [`git remote add origin ${TEST_REPO_URL}`]; - - afterEach(() => { - sinon.restore(); - }); - - it('| test git addOrigin execute commands correctly ', () => { - // setup - const gitClient = new GitClient(TEST_PROJECT_PATH, TEST_VERBOSITY_OPTIONS); - sinon.stub(gitClient, '_execChildProcessSync'); - // call - gitClient.addOrigin(TEST_REPO_URL); - // verify - expect(gitClient._execChildProcessSync.callCount).eq(1); - expect(gitClient._execChildProcessSync.args[0][0]).eq(TEST_COMMAND[0]); - }); - - it('| test git addOrigin fails', () => { - // setup - const gitClient = new GitClient(TEST_PROJECT_PATH, TEST_VERBOSITY_OPTIONS_DEBUG); - sinon.stub(gitClient, '_execChildProcessSync').throws(new CLiError(`${TEST_ERROR}`)); - // call & verify - expect(() => gitClient.addOrigin(TEST_REPO_URL)).throw(CLiError, `CliError: ${TEST_ERROR}`); - }); - }); - - describe('# test fetchAll', () => { - const TEST_COMMAND = [`git fetch --all${TEST_VERBOSITY_OPTIONS.showOutput === false ? ' --quiet' : ''}`]; - - afterEach(() => { - sinon.restore(); - }); - - it('| test git fetchAll execute commands correctly ', () => { - // setup - const gitClient = new GitClient(TEST_PROJECT_PATH, TEST_VERBOSITY_OPTIONS); - sinon.stub(gitClient, '_execChildProcessSync'); - // call - gitClient.fetchAll(); - // verify - expect(gitClient._execChildProcessSync.callCount).eq(1); - expect(gitClient._execChildProcessSync.args[0][0]).eq(TEST_COMMAND[0]); - }); - - it('| test git fetchAll fails', () => { - // setup - const gitClient = new GitClient(TEST_PROJECT_PATH, TEST_VERBOSITY_OPTIONS_DEBUG); - sinon.stub(gitClient, '_execChildProcessSync').throws(new CLiError(`${TEST_ERROR}`)); - // call & verify - expect(() => gitClient.fetchAll()).throw(CLiError, `CliError: ${TEST_ERROR}`); - }); - }); - - describe('# test checkoutBranch', () => { - const TEST_BRANCH = 'ASK-CLI'; - const TEST_COMMAND = [`git checkout ${TEST_BRANCH}${TEST_VERBOSITY_OPTIONS.showOutput === false ? ' --quiet' : ''}`]; - - afterEach(() => { - sinon.restore(); - }); - - it('| test git checkoutBranch execute commands correctly ', () => { - // setup - const gitClient = new GitClient(TEST_PROJECT_PATH, TEST_VERBOSITY_OPTIONS); - sinon.stub(gitClient, '_execChildProcessSync'); - // call - gitClient.checkoutBranch(TEST_BRANCH); - // verify - expect(gitClient._execChildProcessSync.callCount).eq(1); - expect(gitClient._execChildProcessSync.args[0][0]).eq(TEST_COMMAND[0]); - }); - - it('| test git checkoutBranch fails', () => { - // setup - const gitClient = new GitClient(TEST_PROJECT_PATH, TEST_VERBOSITY_OPTIONS_DEBUG); - sinon.stub(gitClient, '_execChildProcessSync').throws(new CLiError(`${TEST_ERROR}`)); - // call & verify - expect(() => gitClient.checkoutBranch(TEST_BRANCH)).throw(CLiError, `CliError: ${TEST_ERROR}`); - }); - }); - - describe('# git clone', () => { - const TEST_FOLDER_NAME = 'TEST_FOLDER_NAME'; - const TEST_CLONE_URL = 'https://test.git'; - const TEST_BRANCH = 'ASK-CLI'; - const TEST_COMMAND = [`git clone --branch ${TEST_BRANCH} ${TEST_CLONE_URL} "${TEST_FOLDER_NAME}" ` - + `${TEST_VERBOSITY_OPTIONS.showOutput === false ? ' --quiet' : ''}`]; - - afterEach(() => { - sinon.restore(); - }); - - it('| test git clone execute commands correctly ', () => { - // setup - const gitClient = new GitClient(TEST_PROJECT_PATH, TEST_VERBOSITY_OPTIONS); - sinon.stub(gitClient, '_execChildProcessSync'); - // call - gitClient.clone(TEST_CLONE_URL, TEST_BRANCH, TEST_FOLDER_NAME); - // verify - expect(gitClient._execChildProcessSync.callCount).eq(1); - expect(gitClient._execChildProcessSync.args[0][0]).eq(TEST_COMMAND[0]); - }); - - it('| test git clone fails', () => { - // setup - const gitClient = new GitClient(TEST_PROJECT_PATH, TEST_VERBOSITY_OPTIONS_DEBUG); - sinon.stub(gitClient, '_execChildProcessSync').throws(new CLiError(`${TEST_ERROR}`)); - // call & verify - expect(() => gitClient.clone(TEST_CLONE_URL, TEST_BRANCH, TEST_FOLDER_NAME)).throw(CLiError, `CliError: ${TEST_ERROR}`); - }); - }); - - describe('# git add', () => { - const TEST_REPO_DIR = 'repoDir'; - const TEST_COMMAND = [`git add "${TEST_REPO_DIR}"`]; - - afterEach(() => { - sinon.restore(); - }); - - it('| test git add execute commands correctly ', () => { - // setup - const gitClient = new GitClient(TEST_PROJECT_PATH, TEST_VERBOSITY_OPTIONS); - sinon.stub(gitClient, '_execChildProcessSync'); - // call - gitClient.add(TEST_REPO_DIR); - // verify - expect(gitClient._execChildProcessSync.callCount).eq(1); - expect(gitClient._execChildProcessSync.args[0][0]).eq(TEST_COMMAND[0]); - }); - - it('| test git add fails', () => { - // setup - const gitClient = new GitClient(TEST_PROJECT_PATH, TEST_VERBOSITY_OPTIONS_DEBUG); - sinon.stub(gitClient, '_execChildProcessSync').throws(new CLiError(`${TEST_ERROR}`)); - // call & verify - expect(() => gitClient.add(TEST_REPO_DIR)).throw(CLiError, `CliError: ${TEST_ERROR}`); - }); - }); - - describe('# git deleteBranch', () => { - const TEST_BRANCH = 'dev'; - const TEST_COMMAND = [`git branch -d ${TEST_BRANCH}`]; - - afterEach(() => { - sinon.restore(); - }); - - it('| test git delete execute commands correctly ', () => { - // setup - const gitClient = new GitClient(TEST_PROJECT_PATH, TEST_VERBOSITY_OPTIONS); - sinon.stub(gitClient, '_execChildProcessSync'); - // call - gitClient.deleteBranch(TEST_BRANCH); - // verify - expect(gitClient._execChildProcessSync.callCount).eq(1); - expect(gitClient._execChildProcessSync.args[0][0]).eq(TEST_COMMAND[0]); - }); - - it('| test git add fails', () => { - // setup - const gitClient = new GitClient(TEST_PROJECT_PATH, TEST_VERBOSITY_OPTIONS_DEBUG); - sinon.stub(gitClient, '_execChildProcessSync').throws(new CLiError(`${TEST_ERROR}`)); - // call & verify - expect(() => gitClient.deleteBranch(TEST_BRANCH)).throw(CLiError, `CliError: ${TEST_ERROR}`); - }); - }); - - describe('# git merge', () => { - const TEST_BRANCH = 'dev'; - const TEST_COMMAND = [`git merge ${TEST_BRANCH}`]; - - afterEach(() => { - sinon.restore(); - }); - - it('| test git merge execute commands correctly ', () => { - // setup - const gitClient = new GitClient(TEST_PROJECT_PATH, TEST_VERBOSITY_OPTIONS); - sinon.stub(gitClient, '_execChildProcessSync'); - // call - gitClient.merge(TEST_BRANCH); - // verify - expect(gitClient._execChildProcessSync.callCount).eq(1); - expect(gitClient._execChildProcessSync.args[0][0]).eq(TEST_COMMAND[0]); - }); - - it('| test git merge fails', () => { - // setup - const gitClient = new GitClient(TEST_PROJECT_PATH, TEST_VERBOSITY_OPTIONS_DEBUG); - sinon.stub(gitClient, '_execChildProcessSync').throws(new CLiError(`${TEST_ERROR}`)); - // call & verify - expect(() => gitClient.merge(TEST_BRANCH)).throw(CLiError, `CliError: ${TEST_ERROR}`); - }); - }); - - describe('# git shortStatus', () => { - const TEST_COMMAND = 'git status -s'; - - afterEach(() => { - sinon.restore(); - }); - - it('| test git status execute commands correctly ', () => { - // setup - const gitClient = new GitClient(TEST_PROJECT_PATH, TEST_VERBOSITY_OPTIONS); - const TEST_STDOUT = 'stdout'; - sinon.stub(gitClient, '_execChildProcessSync').returns(TEST_STDOUT); - // call - const res = gitClient.shortStatus(); - // verify - expect(res).equal(TEST_STDOUT); - expect(gitClient._execChildProcessSync.callCount).eq(1); - expect(gitClient._execChildProcessSync.args[0][0]).eq(TEST_COMMAND); - }); - - it('| test git status fails', () => { - // setup - const gitClient = new GitClient(TEST_PROJECT_PATH, TEST_VERBOSITY_OPTIONS); - sinon.stub(gitClient, '_execChildProcessSync').throws(new CLiError(`${TEST_ERROR}`)); - // call & verify - expect(() => gitClient.shortStatus()).throw(CLiError, `CliError: ${TEST_ERROR}`); - }); - }); - - describe('# git countCommitDifference', () => { - const COMMIT1 = 'origin/dev'; - const COMMIT2 = 'dev'; - const TEST_COMMAND = `git rev-list --count ${COMMIT1}...${COMMIT2}`; - - afterEach(() => { - sinon.restore(); - }); - - it('| test git rev-list --count execute commands correctly ', () => { - // setup - const gitClient = new GitClient(TEST_PROJECT_PATH, TEST_VERBOSITY_OPTIONS); - const TEST_STDOUT = 'stdout'; - sinon.stub(gitClient, '_execChildProcessSync').returns(TEST_STDOUT); - // call - const res = gitClient.countCommitDifference(COMMIT1, COMMIT2); - // verify - expect(res).equal(TEST_STDOUT); - expect(gitClient._execChildProcessSync.callCount).eq(1); - expect(gitClient._execChildProcessSync.args[0][0]).eq(TEST_COMMAND); - }); - - it('| test git rev-list --count fails', () => { - // setup - const gitClient = new GitClient(TEST_PROJECT_PATH, TEST_VERBOSITY_OPTIONS_DEBUG); - sinon.stub(gitClient, '_execChildProcessSync').throws(new CLiError(`${TEST_ERROR}`)); - // call & verify - expect(() => gitClient.countCommitDifference(COMMIT1, COMMIT2)).throw(CLiError, `CliError: ${TEST_ERROR}`); - }); - }); - - describe('# test setupGitIgnore', () => { - const TEST_FILES_TO_IGNORE = ['.file_one', '.file_two']; - const TEST_GIT_IGNORE = 'TEST_GIT_IGNORE'; - const gitClient = new GitClient(TEST_PROJECT_PATH, TEST_VERBOSITY_OPTIONS); - - afterEach(() => { - sinon.restore(); - }); - - it('| test .gitignore file does not exist ', () => { - // setup - sinon.stub(path, 'join').returns(TEST_GIT_IGNORE); - sinon.stub(fs, 'existsSync').returns(false); - const writeFileStub = sinon.stub(fs, 'writeFileSync'); - sinon.stub(gitClient, 'add'); - // call - gitClient.setupGitIgnore(TEST_FILES_TO_IGNORE); - // verify - expect(writeFileStub.args[0][0]).eq(TEST_GIT_IGNORE); - expect(writeFileStub.args[0][1]).eq('.file_one\n.file_two'); - }); - - it('| test .gitignore file not exists ', () => { - // setup - sinon.stub(path, 'join').returns(TEST_GIT_IGNORE); - sinon.stub(fs, 'existsSync').returns(true); - const writeFileStub = sinon.stub(fs, 'readFileSync').returns('.file_one'); - const appendFileStub = sinon.stub(fs, 'appendFileSync'); - sinon.stub(gitClient, 'add'); - // call - gitClient.setupGitIgnore(TEST_FILES_TO_IGNORE); - // verify - expect(writeFileStub.callCount).eq(1); - expect(appendFileStub.args[0][0]).eq(TEST_GIT_IGNORE); - }); - }); - - describe('# test _execChildProcessSync', () => { - let infoStub; - const TEST_COMMAND = 'TEST_COMMAND'; - - beforeEach(() => { - infoStub = sinon.stub(); - sinon.stub(Messenger, 'getInstance').returns({ - info: infoStub - }); - }); - - afterEach(() => { - sinon.restore(); - }); - - it('| test _execChildProcessSync succeeds ', () => { - // setup - const childProcessStub = { - execSync: () => {} - }; - const proxyHelper = proxyquire('@src/clients/git-client', { - child_process: childProcessStub - }); - // call - proxyHelper.prototype._execChildProcessSync(TEST_COMMAND, TEST_VERBOSITY_OPTIONS_DEBUG); - // verify - expect(infoStub.args[0][0]).eq(TEST_COMMAND); - }); - - it('| test _execChildProcessSync fails ', () => { - // setup - const childProcessStub = { - execSync: () => { throw new Error(TEST_ERROR); } - }; - const proxyHelper = proxyquire('@src/clients/git-client', { - child_process: childProcessStub - }); - // call & verify - expect(() => proxyHelper.prototype._execChildProcessSync(TEST_COMMAND, TEST_VERBOSITY_OPTIONS)) - .throw(Error, `${TEST_ERROR}`); - }); + it("| test _execChildProcessSync fails ", () => { + // setup + const childProcessStub = { + execSync: () => { + throw new Error(TEST_ERROR); + }, + }; + const proxyHelper = proxyquire("../../../lib/clients/git-client", { + child_process: childProcessStub, + }); + // call & verify + expect(() => proxyHelper.prototype._execChildProcessSync(TEST_COMMAND, TEST_VERBOSITY_OPTIONS)).throw(Error, `${TEST_ERROR}`); }); + }); }); diff --git a/test/unit/clients/http-client-test.js b/test/unit/clients/http-client-test.js index 95fd3f5c..a099068d 100644 --- a/test/unit/clients/http-client-test.js +++ b/test/unit/clients/http-client-test.js @@ -1,276 +1,276 @@ -const { expect } = require('chai'); -const sinon = require('sinon'); -const proxyquire = require('proxyquire'); +const {expect} = require("chai"); +const sinon = require("sinon"); +const proxyquire = require("proxyquire"); -const httpClient = require('@src/clients/http-client'); -const urlUtility = require('@src/utils/url-utils'); -const logger = require('@src/utils/logger-utility'); -const CONSTANTS = require('@src/utils/constants'); +const httpClient = require("../../../lib/clients/http-client"); +const urlUtility = require("../../../lib/utils/url-utils"); +const logger = require("../../../lib/utils/logger-utility"); +const CONSTANTS = require("../../../lib/utils/constants"); -describe('Clients test - cli http request client', () => { - const VALID_OPTIONS = { url: 'https://test.com' }; - const BLANK_URL_OPTIONS = { url: ' ' }; - const INVALID_URL_OPTIONS = { url: 'https//test.com' }; - const INVALID_OPERATION = {}; - const VALID_OPERATION = 'valid-operation'; - const TEST_UPLOAD_URL = 'https://upload.url.com'; - const TEST_PAYLOAD = 'payload'; +describe("Clients test - cli http request client", () => { + const VALID_OPTIONS = {url: "https://test.com"}; + const BLANK_URL_OPTIONS = {url: " "}; + const INVALID_URL_OPTIONS = {url: "https//test.com"}; + const INVALID_OPERATION = {}; + const VALID_OPERATION = "valid-operation"; + const TEST_UPLOAD_URL = "https://upload.url.com"; + const TEST_PAYLOAD = "payload"; - describe('# input parameter validation', () => { - it('| input operation is not a string, expect fatal error', (done) => { - // call - httpClient.request(VALID_OPTIONS, INVALID_OPERATION, false, (err) => { - // verify - expect(err).equal('[Fatal]: CLI request must have a non-empty operation name.'); - done(); - }); - }); + describe("# input parameter validation", () => { + it("| input operation is not a string, expect fatal error", (done) => { + // call + httpClient.request(VALID_OPTIONS, INVALID_OPERATION, false, (err) => { + // verify + expect(err).equal("[Fatal]: CLI request must have a non-empty operation name."); + done(); + }); + }); - it('| input operation url is a blank string, expect fatal error', (done) => { - // call - httpClient.request(BLANK_URL_OPTIONS, VALID_OPERATION, false, (err) => { - // verify - expect(err).equal(`[Fatal]: Invalid URL:${BLANK_URL_OPTIONS.url}. CLI request must call with valid url.`); - done(); - }); - }); + it("| input operation url is a blank string, expect fatal error", (done) => { + // call + httpClient.request(BLANK_URL_OPTIONS, VALID_OPERATION, false, (err) => { + // verify + expect(err).equal(`[Fatal]: Invalid URL:${BLANK_URL_OPTIONS.url}. CLI request must call with valid url.`); + done(); + }); + }); - it('| input operation url is not a valid url, expect fatal error', (done) => { - // setup - sinon.stub(urlUtility, 'isValidUrl'); - urlUtility.isValidUrl.withArgs(INVALID_URL_OPTIONS).returns(false); - // call - httpClient.request(INVALID_URL_OPTIONS, VALID_OPERATION, false, (err) => { - // verify - expect(err).equal(`[Fatal]: Invalid URL:${INVALID_URL_OPTIONS.url}. CLI request must call with valid url.`); - urlUtility.isValidUrl.restore(); - done(); - }); - }); + it("| input operation url is not a valid url, expect fatal error", (done) => { + // setup + sinon.stub(urlUtility, "isValidUrl"); + urlUtility.isValidUrl.withArgs(INVALID_URL_OPTIONS).returns(false); + // call + httpClient.request(INVALID_URL_OPTIONS, VALID_OPERATION, false, (err) => { + // verify + expect(err).equal(`[Fatal]: Invalid URL:${INVALID_URL_OPTIONS.url}. CLI request must call with valid url.`); + urlUtility.isValidUrl.restore(); + done(); + }); }); + }); - describe('# embedding user-agent', () => { - let stubRequest; - let proxyhttpClient; - let initialDownstreamClient; + describe("# embedding user-agent", () => { + let stubRequest; + let proxyhttpClient; + let initialDownstreamClient; - before(() => { - initialDownstreamClient = process.env.ASK_DOWNSTREAM_CLIENT; - stubRequest = sinon.stub(); - proxyhttpClient = proxyquire('@src/clients/http-client', { request: stubRequest }); - }); + before(() => { + initialDownstreamClient = process.env.ASK_DOWNSTREAM_CLIENT; + stubRequest = sinon.stub(); + proxyhttpClient = proxyquire("../../../lib/clients/http-client", {request: stubRequest}); + }); - it('| no downstream client, expect CLI user agent', (done) => { - // setup - const VALID_OPTION_WITH_HEADERS = { - url: 'https://test.com', - headers: {} - }; - process.env.ASK_DOWNSTREAM_CLIENT = ''; - stubRequest.callsFake(() => {}); - // call - proxyhttpClient.request(VALID_OPTION_WITH_HEADERS, VALID_OPERATION, true, () => {}); - // verify - expect(stubRequest.args[0][0]).to.have.property('headers'); - expect(stubRequest.args[0][0].headers).to.have.property('User-Agent'); - expect(stubRequest.args[0][0].headers['User-Agent'].startsWith('ask-cli')).equal(true); - done(); - }); + it("| no downstream client, expect CLI user agent", (done) => { + // setup + const VALID_OPTION_WITH_HEADERS = { + url: "https://test.com", + headers: {}, + }; + process.env.ASK_DOWNSTREAM_CLIENT = ""; + stubRequest.callsFake(() => {}); + // call + proxyhttpClient.request(VALID_OPTION_WITH_HEADERS, VALID_OPERATION, true, () => {}); + // verify + expect(stubRequest.args[0][0]).to.have.property("headers"); + expect(stubRequest.args[0][0].headers).to.have.property("User-Agent"); + expect(stubRequest.args[0][0].headers["User-Agent"].startsWith("ask-cli")).equal(true); + done(); + }); - it('| downstream client environmental variable exists, expect downstream user agent', (done) => { - // setup - const TEST_DOWNSTREAM = 'test_downstream'; - process.env.ASK_DOWNSTREAM_CLIENT = TEST_DOWNSTREAM; - stubRequest.callsFake(() => {}); - // call - proxyhttpClient.request(VALID_OPTIONS, VALID_OPERATION, false, () => {}); - // verfiy - expect(stubRequest.args[0][0]).to.have.property('headers'); - expect(stubRequest.args[0][0].headers).to.have.property('User-Agent'); - expect(stubRequest.args[0][0].headers['User-Agent'].startsWith(TEST_DOWNSTREAM)).equal(true); - done(); - }); + it("| downstream client environmental variable exists, expect downstream user agent", (done) => { + // setup + const TEST_DOWNSTREAM = "test_downstream"; + process.env.ASK_DOWNSTREAM_CLIENT = TEST_DOWNSTREAM; + stubRequest.callsFake(() => {}); + // call + proxyhttpClient.request(VALID_OPTIONS, VALID_OPERATION, false, () => {}); + // verfiy + expect(stubRequest.args[0][0]).to.have.property("headers"); + expect(stubRequest.args[0][0].headers).to.have.property("User-Agent"); + expect(stubRequest.args[0][0].headers["User-Agent"].startsWith(TEST_DOWNSTREAM)).equal(true); + done(); + }); - afterEach(() => { - stubRequest.reset(); - }); + afterEach(() => { + stubRequest.reset(); + }); - after(() => { - process.env.ASK_DOWNSTREAM_CLIENT = initialDownstreamClient; - }); + after(() => { + process.env.ASK_DOWNSTREAM_CLIENT = initialDownstreamClient; }); + }); - describe('# embedding proxyUrl', () => { - let stubRequest; - let proxyhttpClient; - let initialProxyUrl; + describe("# embedding proxyUrl", () => { + let stubRequest; + let proxyhttpClient; + let initialProxyUrl; - beforeEach(() => { - initialProxyUrl = process.env.ASK_CLI_PROXY; - stubRequest = sinon.stub(); - proxyhttpClient = proxyquire('@src/clients/http-client', { request: stubRequest }); - }); + beforeEach(() => { + initialProxyUrl = process.env.ASK_CLI_PROXY; + stubRequest = sinon.stub(); + proxyhttpClient = proxyquire("../../../lib/clients/http-client", {request: stubRequest}); + }); - it('| proxyUrl is added to request options', (done) => { - // setup - process.env.ASK_CLI_PROXY = 'proxyUrl'; - stubRequest.callsFake(() => {}); - // call - proxyhttpClient.request(VALID_OPTIONS, VALID_OPERATION, true, () => {}); - // verfiy - expect(stubRequest.args[0][0]).to.have.property('proxy'); - expect(stubRequest.args[0][0].proxy).equal('proxyUrl'); - done(); - // reset - }); + it("| proxyUrl is added to request options", (done) => { + // setup + process.env.ASK_CLI_PROXY = "proxyUrl"; + stubRequest.callsFake(() => {}); + // call + proxyhttpClient.request(VALID_OPTIONS, VALID_OPERATION, true, () => {}); + // verfiy + expect(stubRequest.args[0][0]).to.have.property("proxy"); + expect(stubRequest.args[0][0].proxy).equal("proxyUrl"); + done(); + // reset + }); - afterEach(() => { - stubRequest.reset(); - process.env.ASK_DOWNSTREAM_CLIENT = initialProxyUrl; - }); + afterEach(() => { + stubRequest.reset(); + process.env.ASK_DOWNSTREAM_CLIENT = initialProxyUrl; }); + }); - describe('# call request correctly', () => { - let stubRequest; - let proxyhttpClient; + describe("# call request correctly", () => { + let stubRequest; + let proxyhttpClient; - before(() => { - stubRequest = sinon.stub(); - proxyhttpClient = proxyquire('@src/clients/http-client', { request: stubRequest }); - }); + before(() => { + stubRequest = sinon.stub(); + proxyhttpClient = proxyquire("../../../lib/clients/http-client", {request: stubRequest}); + }); - it('| request error occurs, expect error message', (done) => { - // setup - stubRequest.callsArgWith(1, 'error', null); - // call - proxyhttpClient.request(VALID_OPTIONS, VALID_OPERATION, false, (err, response) => { - // verify - expect(err).equal(`Failed to make request to ${VALID_OPERATION}.\nError response: error`); - expect(response).equal(undefined); - done(); - }); - }); + it("| request error occurs, expect error message", (done) => { + // setup + stubRequest.callsArgWith(1, "error", null); + // call + proxyhttpClient.request(VALID_OPTIONS, VALID_OPERATION, false, (err, response) => { + // verify + expect(err).equal(`Failed to make request to ${VALID_OPERATION}.\nError response: error`); + expect(response).equal(undefined); + done(); + }); + }); - it('| request with no error and no response, expect error', (done) => { - // setup - stubRequest.callsArgWith(1, null, null); - // call - proxyhttpClient.request(VALID_OPTIONS, VALID_OPERATION, false, (err, response) => { - // verify - expect(err).equal(`Failed to make request to ${VALID_OPERATION}.\nPlease make sure "${VALID_OPTIONS.url}" is responding.`); - expect(response).equal(undefined); - done(); - }); - }); + it("| request with no error and no response, expect error", (done) => { + // setup + stubRequest.callsArgWith(1, null, null); + // call + proxyhttpClient.request(VALID_OPTIONS, VALID_OPERATION, false, (err, response) => { + // verify + expect(err).equal(`Failed to make request to ${VALID_OPERATION}.\nPlease make sure "${VALID_OPTIONS.url}" is responding.`); + expect(response).equal(undefined); + done(); + }); + }); - it('| request with no error and no response statusCode, expect error', (done) => { - // setup - stubRequest.callsArgWith(1, null, { body: 'response' }); - // call - proxyhttpClient.request(VALID_OPTIONS, VALID_OPERATION, false, (err, response) => { - // verify - expect(err).equal(`Failed to access the statusCode from the request to ${VALID_OPERATION}.`); - expect(response).equal(undefined); - done(); - }); - }); + it("| request with no error and no response statusCode, expect error", (done) => { + // setup + stubRequest.callsArgWith(1, null, {body: "response"}); + // call + proxyhttpClient.request(VALID_OPTIONS, VALID_OPERATION, false, (err, response) => { + // verify + expect(err).equal(`Failed to access the statusCode from the request to ${VALID_OPERATION}.`); + expect(response).equal(undefined); + done(); + }); + }); - it('| request with success, expect no error and response', (done) => { - // setup - stubRequest.callsArgWith(1, null, { statusCode: 200 }); - // call - proxyhttpClient.request(VALID_OPTIONS, VALID_OPERATION, false, (err, response) => { - // verify - expect(err).equal(null); - expect(response).deep.equal({ statusCode: 200 }); - done(); - }); - }); + it("| request with success, expect no error and response", (done) => { + // setup + stubRequest.callsArgWith(1, null, {statusCode: 200}); + // call + proxyhttpClient.request(VALID_OPTIONS, VALID_OPERATION, false, (err, response) => { + // verify + expect(err).equal(null); + expect(response).deep.equal({statusCode: 200}); + done(); + }); + }); - it('| request with no error and debug flag, expect logger filled with correct debug info', (done) => { - // setup - const fakeResponse = { - request: { - method: 'method', - href: 'href', - headers: 'request headers', - body: 'body' - }, - headers: 'response headers', - statusCode: 'status code', - statusMessage: 'status message', - body: 'body' - }; - stubRequest.callsArgWith(1, null, fakeResponse); - sinon.stub(logger, 'getInstance'); - const debugStub = sinon.spy(); - logger.getInstance.returns({ - debug: debugStub - }); - // call - proxyhttpClient.request(VALID_OPTIONS, VALID_OPERATION, true, () => { - // verify - const expectedDebugContent = { - activity: VALID_OPERATION, - error: null, - 'request-id': null, - request: { - method: 'method', - url: 'href', - headers: 'request headers', - body: 'body' - }, - response: { - statusCode: 'status code', - statusMessage: 'status message', - headers: 'response headers' - }, - body: 'body' - }; - expect(logger.getInstance.called).equal(true); - expect(debugStub.args[0][0]).deep.equal(expectedDebugContent); - logger.getInstance.restore(); - done(); - }); - }); + it("| request with no error and debug flag, expect logger filled with correct debug info", (done) => { + // setup + const fakeResponse = { + request: { + method: "method", + href: "href", + headers: "request headers", + body: "body", + }, + headers: "response headers", + statusCode: "status code", + statusMessage: "status message", + body: "body", + }; + stubRequest.callsArgWith(1, null, fakeResponse); + sinon.stub(logger, "getInstance"); + const debugStub = sinon.spy(); + logger.getInstance.returns({ + debug: debugStub, + }); + // call + proxyhttpClient.request(VALID_OPTIONS, VALID_OPERATION, true, () => { + // verify + const expectedDebugContent = { + activity: VALID_OPERATION, + error: null, + "request-id": null, + request: { + method: "method", + url: "href", + headers: "request headers", + body: "body", + }, + response: { + statusCode: "status code", + statusMessage: "status message", + headers: "response headers", + }, + body: "body", + }; + expect(logger.getInstance.called).equal(true); + expect(debugStub.args[0][0]).deep.equal(expectedDebugContent); + logger.getInstance.restore(); + done(); + }); }); + }); - describe('# verify upload method', () => { - const stubRequest = sinon.stub(); - const proxyhttpClient = proxyquire('@src/clients/http-client', { request: stubRequest }); + describe("# verify upload method", () => { + const stubRequest = sinon.stub(); + const proxyhttpClient = proxyquire("../../../lib/clients/http-client", {request: stubRequest}); - afterEach(() => { - sinon.restore(); - }); + afterEach(() => { + sinon.restore(); + }); - it('| upload but meet error, expect error callback', (done) => { - // setup - stubRequest.callsArgWith(1, 'uploadErr'); - // test - proxyhttpClient.putByUrl(TEST_UPLOAD_URL, TEST_PAYLOAD, VALID_OPERATION, false, (err, res) => { - // verify - expect(stubRequest.args[0][0].url).equal(TEST_UPLOAD_URL); - expect(stubRequest.args[0][0].method).equal(CONSTANTS.HTTP_REQUEST.VERB.PUT); - expect(stubRequest.args[0][0].body).equal(TEST_PAYLOAD); - expect(res).equal(undefined); - expect(err).equal(`Failed to make request to ${VALID_OPERATION}.\nError response: uploadErr`); - done(); - }); - }); + it("| upload but meet error, expect error callback", (done) => { + // setup + stubRequest.callsArgWith(1, "uploadErr"); + // test + proxyhttpClient.putByUrl(TEST_UPLOAD_URL, TEST_PAYLOAD, VALID_OPERATION, false, (err, res) => { + // verify + expect(stubRequest.args[0][0].url).equal(TEST_UPLOAD_URL); + expect(stubRequest.args[0][0].method).equal(CONSTANTS.HTTP_REQUEST.VERB.PUT); + expect(stubRequest.args[0][0].body).equal(TEST_PAYLOAD); + expect(res).equal(undefined); + expect(err).equal(`Failed to make request to ${VALID_OPERATION}.\nError response: uploadErr`); + done(); + }); + }); - it('| upload successfully', (done) => { - // setup - stubRequest.callsArgWith(1, null, { statusCode: 202 }); - // test - proxyhttpClient.putByUrl(TEST_UPLOAD_URL, TEST_PAYLOAD, VALID_OPERATION, false, (err, res) => { - // verify - expect(stubRequest.args[0][0].url).equal(TEST_UPLOAD_URL); - expect(stubRequest.args[0][0].method).equal(CONSTANTS.HTTP_REQUEST.VERB.PUT); - expect(stubRequest.args[0][0].body).equal(TEST_PAYLOAD); - expect(err).equal(null); - expect(res).deep.equal({ statusCode: 202 }); - done(); - }); - }); + it("| upload successfully", (done) => { + // setup + stubRequest.callsArgWith(1, null, {statusCode: 202}); + // test + proxyhttpClient.putByUrl(TEST_UPLOAD_URL, TEST_PAYLOAD, VALID_OPERATION, false, (err, res) => { + // verify + expect(stubRequest.args[0][0].url).equal(TEST_UPLOAD_URL); + expect(stubRequest.args[0][0].method).equal(CONSTANTS.HTTP_REQUEST.VERB.PUT); + expect(stubRequest.args[0][0].body).equal(TEST_PAYLOAD); + expect(err).equal(null); + expect(res).deep.equal({statusCode: 202}); + done(); + }); }); + }); }); diff --git a/test/unit/clients/lwa-auth-code-client-test.js b/test/unit/clients/lwa-auth-code-client-test.js index 1389d184..74233d16 100644 --- a/test/unit/clients/lwa-auth-code-client-test.js +++ b/test/unit/clients/lwa-auth-code-client-test.js @@ -1,350 +1,352 @@ -const { expect } = require('chai'); -const sinon = require('sinon'); -const { URL } = require('url'); -const queryString = require('querystring'); -const proxyquire = require('proxyquire'); +const {expect} = require("chai"); +const sinon = require("sinon"); +const {URL} = require("url"); +const queryString = require("querystring"); +const proxyquire = require("proxyquire"); -const httpClient = require('@src/clients/http-client'); -const LWAClient = require('@src/clients/lwa-auth-code-client'); -const CONSTANTS = require('@src/utils/constants'); -const jsonView = require('@src/view/json-view'); +const httpClient = require("../../../lib/clients/http-client"); +const LWAClient = require("../../../lib/clients/lwa-auth-code-client"); +const CONSTANTS = require("../../../lib/utils/constants"); +const jsonView = require("../../../lib/view/json-view"); -describe('# Clients test - LWA OAuth2 client test', () => { - const TEST_BASIC_CONFIGURATION = { - doDebug: false, - state: 'state', - scope: 'scope', - redirectUri: 'redirectUri' - }; - const EMPTY_CONFIG = {}; - const authorizePath = CONSTANTS.LWA.DEFAULT_AUTHORIZE_PATH; - const tokenPath = CONSTANTS.LWA.DEFAULT_TOKEN_PATH; - const authorizeHost = CONSTANTS.LWA.DEFAULT_AUTHORIZE_HOST; - const tokenHost = CONSTANTS.LWA.DEFAULT_TOKEN_HOST; - const DEFAULT_CLIENT_ID = CONSTANTS.LWA.CLI_INTERNAL_ONLY_LWA_CLIENT.CLIENT_ID; - const DEFAULT_CLIENT_CONFIRMATION = CONSTANTS.LWA.CLI_INTERNAL_ONLY_LWA_CLIENT.CLIENT_CONFIRMATION; - const DEFAULT_SCOPE = CONSTANTS.LWA.DEFAULT_SCOPES; - const currentDatePlusHalfAnHour = new Date(new Date(Date.now()).getTime() + (0.5 * 60 * 60 * 1000)).toISOString(); - const POST_REQUEST_METHOD = 'POST'; - const REFRESH_TOKEN_GRANT_TYPE = 'refresh_token'; - const AUTHORIZATION_CODE_GRANT_TYPE = 'authorization_code'; - const TEST_EXPIRES_AT = { - toISOString: () => 'expires_at' - }; - const TEST_REQUEST_RESPONSE_ACCESS_TOKEN = { - statusCode: 200, - body: { - access_token: 'BODY', - expires_in: 3600 - }, - headers: {} - }; - const VALID_AUTH_CODE = 'authCode'; +describe("# Clients test - LWA OAuth2 client test", () => { + const TEST_BASIC_CONFIGURATION = { + doDebug: false, + state: "state", + scope: "scope", + redirectUri: "redirectUri", + }; + const EMPTY_CONFIG = {}; + const authorizePath = CONSTANTS.LWA.DEFAULT_AUTHORIZE_PATH; + const tokenPath = CONSTANTS.LWA.DEFAULT_TOKEN_PATH; + const authorizeHost = CONSTANTS.LWA.DEFAULT_AUTHORIZE_HOST; + const tokenHost = CONSTANTS.LWA.DEFAULT_TOKEN_HOST; + const DEFAULT_CLIENT_ID = CONSTANTS.LWA.CLI_INTERNAL_ONLY_LWA_CLIENT.CLIENT_ID; + const DEFAULT_CLIENT_CONFIRMATION = CONSTANTS.LWA.CLI_INTERNAL_ONLY_LWA_CLIENT.CLIENT_CONFIRMATION; + const DEFAULT_SCOPE = CONSTANTS.LWA.DEFAULT_SCOPES; + const currentDatePlusHalfAnHour = new Date(new Date(Date.now()).getTime() + 0.5 * 60 * 60 * 1000).toISOString(); + const POST_REQUEST_METHOD = "POST"; + const REFRESH_TOKEN_GRANT_TYPE = "refresh_token"; + const AUTHORIZATION_CODE_GRANT_TYPE = "authorization_code"; + const TEST_EXPIRES_AT = { + toISOString: () => "expires_at", + }; + const TEST_REQUEST_RESPONSE_ACCESS_TOKEN = { + statusCode: 200, + body: { + access_token: "BODY", + expires_in: 3600, + }, + headers: {}, + }; + const VALID_AUTH_CODE = "authCode"; - const VALID_ACCESS_TOKEN = { - access_token: 'accessToken', - refresh_token: 'refreshToken', - token_type: 'bearer', - expires_in: 3600, - expires_at: currentDatePlusHalfAnHour - }; - const INVALID_ACCESS_TOKEN = { - expires_at: new Date('05 October 2011 14:48 UTC').toISOString() - }; + const VALID_ACCESS_TOKEN = { + access_token: "accessToken", + refresh_token: "refreshToken", + token_type: "bearer", + expires_in: 3600, + expires_at: currentDatePlusHalfAnHour, + }; + const INVALID_ACCESS_TOKEN = { + expires_at: new Date("05 October 2011 14:48 UTC").toISOString(), + }; - describe('# inspect correctness for constructor', () => { - it('| initiate as a LWAClient class', () => { - // call - const lwaClient = new LWAClient(TEST_BASIC_CONFIGURATION); - // verify - expect(lwaClient).to.be.instanceOf(LWAClient); - expect(lwaClient.config.doDebug).equal(false); - expect(lwaClient.config.authorizePath).equal(authorizePath); - expect(lwaClient.config.tokenPath).equal(tokenPath); - }); + describe("# inspect correctness for constructor", () => { + it("| initiate as a LWAClient class", () => { + // call + const lwaClient = new LWAClient(TEST_BASIC_CONFIGURATION); + // verify + expect(lwaClient).to.be.instanceOf(LWAClient); + expect(lwaClient.config.doDebug).equal(false); + expect(lwaClient.config.authorizePath).equal(authorizePath); + expect(lwaClient.config.tokenPath).equal(tokenPath); }); + }); - describe('# test generateAuthorizeUrl', () => { - beforeEach(() => { - sinon.useFakeTimers(Date.UTC(2016, 2, 15)); - }); + describe("# test generateAuthorizeUrl", () => { + beforeEach(() => { + sinon.useFakeTimers(Date.UTC(2016, 2, 15)); + }); - it('| test proper authorization code uri generation', () => { - // setup - const CONFIG = { - doDebug: false, - scope: 'scope', - redirectUri: 'redirectUri' - }; - const queryParamsUri = `response_type=code&client_id=${DEFAULT_CLIENT_ID}&state=1458000000000&scope=scope&redirect_uri=redirectUri`; + it("| test proper authorization code uri generation", () => { + // setup + const CONFIG = { + doDebug: false, + scope: "scope", + redirectUri: "redirectUri", + }; + const queryParamsUri = `response_type=code&client_id=${DEFAULT_CLIENT_ID}&state=1458000000000&scope=scope&redirect_uri=redirectUri`; - const uri = `${authorizeHost}${authorizePath}?${queryParamsUri}`; - const lwaClient = new LWAClient(CONFIG); - // call & verify - expect(lwaClient.generateAuthorizeUrl()).equal(uri); - }); + const uri = `${authorizeHost}${authorizePath}?${queryParamsUri}`; + const lwaClient = new LWAClient(CONFIG); + // call & verify + expect(lwaClient.generateAuthorizeUrl()).equal(uri); + }); - it('| test authorization code uri generation with blank scope and redirectUri', () => { - // setup - sinon.stub(Date, 'now'); - Date.now.returns('date'); - const CONFIG = { - doDebug: false, - scope: '', - redirectUri: '', - state: '' - }; - const outQueryParams = { - response_type: 'code', - client_id: DEFAULT_CLIENT_ID, - state: 'date', - scope: DEFAULT_SCOPE - }; + it("| test authorization code uri generation with blank scope and redirectUri", () => { + // setup + sinon.stub(Date, "now"); + Date.now.returns("date"); + const CONFIG = { + doDebug: false, + scope: "", + redirectUri: "", + state: "", + }; + const outQueryParams = { + response_type: "code", + client_id: DEFAULT_CLIENT_ID, + state: "date", + scope: DEFAULT_SCOPE, + }; - const uri = `${authorizeHost}${authorizePath}?${queryString.stringify(outQueryParams)}`; - const lwaClient = new LWAClient(CONFIG); - // call & verify - expect(lwaClient.generateAuthorizeUrl()).equal(uri); - }); + const uri = `${authorizeHost}${authorizePath}?${queryString.stringify(outQueryParams)}`; + const lwaClient = new LWAClient(CONFIG); + // call & verify + expect(lwaClient.generateAuthorizeUrl()).equal(uri); + }); - afterEach(() => { - sinon.restore(); - }); + afterEach(() => { + sinon.restore(); }); + }); - describe('# test isValidToken', () => { - it('| access token is valid', () => { - // setup - const lwaClient = new LWAClient(EMPTY_CONFIG); - // call & verify - expect(lwaClient.isValidToken(VALID_ACCESS_TOKEN)).equal(true); - }); + describe("# test isValidToken", () => { + it("| access token is valid", () => { + // setup + const lwaClient = new LWAClient(EMPTY_CONFIG); + // call & verify + expect(lwaClient.isValidToken(VALID_ACCESS_TOKEN)).equal(true); + }); - it('| access token is invalid', () => { - // setup - const lwaClient = new LWAClient(EMPTY_CONFIG); - // call & verify - expect(lwaClient.isValidToken(INVALID_ACCESS_TOKEN)).equal(false); - }); + it("| access token is invalid", () => { + // setup + const lwaClient = new LWAClient(EMPTY_CONFIG); + // call & verify + expect(lwaClient.isValidToken(INVALID_ACCESS_TOKEN)).equal(false); }); + }); - describe('# test refreshToken', () => { - beforeEach(() => { - sinon.stub(httpClient, 'request'); - sinon.stub(LWAClient.prototype, '_getExpiresAt'); - }); + describe("# test refreshToken", () => { + beforeEach(() => { + sinon.stub(httpClient, "request"); + sinon.stub(LWAClient.prototype, "_getExpiresAt"); + }); - it('| httpClient request fails while refreshing access token', (done) => { - // setup - const TEST_ERROR = 'error'; - const lwaClient = new LWAClient(TEST_BASIC_CONFIGURATION); - httpClient.request.callsArgWith(3, TEST_ERROR); - // call - lwaClient.refreshToken(VALID_ACCESS_TOKEN, (err, res) => { - // verify - expect(err).equal(TEST_ERROR); - expect(res).equal(undefined); - done(); - }); - }); + it("| httpClient request fails while refreshing access token", (done) => { + // setup + const TEST_ERROR = "error"; + const lwaClient = new LWAClient(TEST_BASIC_CONFIGURATION); + httpClient.request.callsArgWith(3, TEST_ERROR); + // call + lwaClient.refreshToken(VALID_ACCESS_TOKEN, (err, res) => { + // verify + expect(err).equal(TEST_ERROR); + expect(res).equal(undefined); + done(); + }); + }); - it('| httpClient response contains failure message, expect process fails with correct message', (done) => { - // setup - const TEST_ERROR = 'error'; - const TEST_ERROR_RESPONSE = { - body: { error: TEST_ERROR } - }; - const lwaClient = new LWAClient(TEST_BASIC_CONFIGURATION); - httpClient.request.callsArgWith(3, undefined, TEST_ERROR_RESPONSE); - // call - lwaClient.refreshToken(VALID_ACCESS_TOKEN, (err, res) => { - // verify - expect(err).equal(`Refresh LWA tokens failed, please run "ask configure" to manually update your tokens. Error: ${TEST_ERROR}.`); - expect(res).equal(undefined); - done(); - }); - }); + it("| httpClient response contains failure message, expect process fails with correct message", (done) => { + // setup + const TEST_ERROR = "error"; + const TEST_ERROR_RESPONSE = { + body: {error: TEST_ERROR}, + }; + const lwaClient = new LWAClient(TEST_BASIC_CONFIGURATION); + httpClient.request.callsArgWith(3, undefined, TEST_ERROR_RESPONSE); + // call + lwaClient.refreshToken(VALID_ACCESS_TOKEN, (err, res) => { + // verify + expect(err).equal(`Refresh LWA tokens failed, please run "ask configure" to manually update your tokens. Error: ${TEST_ERROR}.`); + expect(res).equal(undefined); + done(); + }); + }); - it('| httpClient response is invalid, expect process fails with correct message', (done) => { - // setup - const TEST_INVALID_RESPONSE = { - body: { - access_token: 'token' - } - }; - const lwaClient = new LWAClient(TEST_BASIC_CONFIGURATION); - httpClient.request.callsArgWith(3, undefined, TEST_INVALID_RESPONSE); - // call - lwaClient.refreshToken(VALID_ACCESS_TOKEN, (err, res) => { - // verify - expect(err).equal(`Received invalid response body from LWA without "expires_in":\n${jsonView.toString(TEST_INVALID_RESPONSE.body)}`); - expect(res).equal(undefined); - done(); - }); - }); + it("| httpClient response is invalid, expect process fails with correct message", (done) => { + // setup + const TEST_INVALID_RESPONSE = { + body: { + access_token: "token", + }, + }; + const lwaClient = new LWAClient(TEST_BASIC_CONFIGURATION); + httpClient.request.callsArgWith(3, undefined, TEST_INVALID_RESPONSE); + // call + lwaClient.refreshToken(VALID_ACCESS_TOKEN, (err, res) => { + // verify + expect(err).equal( + `Received invalid response body from LWA without "expires_in":\n${jsonView.toString(TEST_INVALID_RESPONSE.body)}`, + ); + expect(res).equal(undefined); + done(); + }); + }); - it('| refreshing access token successful', (done) => { - // setup - const lwaClient = new LWAClient(TEST_BASIC_CONFIGURATION); - httpClient.request.callsArgWith(3, undefined, TEST_REQUEST_RESPONSE_ACCESS_TOKEN); - LWAClient.prototype._getExpiresAt.returns(TEST_EXPIRES_AT); - // call - lwaClient.refreshToken(VALID_ACCESS_TOKEN, (err, res) => { - const expectedOptions = { - url: `${new URL(tokenPath, tokenHost)}`, - method: POST_REQUEST_METHOD, - body: { - grant_type: REFRESH_TOKEN_GRANT_TYPE, - refresh_token: 'refreshToken', - client_id: DEFAULT_CLIENT_ID, - client_secret: DEFAULT_CLIENT_CONFIRMATION - }, - json: true - }; - // verify - expect(httpClient.request.args[0][0]).deep.equal(expectedOptions); - expect(httpClient.request.args[0][2]).equal(false); - expect(err).equal(null); - expect(res).deep.equal({ - access_token: 'BODY', - expires_in: 3600, - expires_at: 'expires_at' - }); - done(); - }); + it("| refreshing access token successful", (done) => { + // setup + const lwaClient = new LWAClient(TEST_BASIC_CONFIGURATION); + httpClient.request.callsArgWith(3, undefined, TEST_REQUEST_RESPONSE_ACCESS_TOKEN); + LWAClient.prototype._getExpiresAt.returns(TEST_EXPIRES_AT); + // call + lwaClient.refreshToken(VALID_ACCESS_TOKEN, (err, res) => { + const expectedOptions = { + url: `${new URL(tokenPath, tokenHost)}`, + method: POST_REQUEST_METHOD, + body: { + grant_type: REFRESH_TOKEN_GRANT_TYPE, + refresh_token: "refreshToken", + client_id: DEFAULT_CLIENT_ID, + client_secret: DEFAULT_CLIENT_CONFIRMATION, + }, + json: true, + }; + // verify + expect(httpClient.request.args[0][0]).deep.equal(expectedOptions); + expect(httpClient.request.args[0][2]).equal(false); + expect(err).equal(null); + expect(res).deep.equal({ + access_token: "BODY", + expires_in: 3600, + expires_at: "expires_at", }); + done(); + }); + }); - afterEach(() => { - sinon.restore(); - }); + afterEach(() => { + sinon.restore(); }); + }); - describe('# test getAccessTokenUsingAuthCode', () => { - beforeEach(() => { - sinon.stub(httpClient, 'request'); - sinon.stub(LWAClient.prototype, '_getExpiresAt'); - }); + describe("# test getAccessTokenUsingAuthCode", () => { + beforeEach(() => { + sinon.stub(httpClient, "request"); + sinon.stub(LWAClient.prototype, "_getExpiresAt"); + }); - it('| fetch access token successful using auth code', (done) => { - // setup - const lwaClient = new LWAClient(TEST_BASIC_CONFIGURATION); - httpClient.request.callsArgWith(3, null, TEST_REQUEST_RESPONSE_ACCESS_TOKEN); - LWAClient.prototype._getExpiresAt.returns(TEST_EXPIRES_AT); - // call - lwaClient.getAccessTokenUsingAuthCode(VALID_AUTH_CODE, (err, res) => { - const expectedOptions = { - url: `${new URL(tokenPath, tokenHost)}`, - method: POST_REQUEST_METHOD, - body: { - code: 'authCode', - grant_type: AUTHORIZATION_CODE_GRANT_TYPE, - redirect_uri: 'redirectUri', - client_id: DEFAULT_CLIENT_ID, - client_secret: DEFAULT_CLIENT_CONFIRMATION - }, - json: true - }; - // verify - expect(httpClient.request.args[0][0]).deep.equal(expectedOptions); - expect(httpClient.request.args[0][2]).equal(false); - expect(err).equal(null); - expect(res).deep.equal({ - access_token: 'BODY', - expires_in: 3600, - expires_at: 'expires_at' - }); - done(); - }); + it("| fetch access token successful using auth code", (done) => { + // setup + const lwaClient = new LWAClient(TEST_BASIC_CONFIGURATION); + httpClient.request.callsArgWith(3, null, TEST_REQUEST_RESPONSE_ACCESS_TOKEN); + LWAClient.prototype._getExpiresAt.returns(TEST_EXPIRES_AT); + // call + lwaClient.getAccessTokenUsingAuthCode(VALID_AUTH_CODE, (err, res) => { + const expectedOptions = { + url: `${new URL(tokenPath, tokenHost)}`, + method: POST_REQUEST_METHOD, + body: { + code: "authCode", + grant_type: AUTHORIZATION_CODE_GRANT_TYPE, + redirect_uri: "redirectUri", + client_id: DEFAULT_CLIENT_ID, + client_secret: DEFAULT_CLIENT_CONFIRMATION, + }, + json: true, + }; + // verify + expect(httpClient.request.args[0][0]).deep.equal(expectedOptions); + expect(httpClient.request.args[0][2]).equal(false); + expect(err).equal(null); + expect(res).deep.equal({ + access_token: "BODY", + expires_in: 3600, + expires_at: "expires_at", }); + done(); + }); + }); - it('| Failure while fetching access token using auth code', (done) => { - // setup - const TEST_ERROR = 'error'; - const lwaClient = new LWAClient(TEST_BASIC_CONFIGURATION); - httpClient.request.callsArgWith(3, TEST_ERROR); - // call - lwaClient.getAccessTokenUsingAuthCode(VALID_AUTH_CODE, (err, res) => { - // verify - expect(err).equal(TEST_ERROR); - expect(res).equal(undefined); - done(); - }); - }); + it("| Failure while fetching access token using auth code", (done) => { + // setup + const TEST_ERROR = "error"; + const lwaClient = new LWAClient(TEST_BASIC_CONFIGURATION); + httpClient.request.callsArgWith(3, TEST_ERROR); + // call + lwaClient.getAccessTokenUsingAuthCode(VALID_AUTH_CODE, (err, res) => { + // verify + expect(err).equal(TEST_ERROR); + expect(res).equal(undefined); + done(); + }); + }); - afterEach(() => { - sinon.restore(); - }); + afterEach(() => { + sinon.restore(); }); + }); - describe('# test _handleDefaultLwaAuthCodeConfiguration', () => { - let initialClientId; - let initialClientConfirmation; + describe("# test _handleDefaultLwaAuthCodeConfiguration", () => { + let initialClientId; + let initialClientConfirmation; - beforeEach(() => { - initialClientId = process.env.ASK_LWA_CLIENT_ID; - initialClientConfirmation = process.env.ASK_LWA_CLIENT_CONFIRMATION; - }); + beforeEach(() => { + initialClientId = process.env.ASK_LWA_CLIENT_ID; + initialClientConfirmation = process.env.ASK_LWA_CLIENT_CONFIRMATION; + }); - it('| test default value setting in case of missing config values', () => { - // call - const lwaClient = new LWAClient(EMPTY_CONFIG); - // verify - expect(lwaClient.config.clientId).equal(DEFAULT_CLIENT_ID); - expect(lwaClient.config.clientConfirmation).equal(DEFAULT_CLIENT_CONFIRMATION); - expect(lwaClient.config.authorizeHost).equal(authorizeHost); - expect(lwaClient.config.tokenHost).equal(tokenHost); - }); + it("| test default value setting in case of missing config values", () => { + // call + const lwaClient = new LWAClient(EMPTY_CONFIG); + // verify + expect(lwaClient.config.clientId).equal(DEFAULT_CLIENT_ID); + expect(lwaClient.config.clientConfirmation).equal(DEFAULT_CLIENT_CONFIRMATION); + expect(lwaClient.config.authorizeHost).equal(authorizeHost); + expect(lwaClient.config.tokenHost).equal(tokenHost); + }); - it('| test default value setting in case of non-empty config values', () => { - // setup - const NON_EMPTY_CONFIG = { - clientId: 'clientId', - clientConfirmation: 'clientConfirmation', - scope: 'scope', - state: 'state' - }; - // call - const lwaClient = new LWAClient(NON_EMPTY_CONFIG); - // verify - expect(lwaClient.config.clientId).equal('clientId'); - expect(lwaClient.config.clientConfirmation).equal('clientConfirmation'); - expect(lwaClient.config.scope).equal('scope'); - expect(lwaClient.config.state).equal('state'); - }); + it("| test default value setting in case of non-empty config values", () => { + // setup + const NON_EMPTY_CONFIG = { + clientId: "clientId", + clientConfirmation: "clientConfirmation", + scope: "scope", + state: "state", + }; + // call + const lwaClient = new LWAClient(NON_EMPTY_CONFIG); + // verify + expect(lwaClient.config.clientId).equal("clientId"); + expect(lwaClient.config.clientConfirmation).equal("clientConfirmation"); + expect(lwaClient.config.scope).equal("scope"); + expect(lwaClient.config.state).equal("state"); + }); - it('| test default value setting in case of undefined config values', () => { - // setup - const INVALID_CONFIG = { - clientId: undefined, - clientConfirmation: undefined - }; - process.env.ASK_LWA_CLIENT_ID = 'envClientId'; - process.env.ASK_LWA_CLIENT_CONFIRMATION = 'envClientConfirmation'; - // call - const lwaClient = new LWAClient(INVALID_CONFIG); - // verify - expect(lwaClient.config.clientId).equal(process.env.ASK_LWA_CLIENT_ID); - expect(lwaClient.config.clientConfirmation).equal(process.env.ASK_LWA_CLIENT_CONFIRMATION); - }); + it("| test default value setting in case of undefined config values", () => { + // setup + const INVALID_CONFIG = { + clientId: undefined, + clientConfirmation: undefined, + }; + process.env.ASK_LWA_CLIENT_ID = "envClientId"; + process.env.ASK_LWA_CLIENT_CONFIRMATION = "envClientConfirmation"; + // call + const lwaClient = new LWAClient(INVALID_CONFIG); + // verify + expect(lwaClient.config.clientId).equal(process.env.ASK_LWA_CLIENT_ID); + expect(lwaClient.config.clientConfirmation).equal(process.env.ASK_LWA_CLIENT_CONFIRMATION); + }); - afterEach(() => { - process.env.ASK_LWA_CLIENT_ID = initialClientId; - process.env.ASK_LWA_CLIENT_CONFIRMATION = initialClientConfirmation; - sinon.restore(); - }); + afterEach(() => { + process.env.ASK_LWA_CLIENT_ID = initialClientId; + process.env.ASK_LWA_CLIENT_CONFIRMATION = initialClientConfirmation; + sinon.restore(); }); + }); - describe('# test _getExpiresAt', () => { - it('| calls addSeconds with expireIn to data.now', () => { - // setup - const TEST_EXPIRES_IN = 'expires_in'; - const addSecondsStub = sinon.stub(); - const proxyLwaClient = proxyquire('@src/clients/lwa-auth-code-client', { - 'date-fns/addSeconds': addSecondsStub - }); - addSecondsStub.returns(TEST_EXPIRES_AT); - // call & verify - expect(proxyLwaClient.prototype._getExpiresAt(TEST_EXPIRES_IN)).equal(TEST_EXPIRES_AT); - }); + describe("# test _getExpiresAt", () => { + it("| calls addSeconds with expireIn to data.now", () => { + // setup + const TEST_EXPIRES_IN = "expires_in"; + const addSecondsStub = sinon.stub(); + const proxyLwaClient = proxyquire("../../../lib/clients/lwa-auth-code-client", { + "date-fns/addSeconds": addSecondsStub, + }); + addSecondsStub.returns(TEST_EXPIRES_AT); + // call & verify + expect(proxyLwaClient.prototype._getExpiresAt(TEST_EXPIRES_IN)).equal(TEST_EXPIRES_AT); }); + }); }); diff --git a/test/unit/clients/metric-client-test.js b/test/unit/clients/metric-client-test.js deleted file mode 100644 index 4950492e..00000000 --- a/test/unit/clients/metric-client-test.js +++ /dev/null @@ -1,267 +0,0 @@ -const chai = require('chai'); -const uuid = require('uuid/v4'); -const chaiUuid = require('chai-uuid'); -const chaiJsonSchema = require('chai-json-schema'); -const sinon = require('sinon'); -const { METRICS } = require('@src/utils/constants'); -const profileHelper = require('@src/utils/profile-helper'); -const AppConfig = require('@src/model/app-config'); -const { MetricClient, MetricActionResult } = require('@src/clients/metric-client'); -const jsonSchema = require('@test/fixture/ask-devtools-metrics.schema.json'); - -const { expect } = chai; -chai.use(chaiUuid); -chai.use(chaiJsonSchema); - -describe('Clients test - cli metric client', () => { - const getShareUsageStub = sinon.stub(); - const getMachineIdStub = sinon.stub(); - const setMachineIdStub = sinon.stub(); - const writeConfigStub = sinon.stub(); - let isEnvProfileStub; - let configExistsStub; - let shareUsageVariableValue; - - beforeEach(() => { - shareUsageVariableValue = process.env.ASK_SHARE_USAGE; - delete process.env.ASK_SHARE_USAGE; - configExistsStub = sinon.stub(AppConfig, 'configFileExists').returns(true); - isEnvProfileStub = sinon.stub(profileHelper, 'isEnvProfile').returns(false); - sinon.stub(AppConfig.prototype, 'read'); - sinon.stub(AppConfig, 'getInstance').returns({ - getShareUsage: getShareUsageStub.returns(true), - getMachineId: getMachineIdStub.returns(uuid()), - setMachineId: setMachineIdStub, - write: writeConfigStub, - read: sinon.stub() - }); - }); - - afterEach(() => { - process.env.ASK_SHARE_USAGE = shareUsageVariableValue; - sinon.restore(); - }); - - describe('# constructor validation', () => { - it('| creates instance of MetricClient, expect initial data to be set', () => { - // set up - const client = new MetricClient(); - - // call - const data = client.getData(); - - // verify - expect(data).have.keys(['actions', 'version', 'machineId', 'newUser', 'timeStarted', 'clientId', 'timeUploaded']); - expect(data.actions).eql([]); - expect(data.timeStarted).instanceof(Date); - }); - - it('| creates machine id if it does not exist', () => { - getMachineIdStub.returns(undefined); - - // call - new MetricClient(); - - // verify - expect(setMachineIdStub.callCount).eql(1); - expect(writeConfigStub.callCount).eql(1); - }); - }); - - describe('# start action validation', () => { - let client; - beforeEach(() => { - client = new MetricClient(); - }); - - it('| adds action, expect action to be set', () => { - const name = 'ask.clone'; - const type = 'userCommand'; - // call - client.startAction(name, type); - - const { actions } = client.getData(); - const [action] = actions; - - // verify - expect(actions).instanceof(Array).have.lengthOf(1); - expect(action).include({ endTime: null, failureMessage: '', name, result: null, type }); - expect(action.startTime).instanceof(Date); - expect(action.id).to.be.a.uuid(); - }); - - it('| adds multiple action, expect actions to be set', () => { - const startActionsParams = [ - { name: 'ask.clone', type: 'userCommand' }, - { name: 'ask.init', type: 'internalCommand' }, - { name: 'ask.foo', type: 'userCommand' } - ]; - - // call - startActionsParams.forEach((params) => { - client.startAction(params.name, params.type); - }); - - const { actions } = client.getData(); - - // verify - expect(actions).instanceof(Array).have.lengthOf(startActionsParams.length); - actions.forEach((action, index) => { - const { name, type } = startActionsParams[index]; - expect(action).include({ endTime: null, failureMessage: '', name, result: null, type }); - expect(action.startTime).instanceof(Date); - expect(action.id).to.be.a.uuid(); - }); - }); - }); - - describe('# end action validation', () => { - let client; - let action; - const name = 'ask.clone'; - const type = 'userCommand'; - beforeEach(() => { - client = new MetricClient(); - action = client.startAction(name, type); - }); - - it('| ends action with success, expect end event to be set with success status', () => { - // call - action.end(); - - // verify - expect(action).include({ failureMessage: '', name, result: MetricActionResult.SUCCESS, type }); - expect(action.startTime).instanceof(Date); - expect(action.endTime).instanceof(Date); - expect(action.id).to.be.a.uuid(); - }); - - it('| ends action that was already ended, expect endTime of originally ended action to not change', () => { - // call - // close first time - action.end(); - const originalEndTime = action.endTime; - - // close second time - action.end(); - const endTimeAfterSecondEndRequest = action.endTime; - - // verify - expect(action).include({ failureMessage: '', name, result: MetricActionResult.SUCCESS, type }); - expect(originalEndTime).eql(endTimeAfterSecondEndRequest); - expect(action.startTime).instanceof(Date); - expect(action.endTime).instanceof(Date); - expect(action.id).to.be.a.uuid(); - }); - - it('| ends action with error message, expect end event to be set with failure status', () => { - const failureMessage = 'Boom!'; - // call - action.end(failureMessage); - - // verify - expect(action).include({ failureMessage, name, result: MetricActionResult.FAILURE, type }); - expect(action.startTime).instanceof(Date); - expect(action.endTime).instanceof(Date); - expect(action.id).to.be.a.uuid(); - }); - - it('| ends action with error object, expect end event to be set with failure status', () => { - const failureMessage = 'Boom!'; - // call - action.end(new Error(failureMessage)); - - // verify - expect(action).include({ failureMessage, name, result: MetricActionResult.FAILURE, type }); - expect(action.startTime).instanceof(Date); - expect(action.endTime).instanceof(Date); - expect(action.id).to.be.a.uuid(); - }); - }); - - describe('# sends metrics validation', () => { - let client; - let httpClientPostStub; - const name = 'ask.clone'; - const type = 'userCommand'; - - beforeEach(() => { - client = new MetricClient(); - client.startAction(name, type); - }); - - afterEach(() => { - sinon.restore(); - }); - - it('| sends metrics, expect metrics to be send to metric server', async () => { - httpClientPostStub = sinon.stub(client.httpClient, 'post').resolves({}); - - // call - const { success } = await client.sendData(); - - // verify - const [calledUrl, calledPayload] = httpClientPostStub.args[0]; - - expect(success).eql(true); - expect(httpClientPostStub.calledOnce).eql(true); - expect(calledUrl).eql(METRICS.ENDPOINT); - expect(JSON.parse(calledPayload)).to.be.jsonSchema(jsonSchema); - }); - - it('| sends metrics, expect metrics not to be send to metric server when enabled is false', async () => { - configExistsStub.returns(false); - client = new MetricClient(); - httpClientPostStub = sinon.stub(client.httpClient, 'post'); - - // call - const { success } = await client.sendData(); - - // verify - expect(success).eql(true); - expect(httpClientPostStub.called).eql(false); - }); - - it('| sends metrics, expect metrics not to be send to metric server when ASK_SHARE_USAGE is false', async () => { - process.env.ASK_SHARE_USAGE = false; - client = new MetricClient(); - httpClientPostStub = sinon.stub(client.httpClient, 'post'); - - // call - const { success } = await client.sendData(); - - // verify - expect(success).eql(true); - expect(httpClientPostStub.called).eql(false); - }); - - it('| sends metrics, expect metrics be send to metric server when using env profile', async () => { - isEnvProfileStub.returns(true); - client = new MetricClient(); - httpClientPostStub = sinon.stub(client.httpClient, 'post').resolves({}); - - // call - const { success } = await client.sendData(); - - // verify - expect(success).eql(true); - expect(httpClientPostStub.called).eql(true); - expect(httpClientPostStub.args[0][1]).contains('"machine_id":"all_environmental"'); - }); - - it('| sends metrics, expect to retry on transmission error', async () => { - httpClientPostStub = sinon.stub(client.httpClient, 'post').rejects(); - - // call - const { success } = await client.sendData(); - - // verify - const [calledUrl, calledPayload] = httpClientPostStub.args[0]; - - expect(success).eql(false); - expect(httpClientPostStub.calledThrice).eql(true); - expect(calledUrl).eql(METRICS.ENDPOINT); - expect(JSON.parse(calledPayload)).to.be.jsonSchema(jsonSchema); - }); - }); -}); diff --git a/test/unit/clients/metric-client-test.ts b/test/unit/clients/metric-client-test.ts new file mode 100644 index 00000000..d25b961a --- /dev/null +++ b/test/unit/clients/metric-client-test.ts @@ -0,0 +1,457 @@ +import chai from "chai"; +import {v4 as uuid} from "uuid"; +import chaiUuid from "chai-uuid"; +import chaiJsonSchema from "chai-json-schema"; +import sinon from "sinon"; +import {METRICS} from "../../../lib/utils/constants"; +import profileHelper from "../../../lib/utils/profile-helper"; +import AppConfig from "../../../lib/model/app-config"; +import {MetricClient, MetricActionResult, MetricAction} from "../../../lib/clients/metric-client"; +import jsonSchema from "../../../test/fixture/ask-devtools-metrics.schema.json"; + +const {expect} = chai; +chai.use(chaiUuid); +chai.use(chaiJsonSchema); + +describe("Clients test - cli metric client", () => { + const getShareUsageStub: sinon.SinonStub = sinon.stub(); + const getMachineIdStub: sinon.SinonStub = sinon.stub(); + const setMachineIdStub: sinon.SinonStub = sinon.stub(); + const writeConfigStub: sinon.SinonStub = sinon.stub(); + let isEnvProfileStub: sinon.SinonStub; + let configExistsStub: sinon.SinonStub; + let shareUsageVariableValue: string | undefined; + + beforeEach(() => { + shareUsageVariableValue = process.env.ASK_SHARE_USAGE; + delete process.env.ASK_SHARE_USAGE; + configExistsStub = sinon.stub(AppConfig, "configFileExists").returns(true); + isEnvProfileStub = sinon.stub(profileHelper, "isEnvProfile").returns(false); + sinon.stub(AppConfig.prototype, "read"); + sinon.stub(AppConfig, "getInstance").returns({ + getShareUsage: getShareUsageStub.returns(true), + getMachineId: getMachineIdStub.returns(uuid()), + setMachineId: setMachineIdStub, + write: writeConfigStub, + read: sinon.stub(), + }); + }); + + afterEach(() => { + process.env.ASK_SHARE_USAGE = shareUsageVariableValue; + sinon.restore(); + }); + + describe("# constructor validation", () => { + it("| creates instance of MetricClient, expect initial data to be set", () => { + // set up + const client = new MetricClient(); + + // call + const data = client.getData(); + + // verify + expect(data).have.keys(["actions", "version", "machineId", "newUser", "timeStarted", "clientId", "timeUploaded"]); + expect(data.actions).eql([]); + expect(data.timeStarted).instanceof(Date); + }); + + it("| creates machine id if it does not exist", () => { + getMachineIdStub.returns(undefined); + + // call + new MetricClient(); + + // verify + expect(setMachineIdStub.callCount).eql(1); + expect(writeConfigStub.callCount).eql(1); + }); + }); + + describe("# start action validation", () => { + let client: MetricClient; + beforeEach(() => { + client = new MetricClient(); + }); + + it("| adds action, expect action to be set", () => { + const name = "ask.clone"; + const type = "userCommand"; + // call + client.startAction(name, type); + + const {actions} = client.getData(); + const [action] = actions; + + // verify + expect(actions).instanceof(Array).have.lengthOf(1); + expect(action).include({endTime: null, failureMessage: "", name, result: null, type}); + expect(action.startTime).instanceof(Date); + expect(action.id).to.be.a.uuid(); + }); + + it("| adds multiple action, expect actions to be set", () => { + const startActionsParams = [ + {name: "ask.clone", type: "userCommand"}, + {name: "ask.init", type: "internalCommand"}, + {name: "ask.foo", type: "userCommand"}, + ]; + + // call + startActionsParams.forEach((params) => { + client.startAction(params.name, params.type); + }); + + const actions = client.getData().actions; + + // verify + expect(actions).instanceof(Array).have.lengthOf(startActionsParams.length); + actions.forEach((action: MetricAction, index: number) => { + const {name, type} = startActionsParams[index]; + expect(action).include({endTime: null, failureMessage: "", name, result: null, type}); + expect(action.startTime).instanceof(Date); + expect(action.id).to.be.a.uuid(); + }); + }); + + it("| adds action with options, expect options to be set", () => { + // sample: ask dialog --locale en-US --replay personalfile.json + const actionName = "dialog", + actionType = "userCommand"; + const sampleOptions: {[key: string]: string} = { + locale: "en-US", + replay: "personalfile.json", + }; + const optionNames = Object.keys(sampleOptions); + client.startAction(actionName, actionType); + + // call + optionNames.forEach((name) => { + client.setOption(name, sampleOptions[name]); + }); + + // verify + const data = client.getData(); + const lastAction = data.actions[data.actions.length - 1]; + const options = lastAction.options; + + expect(options).instanceOf(Array).have.lengthOf(optionNames.length); + expect(options).has.members(optionNames); + }); + + it("| adds action with options, expect only storeable values are set", () => { + // sample: ask dialog --locale en-US --replay personalfile.json + const actionName = "dialog", + actionType = "userCommand"; + const sampleOptions: {[key: string]: string} = { + locale: "en-US", + replay: "personalfile.json", + }; + const optionNames = Object.keys(sampleOptions); + client.startAction(actionName, actionType); + + // call + optionNames.forEach((name) => { + client.setOption(name, sampleOptions[name]); + }); + + // verify + // only the storeable keys are allowed in telemetry + const data = client.getData(); + const lastAction = data.actions[data.actions.length - 1]; + const optionData = lastAction.optionData; + + optionNames.forEach((name) => { + if (METRICS.STOREABLE_KEYS.includes(name)) { + expect(Object.keys(optionData).includes(name)).to.be.true; // expect storeable things allowed + expect(optionData[name]).to.equal(sampleOptions[name]); + } else { + expect(Object.keys(optionData).includes(name)).to.be.false; // ...and nothing else + } + }); + }); + }); + + describe("# end action validation", () => { + let client: MetricClient; + let action: MetricAction; + const name: string = "ask.clone"; + const type: string = "userCommand"; + beforeEach(() => { + client = new MetricClient(); + action = client.startAction(name, type); + }); + + it("| ends action with success, expect end event to be set with success status", () => { + // call + action.end(); + + // verify + expect(action).include({failureMessage: "", name, result: MetricActionResult.SUCCESS, type}); + expect(action.startTime).instanceof(Date); + expect(action.endTime).instanceof(Date); + expect(action.id).to.be.a.uuid(); + }); + + it("| ends action that was already ended, expect endTime of originally ended action to not change", () => { + // call + // close first time + action.end(); + const originalEndTime = action.endTime; + + // close second time + action.end(); + const endTimeAfterSecondEndRequest = action.endTime; + + // verify + expect(action).include({failureMessage: "", name, result: MetricActionResult.SUCCESS, type}); + expect(originalEndTime).eql(endTimeAfterSecondEndRequest); + expect(action.startTime).instanceof(Date); + expect(action.endTime).instanceof(Date); + expect(action.id).to.be.a.uuid(); + }); + + it("| ends action with error message, expect end event to be set with failure status", () => { + const failureMessage = "Boom!"; + // call + action.end(failureMessage); + + // verify + expect(action).include({failureMessage, name, result: MetricActionResult.FAILURE, type}); + expect(action.startTime).instanceof(Date); + expect(action.endTime).instanceof(Date); + expect(action.id).to.be.a.uuid(); + }); + + it("| ends action with error object, expect end event to be set with failure status", () => { + const failureMessage = "Boom!"; + // call + action.end(new Error(failureMessage)); + + // verify + expect(action).include({failureMessage, name, result: MetricActionResult.FAILURE, type}); + expect(action.startTime).instanceof(Date); + expect(action.endTime).instanceof(Date); + expect(action.id).to.be.a.uuid(); + }); + }); + + describe("# sends metrics validation, for various commands", () => { + let client: MetricClient; + let httpClientPostStub: sinon.SinonStub; + + // expectations when post succeeds + const verifyActionSuccess = async (name: string) => { + httpClientPostStub = sinon.stub(client.httpClient, "post").resolves({}); + + client.startAction(name, "userCommand"); + + // call + const {success} = await client.sendData(); + + // verify + const [calledUrl, calledPayload] = httpClientPostStub.args[0]; + + expect(success).eql(true); + expect(httpClientPostStub.calledOnce).eql(true); + expect(calledUrl).eql(METRICS.ENDPOINT); + expect(JSON.parse(calledPayload)).to.be.a.jsonSchema(jsonSchema); + }; + + // expectations when post fails + const verifyActionFails = async (name: string) => { + httpClientPostStub = sinon.stub(client.httpClient, "post").rejects(); + + client.startAction(name, "userCommand"); + + // call + const {success} = await client.sendData(); + + // verify + const [calledUrl, calledPayload] = httpClientPostStub.args[0]; + + expect(success).eql(false); + expect(httpClientPostStub.calledThrice).eql(true); + expect(calledUrl).eql(METRICS.ENDPOINT); + expect(JSON.parse(calledPayload)).to.be.a.jsonSchema(jsonSchema); + }; + + beforeEach(() => { + client = new MetricClient(); + }); + + afterEach(() => { + sinon.restore(); + }); + + // smapi, data sent + it("| sends data for smapi, expect metrics sent to metric server", async () => { + await verifyActionSuccess("smapi"); + }); + + // smapi, data can't be sent + it("| sends data for smapi, expect metrics not sent to metric server", async () => { + await verifyActionFails("smapi"); + }); + + // non-smapi, data sent + it("| sends data for configure, expect metrics sent to metric server", async () => { + await verifyActionSuccess("configure"); + }); + + it("| sends data for deploy, expect metrics sent to metric server", async () => { + await verifyActionSuccess("deploy"); + }); + + it("| sends data for new, expect metrics sent to metric server", async () => { + await verifyActionSuccess("new"); + }); + + it("| sends data for init, expect metrics sent to metric server", async () => { + await verifyActionSuccess("init"); + }); + + it("| sends data for dialog, expect metrics sent to metric server", async () => { + await verifyActionSuccess("dialog"); + }); + + it("| sends data for compile, expect metrics sent to metric server", async () => { + await verifyActionSuccess("compile"); + }); + + it("| sends data for run, expect metrics sent to metric server", async () => { + await verifyActionSuccess("run"); + }); + + it("| sends data for decompile, expect metrics sent to metric server", async () => { + await verifyActionSuccess("decompile"); + }); + + it("| sends data for util, expect metrics sent to metric server", async () => { + await verifyActionSuccess("util"); + }); + + // non-smapi, data can't be sent + it("| sends data for configure, expect metrics not sent to metric server", async () => { + await verifyActionFails("configure"); + }); + + it("| sends data for deploy, expect metrics not sent to metric server", async () => { + await verifyActionFails("deploy"); + }); + + it("| sends data for new, expect metrics not sent to metric server", async () => { + await verifyActionFails("new"); + }); + + it("| sends data for init, expect metrics not sent to metric server", async () => { + await verifyActionFails("init"); + }); + + it("| sends data for dialog, expect metrics not sent to metric server", async () => { + await verifyActionFails("dialog"); + }); + + it("| sends data for compile, expect metrics not sent to metric server", async () => { + await verifyActionFails("compile"); + }); + + it("| sends data for run, expect metrics not sent to metric server", async () => { + await verifyActionFails("run"); + }); + + it("| sends data for decompile, expect metrics not sent to metric server", async () => { + await verifyActionFails("decompile"); + }); + + it("| sends data for util, expect metrics not sent to metric server", async () => { + await verifyActionFails("util"); + }); + }); + + describe("# sends metrics validation", () => { + let client: MetricClient; + let httpClientPostStub: sinon.SinonStub; + const name: string = "ask.clone"; + const type: string = "userCommand"; + + beforeEach(() => { + client = new MetricClient(); + client.startAction(name, type); + }); + + afterEach(() => { + sinon.restore(); + }); + + it("| sends metrics, expect metrics to be send to metric server", async () => { + httpClientPostStub = sinon.stub(client.httpClient, "post").resolves({}); + + // call + const {success} = await client.sendData(); + + // verify + const [calledUrl, calledPayload] = httpClientPostStub.args[0]; + + expect(success).eql(true); + expect(httpClientPostStub.calledOnce).eql(true); + expect(calledUrl).eql(METRICS.ENDPOINT); + expect(JSON.parse(calledPayload)).to.be.a.jsonSchema(jsonSchema); + }); + + it("| sends metrics, expect metrics not to be send to metric server when enabled is false", async () => { + configExistsStub.returns(false); + client = new MetricClient(); + httpClientPostStub = sinon.stub(client.httpClient, "post"); + + // call + const {success} = await client.sendData(); + + // verify + expect(success).eql(true); + expect(httpClientPostStub.called).eql(false); + }); + + it("| sends metrics, expect metrics not to be send to metric server when ASK_SHARE_USAGE is false", async () => { + process.env.ASK_SHARE_USAGE = "false"; + client = new MetricClient(); + httpClientPostStub = sinon.stub(client.httpClient, "post"); + + // call + const {success} = await client.sendData(); + + // verify + expect(success).eql(true); + expect(httpClientPostStub.called).eql(false); + }); + + it("| sends metrics, expect metrics be send to metric server when using env profile", async () => { + isEnvProfileStub.returns(true); + client = new MetricClient(); + httpClientPostStub = sinon.stub(client.httpClient, "post").resolves({}); + + // call + const {success} = await client.sendData(); + + // verify + expect(success).eql(true); + expect(httpClientPostStub.called).eql(true); + expect(httpClientPostStub.args[0][1]).contains('"machine_id":"all_environmental"'); + }); + + it("| sends metrics, expect to retry on transmission error", async () => { + httpClientPostStub = sinon.stub(client.httpClient, "post").rejects(); + + // call + const {success} = await client.sendData(); + + // verify + const [calledUrl, calledPayload] = httpClientPostStub.args[0]; + + expect(success).eql(false); + expect(httpClientPostStub.calledThrice).eql(true); + expect(calledUrl).eql(METRICS.ENDPOINT); + expect(JSON.parse(calledPayload)).to.be.a.jsonSchema(jsonSchema); + }); + }); +}); diff --git a/test/unit/clients/smapi-client-test/index.js b/test/unit/clients/smapi-client-test/index.js deleted file mode 100644 index ead2a651..00000000 --- a/test/unit/clients/smapi-client-test/index.js +++ /dev/null @@ -1,312 +0,0 @@ -const { expect } = require('chai'); -const sinon = require('sinon'); - -const SmapiClient = require('@src/clients/smapi-client'); -const httpClient = require('@src/clients/http-client'); -const AuthorizationController = require('@src/controllers/authorization-controller'); -const CONSTANTS = require('@src/utils/constants'); - -const triggerAccountLinking = require('./resources/account-linking'); -const triggerCatalog = require('./resources/catalog'); -const triggerHistory = require('./resources/history'); -const triggerIsp = require('./resources/isp'); -const triggerManifest = require('./resources/manifest'); -const triggerInteractionModel = require('./resources/interaction-model'); -const triggerPrivateSkill = require('./resources/private-skill'); -const triggerSkillPackage = require('./resources/skill-package'); -const triggerSkill = require('./resources/skill'); -const triggerTest = require('./resources/test'); -const triggerVendor = require('./resources/vendor'); -const triggerTask = require('./resources/task'); -const triggerEvaluations = require('./resources/evaluations'); -const triggerAlexaHosted = require('./resources/alexa-hosted'); -const triggerBetaTestTests = require('./resources/beta-test'); -const triggerPublishingTests = require('./resources/publishing'); - -describe('Clients test - smapi client test', () => { - const TEST_PROFILE = 'testProfile'; - const TEST_DO_DEBUG = false; - const TEST_ACCESS_TOKEN = { - access_token: 'access_token', - refresh_token: 'refresh_token', - token_type: 'bearer', - expires_in: 3600, - expires_at: 'expires_at' - }; - const smapiClient = new SmapiClient({ - profile: TEST_PROFILE, - doDebug: TEST_DO_DEBUG - }); - const TEST_REQUEST_RESPONSE = { - statusCode: 100, - body: '{"test":"BODY"}', - headers: {} - }; - const TEST_REQUEST_RESPONSE_NOT_PARSABLE = { - statusCode: 100, - body: '{"test","BODY"}', - headers: {} - }; - const TEST_REQUEST_RESPONSE_ERROR_STATUS_CODE_WITHOUT_BODY = { - statusCode: 401, - headers: {} - }; - - describe('# smapi client request handler', () => { - const TEST_API_NAME = 'apiName'; - const TEST_URL_PATH = 'urlPath'; - const TEST_VERSION = 'version'; - const TEST_METHOD = 'method'; - const TEST_ERROR = 'error'; - - beforeEach(() => { - sinon.stub(AuthorizationController.prototype, 'tokenRefreshAndRead'); - sinon.stub(httpClient, 'request'); - }); - - it('| input request options correctly to _smapiRequest', (done) => { - // setup - AuthorizationController.prototype.tokenRefreshAndRead.callsArgWith(1, null, TEST_ACCESS_TOKEN.access_token); - httpClient.request.callsArgWith(3, null, TEST_REQUEST_RESPONSE); - // call - smapiClient._smapiRequest(TEST_API_NAME, TEST_METHOD, TEST_VERSION, TEST_URL_PATH, {}, {}, null, (err, res) => { - // verify - const expectedOptions = { - url: `${CONSTANTS.SMAPI.ENDPOINT}/${TEST_VERSION}/${TEST_URL_PATH}`, - method: TEST_METHOD, - headers: { authorization: 'access_token' }, - body: null, - json: false - }; - - expect(AuthorizationController.prototype.tokenRefreshAndRead.args[0][0]).equal(TEST_PROFILE); - expect(httpClient.request.args[0][0]).deep.equal(expectedOptions); - expect(httpClient.request.args[0][1]).equal(TEST_API_NAME); - expect(httpClient.request.args[0][2]).equal(false); - expect(err).equal(null); - expect(res).deep.equal({ - statusCode: 100, - body: { test: 'BODY' }, - headers: {} - }); - done(); - }); - }); - - it('| input request options without headers input to _smapiRequest', (done) => { - // setup - AuthorizationController.prototype.tokenRefreshAndRead.callsArgWith(1, null, TEST_ACCESS_TOKEN.access_token); - httpClient.request.callsArgWith(3, null, TEST_REQUEST_RESPONSE); - // call - smapiClient._smapiRequest(TEST_API_NAME, TEST_METHOD, TEST_VERSION, TEST_URL_PATH, {}, null, null, (err, res) => { - // verify - const expectedOptions = { - url: `${CONSTANTS.SMAPI.ENDPOINT}/${TEST_VERSION}/${TEST_URL_PATH}`, - method: TEST_METHOD, - headers: { authorization: 'access_token' }, - body: null, - json: false - }; - expect(AuthorizationController.prototype.tokenRefreshAndRead.args[0][0]).deep.equal(TEST_PROFILE); - expect(httpClient.request.args[0][0]).deep.equal(expectedOptions); - expect(httpClient.request.args[0][1]).equal(TEST_API_NAME); - expect(httpClient.request.args[0][2]).equal(false); - expect(err).equal(null); - expect(res).deep.equal({ - statusCode: 100, - body: { test: 'BODY' }, - headers: {} - }); - done(); - }); - }); - - it('| input request options but http request fails', (done) => { - // setup - AuthorizationController.prototype.tokenRefreshAndRead.callsArgWith(1, null, TEST_ACCESS_TOKEN.access_token); - httpClient.request.callsArgWith(3, TEST_ERROR); - // call - smapiClient._smapiRequest(TEST_API_NAME, TEST_METHOD, TEST_VERSION, TEST_URL_PATH, {}, {}, null, (err, res) => { - // verify - expect(err).equal(TEST_ERROR); - expect(res).equal(undefined); - done(); - }); - }); - - it('| input request options but the response is not parsable', (done) => { - // setup - AuthorizationController.prototype.tokenRefreshAndRead.callsArgWith(1, null, TEST_ACCESS_TOKEN.access_token); - httpClient.request.callsArgWith(3, null, TEST_REQUEST_RESPONSE_NOT_PARSABLE); - // call - smapiClient._smapiRequest(TEST_API_NAME, TEST_METHOD, TEST_VERSION, TEST_URL_PATH, {}, {}, null, (err, res) => { - // verify - const errMsg = '[Fatal]: Failed to parse SMAPI\'s response. Please run again with --debug to check more details.\nError:'; - expect(err.startsWith(errMsg)).equal(true); - expect(res).equal(null); - done(); - }); - }); - - it('| input request options and the SMAPI returns error status code but without response object', (done) => { - // setup - AuthorizationController.prototype.tokenRefreshAndRead.callsArgWith(1, null, TEST_ACCESS_TOKEN.access_token); - httpClient.request.callsArgWith(3, null, TEST_REQUEST_RESPONSE_ERROR_STATUS_CODE_WITHOUT_BODY); - // call - smapiClient._smapiRequest(TEST_API_NAME, TEST_METHOD, TEST_VERSION, TEST_URL_PATH, {}, {}, null, (err, res) => { - // verify - const errMsg = `[Fatal]: SMAPI error code ${TEST_REQUEST_RESPONSE_ERROR_STATUS_CODE_WITHOUT_BODY.statusCode}. \ -No response body from the service request.`; - expect(err).equal(errMsg); - expect(res).equal(null); - done(); - }); - }); - - afterEach(() => { - httpClient.request.restore(); - AuthorizationController.prototype.tokenRefreshAndRead.restore(); - }); - }); - - describe('# smapi client smapiRedirectRequestWithUrl method', () => { - const TEST_URL = 'url'; - - beforeEach(() => { - sinon.stub(httpClient, 'request'); - sinon.stub(AuthorizationController.prototype, 'tokenRefreshAndRead'); - }); - - it('| pass the resquest option and make http client request correctly', (done) => { - // setup - AuthorizationController.prototype.tokenRefreshAndRead.callsArgWith(1, null, TEST_ACCESS_TOKEN.access_token); - httpClient.request.callsArgWith(3, null, TEST_REQUEST_RESPONSE); - // call - smapiClient.smapiRedirectRequestWithUrl(TEST_URL, (err, res) => { - // verify - const expectedRequestOption = { - url: TEST_URL, - method: CONSTANTS.HTTP_REQUEST.VERB.GET, - headers: { authorization: 'access_token' }, - body: null - }; - expect(AuthorizationController.prototype.tokenRefreshAndRead.args[0][0]).deep.equal(TEST_PROFILE); - expect(httpClient.request.args[0][0]).deep.equal(expectedRequestOption); - expect(httpClient.request.args[0][1]).equal('REDIRECT_URL'); - expect(httpClient.request.args[0][2]).equal(false); - expect(err).equal(null); - expect(res).deep.equal({ - statusCode: 100, - body: { test: 'BODY' }, - headers: {} - }); - done(); - }); - }); - - it('| pass the resquest option correctly but SMAPI response error status code without response body', (done) => { - // setup - AuthorizationController.prototype.tokenRefreshAndRead.callsArgWith(1, null, TEST_ACCESS_TOKEN.access_token); - httpClient.request.callsArgWith(3, null, TEST_REQUEST_RESPONSE_ERROR_STATUS_CODE_WITHOUT_BODY); - // call - smapiClient.smapiRedirectRequestWithUrl(TEST_URL, (err, res) => { - // verify - const errMsg = `[Fatal]: SMAPI error code ${TEST_REQUEST_RESPONSE_ERROR_STATUS_CODE_WITHOUT_BODY.statusCode}. \ -No response body from the service request.`; - expect(err).equal(errMsg); - expect(res).equal(null); - done(); - }); - }); - - afterEach(() => { - sinon.restore(); - }); - }); - - describe('# smapi client listWithAutoPagination method', () => { - smapiClient.testFunc = () => {}; - const TEST_CALL_API_TRACK = ['testFunc']; - const TEST_CALL_ARGV = ['arg1', 'arg2']; - const TEST_RESPONSE_ACCESSOR = 'TEST'; - const TEST_HTTP_RESPONSE_BODY = { TEST: 'RESPONSE_BODY' }; - const TEST_RESPONSE_HANDLE = (res) => { - const array = []; - array.push(res.body); - return { - nextToken: res.nextToken, - listResult: array - }; - }; - const TEST_ERROR_MESSAGE = 'error'; - let stubTestFunc; - beforeEach(() => { - stubTestFunc = sinon.stub(smapiClient, 'testFunc'); - }); - - it('| handle error from target function', (done) => { - // setup - stubTestFunc.callsArgWith(3, TEST_ERROR_MESSAGE, null); - // call - smapiClient.listWithAutoPagination(TEST_CALL_API_TRACK, TEST_CALL_ARGV, TEST_RESPONSE_ACCESSOR, TEST_RESPONSE_HANDLE, (err) => { - // verify - expect(err).equal(TEST_ERROR_MESSAGE); - done(); - }); - }); - - it('| handle response with status code >= 300', (done) => { - // setup - stubTestFunc.callsArgWith(3, null, { statusCode: 300, body: TEST_HTTP_RESPONSE_BODY }); - // call - smapiClient.listWithAutoPagination(TEST_CALL_API_TRACK, TEST_CALL_ARGV, TEST_RESPONSE_ACCESSOR, TEST_RESPONSE_HANDLE, (err) => { - // verify - expect(err).equal(TEST_HTTP_RESPONSE_BODY); - done(); - }); - }); - - it('| handle response with status code < 300', (done) => { - // setup - stubTestFunc.onCall(0).callsArgWith(3, null, { statusCode: 200, body: 'TEST_BODY1', nextToken: 'TEST_TOKEN' }); - stubTestFunc.onCall(1).callsArgWith(3, null, { statusCode: 200, body: 'TEST_BODY2', nextToken: null }); - // call - smapiClient.listWithAutoPagination(TEST_CALL_API_TRACK, TEST_CALL_ARGV, TEST_RESPONSE_ACCESSOR, TEST_RESPONSE_HANDLE, (err, res) => { - // verify - const expectation = {}; - expectation[TEST_RESPONSE_ACCESSOR] = ['TEST_BODY1', 'TEST_BODY2']; - expect(err).to.equal(null); - expect(res).to.deep.equals(expectation); - done(); - }); - }); - - afterEach(() => { - stubTestFunc.restore(); - }); - }); - - describe('# smapi client skill APIs', () => { - triggerSkill(smapiClient); - triggerManifest(smapiClient); - triggerInteractionModel(smapiClient); - triggerAccountLinking(smapiClient); - triggerTest(smapiClient); - triggerPrivateSkill(smapiClient); - triggerHistory(smapiClient); - triggerEvaluations(smapiClient); - triggerAlexaHosted(smapiClient); - triggerBetaTestTests(smapiClient); - triggerPublishingTests(smapiClient); - }); - - triggerSkillPackage(smapiClient); - - triggerIsp(smapiClient); - - triggerVendor(smapiClient); - - triggerCatalog(smapiClient); - - triggerTask(smapiClient); -}); diff --git a/test/unit/clients/smapi-client-test/index.test.ts b/test/unit/clients/smapi-client-test/index.test.ts new file mode 100644 index 00000000..ca4602df --- /dev/null +++ b/test/unit/clients/smapi-client-test/index.test.ts @@ -0,0 +1,260 @@ +import {expect} from "chai"; +import sinon from "sinon"; + +import {SmapiClientLateBound} from "../../../../lib/clients/smapi-client"; +import httpClient from "../../../../lib/clients/http-client"; +import AuthorizationController from "../../../../lib/controllers/authorization-controller"; +import CONSTANTS from "../../../../lib/utils/constants"; + +import triggerAccountLinking from "./resources/account-linking"; +import triggerCatalog from "./resources/catalog"; +import triggerHistory from "./resources/history"; +import triggerIsp from "./resources/isp"; +import triggerManifest from "./resources/manifest"; +import triggerInteractionModel from "./resources/interaction-model"; +import triggerPrivateSkill from "./resources/private-skill"; +import triggerSkillPackage from "./resources/skill-package"; +import triggerSkill from "./resources/skill"; +import triggerTest from "./resources/test"; +import triggerVendor from "./resources/vendor"; +import triggerTask from "./resources/task"; +import triggerEvaluations from "./resources/evaluations"; +import triggerAlexaHosted from "./resources/alexa-hosted"; +import triggerBetaTestTests from "./resources/beta-test"; +import triggerPublishingTests from "./resources/publishing"; + +describe("Clients test - smapi client test", () => { + const TEST_PROFILE = "testProfile"; + const TEST_DO_DEBUG = false; + const TEST_ACCESS_TOKEN = { + access_token: "access_token", + refresh_token: "refresh_token", + token_type: "bearer", + expires_in: 3600, + expires_at: "expires_at", + }; + const smapiClient = new SmapiClientLateBound(); + const smapiClientBound = smapiClient.withConfiguration({ + profile: TEST_PROFILE, + doDebug: TEST_DO_DEBUG, + }); + const TEST_REQUEST_RESPONSE = { + statusCode: 100, + body: '{"test":"BODY"}', + headers: {}, + }; + const TEST_REQUEST_RESPONSE_NOT_PARSABLE = { + statusCode: 100, + body: '{"test","BODY"}', + headers: {}, + }; + const TEST_REQUEST_RESPONSE_ERROR_STATUS_CODE_WITHOUT_BODY = { + statusCode: 401, + headers: {}, + }; + + describe("# smapi client request handler", () => { + const TEST_API_NAME = "apiName"; + const TEST_URL_PATH = "urlPath"; + const TEST_VERSION = "version"; + const TEST_METHOD = "method"; + const TEST_ERROR = "error"; + + let tokenReadStub: sinon.SinonStub; + let httpRequestStub: sinon.SinonStub; + + beforeEach(() => { + sinon.restore(); + tokenReadStub = sinon.stub(AuthorizationController.prototype, "tokenRefreshAndRead"); + httpRequestStub = sinon.stub(httpClient, "request"); + }); + + it("| input request options correctly to _smapiRequest", (done) => { + // setup + tokenReadStub.callsArgWith(1, null, TEST_ACCESS_TOKEN.access_token); + httpRequestStub.callsArgWith(3, null, TEST_REQUEST_RESPONSE); + // call + smapiClient._smapiRequest( + { + profile: TEST_PROFILE, + doDebug: TEST_DO_DEBUG, + }, + TEST_API_NAME, + TEST_METHOD, + TEST_VERSION, + TEST_URL_PATH, + {}, + {}, + null, + (err, res) => { + // verify + const expectedOptions = { + url: `${CONSTANTS.SMAPI.ENDPOINT}/${TEST_VERSION}/${TEST_URL_PATH}`, + method: TEST_METHOD, + headers: {authorization: "access_token"}, + body: null, + json: false, + }; + + expect(tokenReadStub.args[0][0]).equal(TEST_PROFILE); + expect(httpRequestStub.args[0][0]).deep.equal(expectedOptions); + expect(httpRequestStub.args[0][1]).equal(TEST_API_NAME); + expect(httpRequestStub.args[0][2]).equal(false); + expect(err).equal(null); + expect(res).deep.equal({ + statusCode: 100, + body: {test: "BODY"}, + headers: {}, + }); + done(); + }, + ); + }); + + it("| input request options without headers input to _smapiRequest", (done) => { + // setup + tokenReadStub.callsArgWith(1, null, TEST_ACCESS_TOKEN.access_token); + httpRequestStub.callsArgWith(3, null, TEST_REQUEST_RESPONSE); + // call + smapiClient._smapiRequest( + { + profile: TEST_PROFILE, + doDebug: TEST_DO_DEBUG, + }, + TEST_API_NAME, + TEST_METHOD, + TEST_VERSION, + TEST_URL_PATH, + {}, + null, + null, + (err, res) => { + // verify + const expectedOptions = { + url: `${CONSTANTS.SMAPI.ENDPOINT}/${TEST_VERSION}/${TEST_URL_PATH}`, + method: TEST_METHOD, + headers: {authorization: "access_token"}, + body: null, + json: false, + }; + expect(tokenReadStub.args[0][0]).deep.equal(TEST_PROFILE); + expect(httpRequestStub.args[0][0]).deep.equal(expectedOptions); + expect(httpRequestStub.args[0][1]).equal(TEST_API_NAME); + expect(httpRequestStub.args[0][2]).equal(false); + expect(err).equal(null); + expect(res).deep.equal({ + statusCode: 100, + body: {test: "BODY"}, + headers: {}, + }); + done(); + }, + ); + }); + + it("| input request options but http request fails", (done) => { + // setup + tokenReadStub.callsArgWith(1, null, TEST_ACCESS_TOKEN.access_token); + httpRequestStub.callsArgWith(3, TEST_ERROR); + // call + smapiClient._smapiRequest( + { + profile: TEST_PROFILE, + doDebug: TEST_DO_DEBUG, + }, + TEST_API_NAME, + TEST_METHOD, + TEST_VERSION, + TEST_URL_PATH, + {}, + {}, + null, + (err, res) => { + // verify + expect(err).equal(TEST_ERROR); + expect(res).equal(undefined); + done(); + }, + ); + }); + + it("| input request options but the response is not parsable", (done) => { + // setup + tokenReadStub.callsArgWith(1, null, TEST_ACCESS_TOKEN.access_token); + httpRequestStub.callsArgWith(3, null, TEST_REQUEST_RESPONSE_NOT_PARSABLE); + // call + smapiClient._smapiRequest( + { + profile: TEST_PROFILE, + doDebug: TEST_DO_DEBUG, + }, + TEST_API_NAME, + TEST_METHOD, + TEST_VERSION, + TEST_URL_PATH, + {}, + {}, + null, + (err, res) => { + // verify + const errMsg = "[Fatal]: Failed to parse SMAPI's response. Please run again with --debug to check more details.\nError:"; + expect(err.startsWith(errMsg)).equal(true); + expect(res).equal(null); + done(); + }, + ); + }); + + it("| input request options and the SMAPI returns error status code but without response object", (done) => { + // setup + tokenReadStub.callsArgWith(1, null, TEST_ACCESS_TOKEN.access_token); + httpRequestStub.callsArgWith(3, null, TEST_REQUEST_RESPONSE_ERROR_STATUS_CODE_WITHOUT_BODY); + // call + smapiClient._smapiRequest( + { + profile: TEST_PROFILE, + doDebug: TEST_DO_DEBUG, + }, + TEST_API_NAME, + TEST_METHOD, + TEST_VERSION, + TEST_URL_PATH, + {}, + {}, + null, + (err, res) => { + // verify + const errMsg = `[Fatal]: SMAPI error code ${TEST_REQUEST_RESPONSE_ERROR_STATUS_CODE_WITHOUT_BODY.statusCode}. \ +No response body from the service request.`; + expect(err).equal(errMsg); + expect(res).equal(null); + done(); + }, + ); + }); + }); + + describe("# smapi client skill APIs", () => { + triggerSkill(smapiClientBound); + triggerManifest(smapiClientBound); + triggerInteractionModel(smapiClientBound); + triggerAccountLinking(smapiClientBound); + triggerTest(smapiClientBound); + triggerPrivateSkill(smapiClientBound); + triggerHistory(smapiClientBound); + triggerEvaluations(smapiClientBound); + triggerAlexaHosted(smapiClientBound); + triggerBetaTestTests(smapiClientBound); + triggerPublishingTests(smapiClientBound); + }); + + triggerSkillPackage(smapiClientBound); + + triggerIsp(smapiClientBound); + + triggerVendor(smapiClientBound); + + triggerCatalog(smapiClientBound); + + triggerTask(smapiClientBound); +}); diff --git a/test/unit/clients/smapi-client-test/index.ts b/test/unit/clients/smapi-client-test/index.ts new file mode 100644 index 00000000..d4116ac0 --- /dev/null +++ b/test/unit/clients/smapi-client-test/index.ts @@ -0,0 +1,262 @@ +import {expect} from "chai"; +import sinon from "sinon"; + +import {SmapiClientLateBound} from "../../../../lib/clients/smapi-client"; +import httpClient from "../../../../lib/clients/http-client"; +import AuthorizationController from "../../../../lib/controllers/authorization-controller"; +import CONSTANTS from "../../../../lib/utils/constants"; + +import triggerAccountLinking from "./resources/account-linking"; +import triggerCatalog from "./resources/catalog"; +import triggerHistory from "./resources/history"; +import triggerIsp from "./resources/isp"; +import triggerManifest from "./resources/manifest"; +import triggerInteractionModel from "./resources/interaction-model"; +import triggerPrivateSkill from "./resources/private-skill"; +import triggerSkillPackage from "./resources/skill-package"; +import triggerSkill from "./resources/skill"; +import triggerTest from "./resources/test"; +import triggerVendor from "./resources/vendor"; +import triggerTask from "./resources/task"; +import triggerEvaluations from "./resources/evaluations"; +import triggerAlexaHosted from "./resources/alexa-hosted"; +import triggerBetaTestTests from "./resources/beta-test"; +import triggerPublishingTests from "./resources/publishing"; + +describe("Clients test - smapi client test", () => { + const TEST_PROFILE = "testProfile"; + const TEST_DO_DEBUG = false; + const TEST_ACCESS_TOKEN = { + access_token: "access_token", + refresh_token: "refresh_token", + token_type: "bearer", + expires_in: 3600, + expires_at: "expires_at", + }; + const smapiClient = new SmapiClientLateBound(); + const smapiClientBound = smapiClient.withConfiguration({ + profile: TEST_PROFILE, + doDebug: TEST_DO_DEBUG, + }); + const TEST_REQUEST_RESPONSE = { + statusCode: 100, + body: '{"test":"BODY"}', + headers: {}, + }; + const TEST_REQUEST_RESPONSE_NOT_PARSABLE = { + statusCode: 100, + body: '{"test","BODY"}', + headers: {}, + }; + const TEST_REQUEST_RESPONSE_ERROR_STATUS_CODE_WITHOUT_BODY = { + statusCode: 401, + headers: {}, + }; + + describe("# smapi client request handler", () => { + const TEST_API_NAME = "apiName"; + const TEST_URL_PATH = "urlPath"; + const TEST_VERSION = "version"; + const TEST_METHOD = "method"; + const TEST_ERROR = "error"; + + let tokenReadStub: sinon.SinonStub; + let httpRequestStub: sinon.SinonStub; + + beforeEach(() => { + sinon.restore(); + tokenReadStub = sinon.stub(AuthorizationController.prototype, "tokenRefreshAndRead"); + httpRequestStub = sinon.stub(httpClient, "request"); + }); + + it("| input request options correctly to _smapiRequest", (done) => { + // setup + tokenReadStub.callsArgWith(1, null, TEST_ACCESS_TOKEN.access_token); + httpRequestStub.callsArgWith(3, null, TEST_REQUEST_RESPONSE); + // call + smapiClient._smapiRequest( + { + profile: TEST_PROFILE, + doDebug: TEST_DO_DEBUG, + }, + TEST_API_NAME, + TEST_METHOD, + TEST_VERSION, + TEST_URL_PATH, + {}, + {}, + null, + (err, res) => { + // verify + const expectedOptions = { + url: `${CONSTANTS.SMAPI.ENDPOINT}/${TEST_VERSION}/${TEST_URL_PATH}`, + method: TEST_METHOD, + headers: {authorization: "access_token"}, + body: null, + json: false, + }; + + expect(tokenReadStub.args[0][0]).equal(TEST_PROFILE); + expect(httpRequestStub.args[0][0]).deep.equal(expectedOptions); + expect(httpRequestStub.args[0][1]).equal(TEST_API_NAME); + expect(httpRequestStub.args[0][2]).equal(false); + expect(err).equal(null); + expect(res).deep.equal({ + statusCode: 100, + body: {test: "BODY"}, + headers: {}, + }); + done(); + }, + ); + }); + + it("| input request options without headers input to _smapiRequest", (done) => { + // setup + tokenReadStub.callsArgWith(1, null, TEST_ACCESS_TOKEN.access_token); + httpRequestStub.callsArgWith(3, null, TEST_REQUEST_RESPONSE); + // call + smapiClient._smapiRequest( + { + profile: TEST_PROFILE, + doDebug: TEST_DO_DEBUG, + }, + TEST_API_NAME, + TEST_METHOD, + TEST_VERSION, + TEST_URL_PATH, + {}, + null, + null, + (err, res) => { + // verify + const expectedOptions = { + url: `${CONSTANTS.SMAPI.ENDPOINT}/${TEST_VERSION}/${TEST_URL_PATH}`, + method: TEST_METHOD, + headers: {authorization: "access_token"}, + body: null, + json: false, + }; + expect(tokenReadStub.args[0][0]).deep.equal(TEST_PROFILE); + expect(httpRequestStub.args[0][0]).deep.equal(expectedOptions); + expect(httpRequestStub.args[0][1]).equal(TEST_API_NAME); + expect(httpRequestStub.args[0][2]).equal(false); + expect(err).equal(null); + expect(res).deep.equal({ + statusCode: 100, + body: {test: "BODY"}, + headers: {}, + }); + done(); + }, + ); + }); + + it("| input request options but http request fails", (done) => { + // setup + tokenReadStub.callsArgWith(1, null, TEST_ACCESS_TOKEN.access_token); + httpRequestStub.callsArgWith(3, TEST_ERROR); + // call + smapiClient._smapiRequest( + { + profile: TEST_PROFILE, + doDebug: TEST_DO_DEBUG, + }, + TEST_API_NAME, + TEST_METHOD, + TEST_VERSION, + TEST_URL_PATH, + {}, + {}, + null, + (err, res) => { + // verify + expect(err).equal(TEST_ERROR); + expect(res).equal(undefined); + done(); + }, + ); + }); + + it("| input request options but the response is not parsable", (done) => { + // setup + tokenReadStub.callsArgWith(1, null, TEST_ACCESS_TOKEN.access_token); + httpRequestStub.callsArgWith(3, null, TEST_REQUEST_RESPONSE_NOT_PARSABLE); + // call + smapiClient._smapiRequest( + { + profile: TEST_PROFILE, + doDebug: TEST_DO_DEBUG, + }, + TEST_API_NAME, + TEST_METHOD, + TEST_VERSION, + TEST_URL_PATH, + {}, + {}, + null, + (err, res) => { + // verify + console.log("hi4"); + const errMsg = "[Fatal]: Failed to parse SMAPI's response. Please run again with --debug to check more details.\nError:"; + expect(err.startsWith(errMsg)).equal(true); + expect(res).equal(null); + console.log("hi5"); + done(); + }, + ); + }); + + it("| input request options and the SMAPI returns error status code but without response object", (done) => { + // setup + tokenReadStub.callsArgWith(1, null, TEST_ACCESS_TOKEN.access_token); + httpRequestStub.callsArgWith(3, null, TEST_REQUEST_RESPONSE_ERROR_STATUS_CODE_WITHOUT_BODY); + // call + smapiClient._smapiRequest( + { + profile: TEST_PROFILE, + doDebug: TEST_DO_DEBUG, + }, + TEST_API_NAME, + TEST_METHOD, + TEST_VERSION, + TEST_URL_PATH, + {}, + {}, + null, + (err, res) => { + // verify + const errMsg = `[Fatal]: SMAPI error code ${TEST_REQUEST_RESPONSE_ERROR_STATUS_CODE_WITHOUT_BODY.statusCode}. \ +No response body from the service request.`; + expect(err).equal(errMsg); + expect(res).equal(null); + done(); + }, + ); + }); + }); + + describe("# smapi client skill APIs", () => { + triggerSkill(smapiClientBound); + triggerManifest(smapiClientBound); + triggerInteractionModel(smapiClientBound); + triggerAccountLinking(smapiClientBound); + triggerTest(smapiClientBound); + triggerPrivateSkill(smapiClientBound); + triggerHistory(smapiClientBound); + triggerEvaluations(smapiClientBound); + triggerAlexaHosted(smapiClientBound); + triggerBetaTestTests(smapiClientBound); + triggerPublishingTests(smapiClientBound); + }); + + triggerSkillPackage(smapiClientBound); + + triggerIsp(smapiClientBound); + + triggerVendor(smapiClientBound); + + triggerCatalog(smapiClientBound); + + triggerTask(smapiClientBound); +}); diff --git a/test/unit/clients/smapi-client-test/resources/account-linking.js b/test/unit/clients/smapi-client-test/resources/account-linking.js index fd2fdff0..07e8a324 100644 --- a/test/unit/clients/smapi-client-test/resources/account-linking.js +++ b/test/unit/clients/smapi-client-test/resources/account-linking.js @@ -1,85 +1,85 @@ -const { expect } = require('chai'); -const sinon = require('sinon'); +const {expect} = require("chai"); +const sinon = require("sinon"); -const httpClient = require('@src/clients/http-client'); -const AuthorizationController = require('@src/controllers/authorization-controller'); -const CONSTANTS = require('@src/utils/constants'); +const httpClient = require("../../../../../lib/clients/http-client"); +const AuthorizationController = require("../../../../../lib/controllers/authorization-controller"); +const CONSTANTS = require("../../../../../lib/utils/constants"); const noop = () => {}; module.exports = (smapiClient) => { - describe('# skill accountLinking APIs', () => { - let httpClientStub; - beforeEach(() => { - httpClientStub = sinon.stub(httpClient, 'request').callsFake(noop); - sinon.stub(AuthorizationController.prototype, 'tokenRefreshAndRead'); - }); + describe("# skill accountLinking APIs", () => { + let httpClientStub; + beforeEach(() => { + httpClientStub = sinon.stub(httpClient, "request").callsFake(noop); + sinon.stub(AuthorizationController.prototype, "tokenRefreshAndRead"); + }); - const TEST_SKILL_ID = 'skillId'; - const TEST_SKILL_STAGE = 'skillStage'; - const TEST_ACCOUNT_LINKING_INFO = 'accountLinkingInfo'; - const TEST_PROFILE = 'testProfile'; - const TEST_ACCESS_TOKEN = 'access_token'; + const TEST_SKILL_ID = "skillId"; + const TEST_SKILL_STAGE = "skillStage"; + const TEST_ACCOUNT_LINKING_INFO = "accountLinkingInfo"; + const TEST_PROFILE = "testProfile"; + const TEST_ACCESS_TOKEN = "access_token"; - [ - { - testCase: 'get-account-linking', - apiFunc: smapiClient.skill.accountLinking.getAccountLinking, - parameters: [TEST_SKILL_ID, TEST_SKILL_STAGE, noop], - expectedOptions: { - url: `${CONSTANTS.SMAPI.ENDPOINT}/v1/skills/${TEST_SKILL_ID}/stages/${TEST_SKILL_STAGE}/accountLinkingClient`, - method: CONSTANTS.HTTP_REQUEST.VERB.GET, - headers: { - authorization: TEST_ACCESS_TOKEN - }, - body: null, - json: false - } - }, - { - testCase: 'set-account-linking', - apiFunc: smapiClient.skill.accountLinking.setAccountLinking, - parameters: [TEST_SKILL_ID, TEST_SKILL_STAGE, TEST_ACCOUNT_LINKING_INFO, noop], - expectedOptions: { - url: `${CONSTANTS.SMAPI.ENDPOINT}/v1/skills/${TEST_SKILL_ID}/stages/${TEST_SKILL_STAGE}/accountLinkingClient`, - method: CONSTANTS.HTTP_REQUEST.VERB.PUT, - headers: { - authorization: TEST_ACCESS_TOKEN - }, - body: { accountLinkingRequest: TEST_ACCOUNT_LINKING_INFO }, - json: true - } - }, - { - testCase: 'delete-account-linking', - apiFunc: smapiClient.skill.accountLinking.deleteAccountLinking, - parameters: [TEST_SKILL_ID, TEST_SKILL_STAGE, noop], - expectedOptions: { - url: `${CONSTANTS.SMAPI.ENDPOINT}/v1/skills/${TEST_SKILL_ID}/stages/${TEST_SKILL_STAGE}/accountLinkingClient`, - method: CONSTANTS.HTTP_REQUEST.VERB.DELETE, - headers: { - authorization: TEST_ACCESS_TOKEN - }, - body: null, - json: false - } - } - ].forEach(({ testCase, apiFunc, parameters, expectedOptions }) => { - it(`| call ${testCase} successfully`, (done) => { - // setup - AuthorizationController.prototype.tokenRefreshAndRead.callsArgWith(1, null, TEST_ACCESS_TOKEN); - // call - apiFunc(...parameters); - // verify - expect(AuthorizationController.prototype.tokenRefreshAndRead.called).equal(true); - expect(AuthorizationController.prototype.tokenRefreshAndRead.args[0][0]).equal(TEST_PROFILE); - expect(httpClientStub.args[0][0]).deep.equal(expectedOptions); - done(); - }); - }); + [ + { + testCase: "get-account-linking", + apiFunc: smapiClient.skill.accountLinking.getAccountLinking, + parameters: [TEST_SKILL_ID, TEST_SKILL_STAGE, noop], + expectedOptions: { + url: `${CONSTANTS.SMAPI.ENDPOINT}/v1/skills/${TEST_SKILL_ID}/stages/${TEST_SKILL_STAGE}/accountLinkingClient`, + method: CONSTANTS.HTTP_REQUEST.VERB.GET, + headers: { + authorization: TEST_ACCESS_TOKEN, + }, + body: null, + json: false, + }, + }, + { + testCase: "set-account-linking", + apiFunc: smapiClient.skill.accountLinking.setAccountLinking, + parameters: [TEST_SKILL_ID, TEST_SKILL_STAGE, TEST_ACCOUNT_LINKING_INFO, noop], + expectedOptions: { + url: `${CONSTANTS.SMAPI.ENDPOINT}/v1/skills/${TEST_SKILL_ID}/stages/${TEST_SKILL_STAGE}/accountLinkingClient`, + method: CONSTANTS.HTTP_REQUEST.VERB.PUT, + headers: { + authorization: TEST_ACCESS_TOKEN, + }, + body: {accountLinkingRequest: TEST_ACCOUNT_LINKING_INFO}, + json: true, + }, + }, + { + testCase: "delete-account-linking", + apiFunc: smapiClient.skill.accountLinking.deleteAccountLinking, + parameters: [TEST_SKILL_ID, TEST_SKILL_STAGE, noop], + expectedOptions: { + url: `${CONSTANTS.SMAPI.ENDPOINT}/v1/skills/${TEST_SKILL_ID}/stages/${TEST_SKILL_STAGE}/accountLinkingClient`, + method: CONSTANTS.HTTP_REQUEST.VERB.DELETE, + headers: { + authorization: TEST_ACCESS_TOKEN, + }, + body: null, + json: false, + }, + }, + ].forEach(({testCase, apiFunc, parameters, expectedOptions}) => { + it(`| call ${testCase} successfully`, (done) => { + // setup + AuthorizationController.prototype.tokenRefreshAndRead.callsArgWith(1, null, TEST_ACCESS_TOKEN); + // call + apiFunc(...parameters); + // verify + expect(AuthorizationController.prototype.tokenRefreshAndRead.called).equal(true); + expect(AuthorizationController.prototype.tokenRefreshAndRead.args[0][0]).equal(TEST_PROFILE); + expect(httpClientStub.args[0][0]).deep.equal(expectedOptions); + done(); + }); + }); - afterEach(() => { - sinon.restore(); - }); + afterEach(() => { + sinon.restore(); }); + }); }; diff --git a/test/unit/clients/smapi-client-test/resources/alexa-hosted.js b/test/unit/clients/smapi-client-test/resources/alexa-hosted.js index 10ee83c0..ef13f7db 100644 --- a/test/unit/clients/smapi-client-test/resources/alexa-hosted.js +++ b/test/unit/clients/smapi-client-test/resources/alexa-hosted.js @@ -1,123 +1,123 @@ -const { expect } = require('chai'); -const sinon = require('sinon'); +const {expect} = require("chai"); +const sinon = require("sinon"); -const httpClient = require('@src/clients/http-client'); -const AuthorizationController = require('@src/controllers/authorization-controller'); -const CONSTANTS = require('@src/utils/constants'); +const httpClient = require("../../../../../lib/clients/http-client"); +const AuthorizationController = require("../../../../../lib/controllers/authorization-controller"); +const CONSTANTS = require("../../../../../lib/utils/constants"); const noop = () => {}; module.exports = (smapiClient) => { - describe('# alexa hosted skills API', () => { - const TEST_SKILL_ID = 'skillId'; - const TEST_REPO_URL = 'RepoUrl'; - const TEST_VENDOR_ID = 'vendorId'; - const TEST_PERMISSION_TYPE = 'permissionType'; - const TEST_PROFILE = 'testProfile'; - const TEST_ACCESS_TOKEN = 'access_token'; - const TEST_RUNTIME_FIELD = 'NodeJS'; - const TEST_RUNTIME_VALUE = 'NODE_16_X'; - const TEST_REGION_VALUE = 'US_EAST_1'; - const TEST_MANIFEST = { - runtime: TEST_RUNTIME_FIELD, - vendorId: TEST_VENDOR_ID, - region: TEST_REGION_VALUE, - manifest: {} - }; - let httpClientStub; + describe("# alexa hosted skills API", () => { + const TEST_SKILL_ID = "skillId"; + const TEST_REPO_URL = "RepoUrl"; + const TEST_VENDOR_ID = "vendorId"; + const TEST_PERMISSION_TYPE = "permissionType"; + const TEST_PROFILE = "testProfile"; + const TEST_ACCESS_TOKEN = "access_token"; + const TEST_RUNTIME_FIELD = "NodeJS"; + const TEST_RUNTIME_VALUE = "NODE_16_X"; + const TEST_REGION_VALUE = "US_EAST_1"; + const TEST_MANIFEST = { + runtime: TEST_RUNTIME_FIELD, + vendorId: TEST_VENDOR_ID, + region: TEST_REGION_VALUE, + manifest: {}, + }; + let httpClientStub; - beforeEach(() => { - httpClientStub = sinon.stub(httpClient, 'request').callsFake(noop); - sinon.stub(AuthorizationController.prototype, 'tokenRefreshAndRead'); - }); + beforeEach(() => { + httpClientStub = sinon.stub(httpClient, "request").callsFake(noop); + sinon.stub(AuthorizationController.prototype, "tokenRefreshAndRead"); + }); - [ - { - testCase: 'create-hosted-skill', - apiFunc: smapiClient.skill.alexaHosted.createHostedSkill, - parameters: [TEST_MANIFEST, noop], - expectedOptions: { - url: `${CONSTANTS.SMAPI.ENDPOINT}/v1/skills/`, - method: CONSTANTS.HTTP_REQUEST.VERB.POST, - headers: { - authorization: TEST_ACCESS_TOKEN - }, - body: { - vendorId: TEST_VENDOR_ID, - manifest: {}, - hosting: { - alexaHosted: { - region: TEST_REGION_VALUE, - runtime: TEST_RUNTIME_VALUE - } - } - }, - json: true - } - }, - { - testCase: 'get-hosted-skill-metadata', - apiFunc: smapiClient.skill.alexaHosted.getAlexaHostedSkillMetadata, - parameters: [TEST_SKILL_ID, noop], - expectedOptions: { - url: `${CONSTANTS.SMAPI.ENDPOINT}/v1/skills/${TEST_SKILL_ID}/alexaHosted`, - method: CONSTANTS.HTTP_REQUEST.VERB.GET, - headers: { - authorization: TEST_ACCESS_TOKEN - }, - body: null, - json: false - } - }, - { - testCase: 'get-git-credentials', - apiFunc: smapiClient.skill.alexaHosted.getGitCredentials, - parameters: [TEST_SKILL_ID, TEST_REPO_URL, noop], - expectedOptions: { - url: `${CONSTANTS.SMAPI.ENDPOINT}/v1/skills/${TEST_SKILL_ID}/alexaHosted/repository/credentials/generate`, - method: CONSTANTS.HTTP_REQUEST.VERB.POST, - headers: { - authorization: TEST_ACCESS_TOKEN - }, - body: { - repository: { - type: 'GIT', - url: TEST_REPO_URL - } - }, - json: true - } + [ + { + testCase: "create-hosted-skill", + apiFunc: smapiClient.skill.alexaHosted.createHostedSkill, + parameters: [TEST_MANIFEST, noop], + expectedOptions: { + url: `${CONSTANTS.SMAPI.ENDPOINT}/v1/skills/`, + method: CONSTANTS.HTTP_REQUEST.VERB.POST, + headers: { + authorization: TEST_ACCESS_TOKEN, + }, + body: { + vendorId: TEST_VENDOR_ID, + manifest: {}, + hosting: { + alexaHosted: { + region: TEST_REGION_VALUE, + runtime: TEST_RUNTIME_VALUE, + }, }, - { - testCase: 'get-hosted-skill-permission', - apiFunc: smapiClient.skill.alexaHosted.getHostedSkillPermission, - parameters: [TEST_VENDOR_ID, TEST_PERMISSION_TYPE, noop], - expectedOptions: { - url: `${CONSTANTS.SMAPI.ENDPOINT}/v1/vendors/${TEST_VENDOR_ID}/alexaHosted/permissions/${TEST_PERMISSION_TYPE}`, - method: CONSTANTS.HTTP_REQUEST.VERB.GET, - headers: { - authorization: TEST_ACCESS_TOKEN - }, - body: null, - json: false - } + }, + json: true, + }, + }, + { + testCase: "get-hosted-skill-metadata", + apiFunc: smapiClient.skill.alexaHosted.getAlexaHostedSkillMetadata, + parameters: [TEST_SKILL_ID, noop], + expectedOptions: { + url: `${CONSTANTS.SMAPI.ENDPOINT}/v1/skills/${TEST_SKILL_ID}/alexaHosted`, + method: CONSTANTS.HTTP_REQUEST.VERB.GET, + headers: { + authorization: TEST_ACCESS_TOKEN, + }, + body: null, + json: false, + }, + }, + { + testCase: "get-git-credentials", + apiFunc: smapiClient.skill.alexaHosted.getGitCredentials, + parameters: [TEST_SKILL_ID, TEST_REPO_URL, noop], + expectedOptions: { + url: `${CONSTANTS.SMAPI.ENDPOINT}/v1/skills/${TEST_SKILL_ID}/alexaHosted/repository/credentials/generate`, + method: CONSTANTS.HTTP_REQUEST.VERB.POST, + headers: { + authorization: TEST_ACCESS_TOKEN, + }, + body: { + repository: { + type: "GIT", + url: TEST_REPO_URL, }, - ].forEach(({ testCase, apiFunc, parameters, expectedOptions }) => { - it(`| call ${testCase} successfully`, (done) => { - // setup - AuthorizationController.prototype.tokenRefreshAndRead.callsArgWith(1, null, TEST_ACCESS_TOKEN); - // call - apiFunc(...parameters); - // verify - expect(AuthorizationController.prototype.tokenRefreshAndRead.called).equal(true); - expect(AuthorizationController.prototype.tokenRefreshAndRead.args[0][0]).equal(TEST_PROFILE); - expect(httpClientStub.args[0][0]).deep.equal(expectedOptions); - done(); - }); - }); + }, + json: true, + }, + }, + { + testCase: "get-hosted-skill-permission", + apiFunc: smapiClient.skill.alexaHosted.getHostedSkillPermission, + parameters: [TEST_VENDOR_ID, TEST_PERMISSION_TYPE, noop], + expectedOptions: { + url: `${CONSTANTS.SMAPI.ENDPOINT}/v1/vendors/${TEST_VENDOR_ID}/alexaHosted/permissions/${TEST_PERMISSION_TYPE}`, + method: CONSTANTS.HTTP_REQUEST.VERB.GET, + headers: { + authorization: TEST_ACCESS_TOKEN, + }, + body: null, + json: false, + }, + }, + ].forEach(({testCase, apiFunc, parameters, expectedOptions}) => { + it(`| call ${testCase} successfully`, (done) => { + // setup + AuthorizationController.prototype.tokenRefreshAndRead.callsArgWith(1, null, TEST_ACCESS_TOKEN); + // call + apiFunc(...parameters); + // verify + expect(AuthorizationController.prototype.tokenRefreshAndRead.called).equal(true); + expect(AuthorizationController.prototype.tokenRefreshAndRead.args[0][0]).equal(TEST_PROFILE); + expect(httpClientStub.args[0][0]).deep.equal(expectedOptions); + done(); + }); + }); - afterEach(() => { - sinon.restore(); - }); + afterEach(() => { + sinon.restore(); }); + }); }; diff --git a/test/unit/clients/smapi-client-test/resources/beta-test.js b/test/unit/clients/smapi-client-test/resources/beta-test.js index 046e5d53..329898de 100644 --- a/test/unit/clients/smapi-client-test/resources/beta-test.js +++ b/test/unit/clients/smapi-client-test/resources/beta-test.js @@ -1,189 +1,189 @@ -const { expect } = require('chai'); -const sinon = require('sinon'); +const {expect} = require("chai"); +const sinon = require("sinon"); -const httpClient = require('@src/clients/http-client'); -const AuthorizationController = require('@src/controllers/authorization-controller'); -const CONSTANTS = require('@src/utils/constants'); +const httpClient = require("../../../../../lib/clients/http-client"); +const AuthorizationController = require("../../../../../lib/controllers/authorization-controller"); +const CONSTANTS = require("../../../../../lib/utils/constants"); const MAX_RESULTS = CONSTANTS.SMAPI.DEFAULT_MAX_RESULT_PER_PAGE; -const NEXT_TOKEN = 'NEXT_TOKEN'; +const NEXT_TOKEN = "NEXT_TOKEN"; const noop = () => {}; module.exports = (smapiClient) => { - describe('# Beta Test APIs', () => { - let httpClientStub; - beforeEach(() => { - httpClientStub = sinon.stub(httpClient, 'request').callsFake(noop); - sinon.stub(AuthorizationController.prototype, 'tokenRefreshAndRead'); - }); + describe("# Beta Test APIs", () => { + let httpClientStub; + beforeEach(() => { + httpClientStub = sinon.stub(httpClient, "request").callsFake(noop); + sinon.stub(AuthorizationController.prototype, "tokenRefreshAndRead"); + }); - const TEST_SKILL_ID = 'skillId'; - const TEST_FEEDBACK_EMAIL = 'feedback@amazon.com'; - const TESTERS = [{ emailId: 'test@amazon.com' }]; - const TEST_PROFILE = 'testProfile'; - const TEST_ACCESS_TOKEN = 'access_token'; + const TEST_SKILL_ID = "skillId"; + const TEST_FEEDBACK_EMAIL = "feedback@amazon.com"; + const TESTERS = [{emailId: "test@amazon.com"}]; + const TEST_PROFILE = "testProfile"; + const TEST_ACCESS_TOKEN = "access_token"; - [ - { - testCase: 'create-beta-test', - apiFunc: smapiClient.skill.betaTest.createBetaTest, - parameters: [TEST_SKILL_ID, TEST_FEEDBACK_EMAIL, noop], - expectedOptions: { - url: `${CONSTANTS.SMAPI.ENDPOINT}/${CONSTANTS.SMAPI.VERSION.V1}/skills/${TEST_SKILL_ID}/betaTest`, - method: CONSTANTS.HTTP_REQUEST.VERB.POST, - headers: { - authorization: TEST_ACCESS_TOKEN - }, - body: { - feedbackEmail: TEST_FEEDBACK_EMAIL - }, - json: true - } - }, - { - testCase: 'update-beta-test', - apiFunc: smapiClient.skill.betaTest.updateBetaTest, - parameters: [TEST_SKILL_ID, TEST_FEEDBACK_EMAIL, noop], - expectedOptions: { - url: `${CONSTANTS.SMAPI.ENDPOINT}/${CONSTANTS.SMAPI.VERSION.V1}/skills/${TEST_SKILL_ID}/betaTest`, - method: CONSTANTS.HTTP_REQUEST.VERB.PUT, - headers: { - authorization: TEST_ACCESS_TOKEN - }, - body: { - feedbackEmail: TEST_FEEDBACK_EMAIL - }, - json: true - } - }, - { - testCase: 'get-beta-test', - apiFunc: smapiClient.skill.betaTest.getBetaTest, - parameters: [TEST_SKILL_ID, noop], - expectedOptions: { - url: `${CONSTANTS.SMAPI.ENDPOINT}/${CONSTANTS.SMAPI.VERSION.V1}/skills/${TEST_SKILL_ID}/betaTest`, - method: CONSTANTS.HTTP_REQUEST.VERB.GET, - headers: { - authorization: TEST_ACCESS_TOKEN - }, - body: {}, - json: true - } - }, - { - testCase: 'start-beta-test', - apiFunc: smapiClient.skill.betaTest.startBetaTest, - parameters: [TEST_SKILL_ID, noop], - expectedOptions: { - url: `${CONSTANTS.SMAPI.ENDPOINT}/${CONSTANTS.SMAPI.VERSION.V1}/skills/${TEST_SKILL_ID}/betaTest/start`, - method: CONSTANTS.HTTP_REQUEST.VERB.POST, - headers: { - authorization: TEST_ACCESS_TOKEN - }, - body: {}, - json: true - } - }, - { - testCase: 'end-beta-test', - apiFunc: smapiClient.skill.betaTest.endBetaTest, - parameters: [TEST_SKILL_ID, noop], - expectedOptions: { - url: `${CONSTANTS.SMAPI.ENDPOINT}/${CONSTANTS.SMAPI.VERSION.V1}/skills/${TEST_SKILL_ID}/betaTest/end`, - method: CONSTANTS.HTTP_REQUEST.VERB.POST, - headers: { - authorization: TEST_ACCESS_TOKEN - }, - body: {}, - json: true - } - }, - { - testCase: 'list-beta-testers', - apiFunc: smapiClient.skill.betaTest.listBetaTesters, - parameters: [TEST_SKILL_ID, MAX_RESULTS, NEXT_TOKEN, noop], - expectedOptions: { - url: `${CONSTANTS.SMAPI.ENDPOINT}/${CONSTANTS.SMAPI.VERSION.V1}/skills/${TEST_SKILL_ID}/betaTest/testers`, - method: CONSTANTS.HTTP_REQUEST.VERB.GET, - headers: { - authorization: TEST_ACCESS_TOKEN - }, - body: null, - json: false - } - }, - { - testCase: 'add-beta-testers', - apiFunc: smapiClient.skill.betaTest.addBetaTesters, - parameters: [TEST_SKILL_ID, TESTERS, noop], - expectedOptions: { - url: `${CONSTANTS.SMAPI.ENDPOINT}/${CONSTANTS.SMAPI.VERSION.V1}/skills/${TEST_SKILL_ID}/betaTest/testers/add`, - method: CONSTANTS.HTTP_REQUEST.VERB.POST, - headers: { - authorization: TEST_ACCESS_TOKEN - }, - body: { testers: TESTERS }, - json: true - } - }, - { - testCase: 'remove-beta-testers', - apiFunc: smapiClient.skill.betaTest.removeBetaTesters, - parameters: [TEST_SKILL_ID, TESTERS, noop], - expectedOptions: { - url: `${CONSTANTS.SMAPI.ENDPOINT}/${CONSTANTS.SMAPI.VERSION.V1}/skills/${TEST_SKILL_ID}/betaTest/testers/remove`, - method: CONSTANTS.HTTP_REQUEST.VERB.POST, - headers: { - authorization: TEST_ACCESS_TOKEN - }, - body: { testers: TESTERS }, - json: true - } - }, - { - testCase: 'send-reminder-to-beta-testers', - apiFunc: smapiClient.skill.betaTest.sendReminderToBetaTesters, - parameters: [TEST_SKILL_ID, TESTERS, noop], - expectedOptions: { - url: `${CONSTANTS.SMAPI.ENDPOINT}/${CONSTANTS.SMAPI.VERSION.V1}/skills/${TEST_SKILL_ID}/betaTest/testers/sendReminder`, - method: CONSTANTS.HTTP_REQUEST.VERB.POST, - headers: { - authorization: TEST_ACCESS_TOKEN - }, - body: { testers: TESTERS }, - json: true - } - }, - { - testCase: 'request-feedback-from-beta-testers', - apiFunc: smapiClient.skill.betaTest.requestFeedbackFromBetaTesters, - parameters: [TEST_SKILL_ID, TESTERS, noop], - expectedOptions: { - url: `${CONSTANTS.SMAPI.ENDPOINT}/${CONSTANTS.SMAPI.VERSION.V1}/skills/${TEST_SKILL_ID}/betaTest/testers/requestFeedback`, - method: CONSTANTS.HTTP_REQUEST.VERB.POST, - headers: { - authorization: TEST_ACCESS_TOKEN - }, - body: { testers: TESTERS }, - json: true - } - } - ].forEach(({ testCase, apiFunc, parameters, expectedOptions }) => { - it(`| call ${testCase} successfully`, (done) => { - // setup - AuthorizationController.prototype.tokenRefreshAndRead.callsArgWith(1, null, TEST_ACCESS_TOKEN); - // call - apiFunc(...parameters); - // verify - expect(AuthorizationController.prototype.tokenRefreshAndRead.called).equal(true); - expect(AuthorizationController.prototype.tokenRefreshAndRead.args[0][0]).equal(TEST_PROFILE); - expect(httpClientStub.args[0][0]).deep.equal(expectedOptions); - done(); - }); - }); + [ + { + testCase: "create-beta-test", + apiFunc: smapiClient.skill.betaTest.createBetaTest, + parameters: [TEST_SKILL_ID, TEST_FEEDBACK_EMAIL, noop], + expectedOptions: { + url: `${CONSTANTS.SMAPI.ENDPOINT}/${CONSTANTS.SMAPI.VERSION.V1}/skills/${TEST_SKILL_ID}/betaTest`, + method: CONSTANTS.HTTP_REQUEST.VERB.POST, + headers: { + authorization: TEST_ACCESS_TOKEN, + }, + body: { + feedbackEmail: TEST_FEEDBACK_EMAIL, + }, + json: true, + }, + }, + { + testCase: "update-beta-test", + apiFunc: smapiClient.skill.betaTest.updateBetaTest, + parameters: [TEST_SKILL_ID, TEST_FEEDBACK_EMAIL, noop], + expectedOptions: { + url: `${CONSTANTS.SMAPI.ENDPOINT}/${CONSTANTS.SMAPI.VERSION.V1}/skills/${TEST_SKILL_ID}/betaTest`, + method: CONSTANTS.HTTP_REQUEST.VERB.PUT, + headers: { + authorization: TEST_ACCESS_TOKEN, + }, + body: { + feedbackEmail: TEST_FEEDBACK_EMAIL, + }, + json: true, + }, + }, + { + testCase: "get-beta-test", + apiFunc: smapiClient.skill.betaTest.getBetaTest, + parameters: [TEST_SKILL_ID, noop], + expectedOptions: { + url: `${CONSTANTS.SMAPI.ENDPOINT}/${CONSTANTS.SMAPI.VERSION.V1}/skills/${TEST_SKILL_ID}/betaTest`, + method: CONSTANTS.HTTP_REQUEST.VERB.GET, + headers: { + authorization: TEST_ACCESS_TOKEN, + }, + body: {}, + json: true, + }, + }, + { + testCase: "start-beta-test", + apiFunc: smapiClient.skill.betaTest.startBetaTest, + parameters: [TEST_SKILL_ID, noop], + expectedOptions: { + url: `${CONSTANTS.SMAPI.ENDPOINT}/${CONSTANTS.SMAPI.VERSION.V1}/skills/${TEST_SKILL_ID}/betaTest/start`, + method: CONSTANTS.HTTP_REQUEST.VERB.POST, + headers: { + authorization: TEST_ACCESS_TOKEN, + }, + body: {}, + json: true, + }, + }, + { + testCase: "end-beta-test", + apiFunc: smapiClient.skill.betaTest.endBetaTest, + parameters: [TEST_SKILL_ID, noop], + expectedOptions: { + url: `${CONSTANTS.SMAPI.ENDPOINT}/${CONSTANTS.SMAPI.VERSION.V1}/skills/${TEST_SKILL_ID}/betaTest/end`, + method: CONSTANTS.HTTP_REQUEST.VERB.POST, + headers: { + authorization: TEST_ACCESS_TOKEN, + }, + body: {}, + json: true, + }, + }, + { + testCase: "list-beta-testers", + apiFunc: smapiClient.skill.betaTest.listBetaTesters, + parameters: [TEST_SKILL_ID, MAX_RESULTS, NEXT_TOKEN, noop], + expectedOptions: { + url: `${CONSTANTS.SMAPI.ENDPOINT}/${CONSTANTS.SMAPI.VERSION.V1}/skills/${TEST_SKILL_ID}/betaTest/testers`, + method: CONSTANTS.HTTP_REQUEST.VERB.GET, + headers: { + authorization: TEST_ACCESS_TOKEN, + }, + body: null, + json: false, + }, + }, + { + testCase: "add-beta-testers", + apiFunc: smapiClient.skill.betaTest.addBetaTesters, + parameters: [TEST_SKILL_ID, TESTERS, noop], + expectedOptions: { + url: `${CONSTANTS.SMAPI.ENDPOINT}/${CONSTANTS.SMAPI.VERSION.V1}/skills/${TEST_SKILL_ID}/betaTest/testers/add`, + method: CONSTANTS.HTTP_REQUEST.VERB.POST, + headers: { + authorization: TEST_ACCESS_TOKEN, + }, + body: {testers: TESTERS}, + json: true, + }, + }, + { + testCase: "remove-beta-testers", + apiFunc: smapiClient.skill.betaTest.removeBetaTesters, + parameters: [TEST_SKILL_ID, TESTERS, noop], + expectedOptions: { + url: `${CONSTANTS.SMAPI.ENDPOINT}/${CONSTANTS.SMAPI.VERSION.V1}/skills/${TEST_SKILL_ID}/betaTest/testers/remove`, + method: CONSTANTS.HTTP_REQUEST.VERB.POST, + headers: { + authorization: TEST_ACCESS_TOKEN, + }, + body: {testers: TESTERS}, + json: true, + }, + }, + { + testCase: "send-reminder-to-beta-testers", + apiFunc: smapiClient.skill.betaTest.sendReminderToBetaTesters, + parameters: [TEST_SKILL_ID, TESTERS, noop], + expectedOptions: { + url: `${CONSTANTS.SMAPI.ENDPOINT}/${CONSTANTS.SMAPI.VERSION.V1}/skills/${TEST_SKILL_ID}/betaTest/testers/sendReminder`, + method: CONSTANTS.HTTP_REQUEST.VERB.POST, + headers: { + authorization: TEST_ACCESS_TOKEN, + }, + body: {testers: TESTERS}, + json: true, + }, + }, + { + testCase: "request-feedback-from-beta-testers", + apiFunc: smapiClient.skill.betaTest.requestFeedbackFromBetaTesters, + parameters: [TEST_SKILL_ID, TESTERS, noop], + expectedOptions: { + url: `${CONSTANTS.SMAPI.ENDPOINT}/${CONSTANTS.SMAPI.VERSION.V1}/skills/${TEST_SKILL_ID}/betaTest/testers/requestFeedback`, + method: CONSTANTS.HTTP_REQUEST.VERB.POST, + headers: { + authorization: TEST_ACCESS_TOKEN, + }, + body: {testers: TESTERS}, + json: true, + }, + }, + ].forEach(({testCase, apiFunc, parameters, expectedOptions}) => { + it(`| call ${testCase} successfully`, (done) => { + // setup + AuthorizationController.prototype.tokenRefreshAndRead.callsArgWith(1, null, TEST_ACCESS_TOKEN); + // call + apiFunc(...parameters); + // verify + expect(AuthorizationController.prototype.tokenRefreshAndRead.called).equal(true); + expect(AuthorizationController.prototype.tokenRefreshAndRead.args[0][0]).equal(TEST_PROFILE); + expect(httpClientStub.args[0][0]).deep.equal(expectedOptions); + done(); + }); + }); - afterEach(() => { - sinon.restore(); - }); + afterEach(() => { + sinon.restore(); }); + }); }; diff --git a/test/unit/clients/smapi-client-test/resources/catalog.js b/test/unit/clients/smapi-client-test/resources/catalog.js index 93fb3604..7ffc1806 100644 --- a/test/unit/clients/smapi-client-test/resources/catalog.js +++ b/test/unit/clients/smapi-client-test/resources/catalog.js @@ -1,285 +1,284 @@ -const { expect } = require('chai'); -const sinon = require('sinon'); +const {expect} = require("chai"); +const sinon = require("sinon"); -const httpClient = require('@src/clients/http-client'); -const AuthorizationController = require('@src/controllers/authorization-controller'); -const CONSTANTS = require('@src/utils/constants'); +const httpClient = require("../../../../../lib/clients/http-client"); +const AuthorizationController = require("../../../../../lib/controllers/authorization-controller"); +const CONSTANTS = require("../../../../../lib/utils/constants"); const noop = () => {}; module.exports = (smapiClient) => { - describe('# catalog CRUD related APIs', () => { - let httpClientStub; - beforeEach(() => { - httpClientStub = sinon.stub(httpClient, 'request').callsFake(noop); - sinon.stub(AuthorizationController.prototype, 'tokenRefreshAndRead'); - }); - - const TEST_SKILL_ID = 'skillId'; - const TEST_CATALOG_ID = 'catalogId'; - const TEST_VENDOR_ID = 'vendorId'; - const TEST_UPLOAD_ID = 'uploadId'; - const TEST_NEXT_TOKEN = 'nextToken'; - const TEST_MAX_RESULTS = 'maxResults'; - const TEST_CATALOG_TYPE = 'type'; - const TEST_CATALOG_USAGE = 'usage'; - const TEST_CATALOG_TITLE = 'title'; - const TEST_NUMBER_OF_PARTS = 'numberOfUploadParts'; - const TEST_PART_ETAG_LIST = ['list1', 'list2']; - const TEST_PROFILE = 'testProfile'; - const TEST_ACCESS_TOKEN = 'access_token'; + describe("# catalog CRUD related APIs", () => { + let httpClientStub; + beforeEach(() => { + httpClientStub = sinon.stub(httpClient, "request").callsFake(noop); + sinon.stub(AuthorizationController.prototype, "tokenRefreshAndRead"); + }); - [ - { - testCase: 'create-catalog', - apiFunc: smapiClient.catalog.createCatalog, - parameters: [TEST_CATALOG_TITLE, TEST_CATALOG_TYPE, TEST_CATALOG_USAGE, TEST_VENDOR_ID, noop], - expectedOptions: { - url: `${CONSTANTS.SMAPI.ENDPOINT}/v0/catalogs`, - method: CONSTANTS.HTTP_REQUEST.VERB.POST, - headers: { - authorization: TEST_ACCESS_TOKEN - }, - body: { - title: TEST_CATALOG_TITLE, - type: TEST_CATALOG_TYPE, - usage: TEST_CATALOG_USAGE, - vendorId: TEST_VENDOR_ID - }, - json: true - } - }, - { - testCase: 'get-catalog', - apiFunc: smapiClient.catalog.getCatalog, - parameters: [TEST_CATALOG_ID, noop], - expectedOptions: { - url: `${CONSTANTS.SMAPI.ENDPOINT}/v0/catalogs/${TEST_CATALOG_ID}`, - method: CONSTANTS.HTTP_REQUEST.VERB.GET, - headers: { - authorization: TEST_ACCESS_TOKEN - }, - body: null, - json: false - } - }, - { - testCase: 'list-catalogs', - apiFunc: smapiClient.catalog.listCatalogs, - parameters: [TEST_VENDOR_ID, { nextToken: TEST_NEXT_TOKEN, maxResults: TEST_MAX_RESULTS }, noop], - expectedOptions: { - url: `${CONSTANTS.SMAPI.ENDPOINT}/v0/catalogs?nextToken=${TEST_NEXT_TOKEN}&maxResults=${TEST_MAX_RESULTS}&vendorId=${TEST_VENDOR_ID}`, - method: CONSTANTS.HTTP_REQUEST.VERB.GET, - headers: { - authorization: TEST_ACCESS_TOKEN - }, - body: null, - json: false - } - }, - { - testCase: 'list-catalogs without next token', - apiFunc: smapiClient.catalog.listCatalogs, - parameters: [TEST_VENDOR_ID, { maxResults: TEST_MAX_RESULTS }, noop], - expectedOptions: { - url: `${CONSTANTS.SMAPI.ENDPOINT}/v0/catalogs?maxResults=${TEST_MAX_RESULTS}&vendorId=${TEST_VENDOR_ID}`, - method: CONSTANTS.HTTP_REQUEST.VERB.GET, - headers: { - authorization: TEST_ACCESS_TOKEN - }, - body: null, - json: false - } + const TEST_SKILL_ID = "skillId"; + const TEST_CATALOG_ID = "catalogId"; + const TEST_VENDOR_ID = "vendorId"; + const TEST_UPLOAD_ID = "uploadId"; + const TEST_NEXT_TOKEN = "nextToken"; + const TEST_MAX_RESULTS = "maxResults"; + const TEST_CATALOG_TYPE = "type"; + const TEST_CATALOG_USAGE = "usage"; + const TEST_CATALOG_TITLE = "title"; + const TEST_NUMBER_OF_PARTS = "numberOfUploadParts"; + const TEST_PART_ETAG_LIST = ["list1", "list2"]; + const TEST_PROFILE = "testProfile"; + const TEST_ACCESS_TOKEN = "access_token"; - }, - { - testCase: 'list-catalogs without max results', - apiFunc: smapiClient.catalog.listCatalogs, - parameters: [TEST_VENDOR_ID, { nextToken: TEST_NEXT_TOKEN }, noop], - expectedOptions: { - url: `${CONSTANTS.SMAPI.ENDPOINT}/v0/catalogs?nextToken=${TEST_NEXT_TOKEN}&vendorId=${TEST_VENDOR_ID}&maxResults=50`, - method: CONSTANTS.HTTP_REQUEST.VERB.GET, - headers: { - authorization: TEST_ACCESS_TOKEN - }, - body: null, - json: false - } - }, - { - testCase: 'list-catalogs without max results nor next token', - apiFunc: smapiClient.catalog.listCatalogs, - parameters: [TEST_VENDOR_ID, {}, noop], - expectedOptions: { - url: `${CONSTANTS.SMAPI.ENDPOINT}/v0/catalogs?vendorId=${TEST_VENDOR_ID}&maxResults=50`, - method: CONSTANTS.HTTP_REQUEST.VERB.GET, - headers: { - authorization: TEST_ACCESS_TOKEN - }, - body: null, - json: false - } - }, - { - testCase: 'list-catalogs with null query', - apiFunc: smapiClient.catalog.listCatalogs, - parameters: [TEST_VENDOR_ID, null, noop], - expectedOptions: { - url: `${CONSTANTS.SMAPI.ENDPOINT}/v0/catalogs?vendorId=${TEST_VENDOR_ID}&maxResults=50`, - method: CONSTANTS.HTTP_REQUEST.VERB.GET, - headers: { - authorization: TEST_ACCESS_TOKEN - }, - body: null, - json: false - } - }, - { - testCase: 'create-catalog-upload', - apiFunc: smapiClient.catalog.createCatalogUpload, - parameters: [TEST_CATALOG_ID, TEST_NUMBER_OF_PARTS, noop], - expectedOptions: { - url: `${CONSTANTS.SMAPI.ENDPOINT}/v0/catalogs/${TEST_CATALOG_ID}/uploads`, - method: CONSTANTS.HTTP_REQUEST.VERB.POST, - headers: { - authorization: TEST_ACCESS_TOKEN - }, - body: { - numberOfUploadParts: TEST_NUMBER_OF_PARTS - }, - json: true - } - }, - { - testCase: 'get-catalog-upload', - apiFunc: smapiClient.catalog.getCatalogUpload, - parameters: [TEST_CATALOG_ID, TEST_UPLOAD_ID, noop], - expectedOptions: { - url: `${CONSTANTS.SMAPI.ENDPOINT}/v0/catalogs/${TEST_CATALOG_ID}/uploads/${TEST_UPLOAD_ID}`, - method: CONSTANTS.HTTP_REQUEST.VERB.GET, - headers: { - authorization: TEST_ACCESS_TOKEN - }, - body: null, - json: false - } - }, - { - testCase: 'list-catalog-uploads', - apiFunc: smapiClient.catalog.listCatalogUploads, - parameters: [TEST_CATALOG_ID, { nextToken: TEST_NEXT_TOKEN, maxResults: TEST_MAX_RESULTS }, noop], - expectedOptions: { - url: `${CONSTANTS.SMAPI.ENDPOINT}/v0/catalogs/${TEST_CATALOG_ID}/uploads?nextToken=${TEST_NEXT_TOKEN}&maxResults=${TEST_MAX_RESULTS}`, - method: CONSTANTS.HTTP_REQUEST.VERB.GET, - headers: { - authorization: TEST_ACCESS_TOKEN - }, - body: null, - json: false - } - }, - { - testCase: 'list-catalog-uploads without next token', - apiFunc: smapiClient.catalog.listCatalogUploads, - parameters: [TEST_CATALOG_ID, { maxResults: TEST_MAX_RESULTS }, noop], - expectedOptions: { - url: `${CONSTANTS.SMAPI.ENDPOINT}/v0/catalogs/${TEST_CATALOG_ID}/uploads?maxResults=${TEST_MAX_RESULTS}`, - method: CONSTANTS.HTTP_REQUEST.VERB.GET, - headers: { - authorization: TEST_ACCESS_TOKEN - }, - body: null, - json: false - } - }, - { - testCase: 'list-catalog-uploads without max results', - apiFunc: smapiClient.catalog.listCatalogUploads, - parameters: [TEST_CATALOG_ID, { nextToken: TEST_NEXT_TOKEN }, noop], - expectedOptions: { - url: `${CONSTANTS.SMAPI.ENDPOINT}/v0/catalogs/${TEST_CATALOG_ID}/uploads?nextToken=${TEST_NEXT_TOKEN}&maxResults=50`, - method: CONSTANTS.HTTP_REQUEST.VERB.GET, - headers: { - authorization: TEST_ACCESS_TOKEN - }, - body: null, - json: false - } - }, - { - testCase: 'list-catalog-uploads without max results nor next token', - apiFunc: smapiClient.catalog.listCatalogUploads, - parameters: [TEST_CATALOG_ID, {}, noop], - expectedOptions: { - url: `${CONSTANTS.SMAPI.ENDPOINT}/v0/catalogs/${TEST_CATALOG_ID}/uploads?maxResults=50`, - method: CONSTANTS.HTTP_REQUEST.VERB.GET, - headers: { - authorization: TEST_ACCESS_TOKEN - }, - body: null, - json: false - } - }, - { - testCase: 'list-catalog-uploads with null query', - apiFunc: smapiClient.catalog.listCatalogUploads, - parameters: [TEST_CATALOG_ID, null, noop], - expectedOptions: { - url: `${CONSTANTS.SMAPI.ENDPOINT}/v0/catalogs/${TEST_CATALOG_ID}/uploads?maxResults=50`, - method: CONSTANTS.HTTP_REQUEST.VERB.GET, - headers: { - authorization: TEST_ACCESS_TOKEN - }, - body: null, - json: false - } - }, - { - testCase: 'associate-catalog-with-skill', - apiFunc: smapiClient.catalog.associateCatalogWithSkill, - parameters: [TEST_SKILL_ID, TEST_CATALOG_ID, noop], - expectedOptions: { - url: `${CONSTANTS.SMAPI.ENDPOINT}/v0/skills/${TEST_SKILL_ID}/catalogs/${TEST_CATALOG_ID}`, - method: CONSTANTS.HTTP_REQUEST.VERB.PUT, - headers: { - authorization: TEST_ACCESS_TOKEN - }, - body: null, - json: false - } - }, - { - testCase: 'complete-catalog-upload', - apiFunc: smapiClient.catalog.completeCatalogUpload, - parameters: [TEST_CATALOG_ID, TEST_UPLOAD_ID, TEST_PART_ETAG_LIST, noop], - expectedOptions: { - url: `${CONSTANTS.SMAPI.ENDPOINT}/v0/catalogs/${TEST_CATALOG_ID}/uploads/${TEST_UPLOAD_ID}`, - method: CONSTANTS.HTTP_REQUEST.VERB.POST, - headers: { - authorization: TEST_ACCESS_TOKEN - }, - body: { - partETags: TEST_PART_ETAG_LIST - }, - json: true - } - }, - ].forEach(({ testCase, apiFunc, parameters, expectedOptions }) => { - it(`| call ${testCase} successfully`, (done) => { - // setup - AuthorizationController.prototype.tokenRefreshAndRead.callsArgWith(1, null, TEST_ACCESS_TOKEN); - // call - apiFunc(...parameters); - // verify - expect(AuthorizationController.prototype.tokenRefreshAndRead.called).equal(true); - expect(AuthorizationController.prototype.tokenRefreshAndRead.args[0][0]).equal(TEST_PROFILE); - expect(httpClientStub.args[0][0]).deep.equal(expectedOptions); - done(); - }); - }); + [ + { + testCase: "create-catalog", + apiFunc: smapiClient.catalog.createCatalog, + parameters: [TEST_CATALOG_TITLE, TEST_CATALOG_TYPE, TEST_CATALOG_USAGE, TEST_VENDOR_ID, noop], + expectedOptions: { + url: `${CONSTANTS.SMAPI.ENDPOINT}/v0/catalogs`, + method: CONSTANTS.HTTP_REQUEST.VERB.POST, + headers: { + authorization: TEST_ACCESS_TOKEN, + }, + body: { + title: TEST_CATALOG_TITLE, + type: TEST_CATALOG_TYPE, + usage: TEST_CATALOG_USAGE, + vendorId: TEST_VENDOR_ID, + }, + json: true, + }, + }, + { + testCase: "get-catalog", + apiFunc: smapiClient.catalog.getCatalog, + parameters: [TEST_CATALOG_ID, noop], + expectedOptions: { + url: `${CONSTANTS.SMAPI.ENDPOINT}/v0/catalogs/${TEST_CATALOG_ID}`, + method: CONSTANTS.HTTP_REQUEST.VERB.GET, + headers: { + authorization: TEST_ACCESS_TOKEN, + }, + body: null, + json: false, + }, + }, + { + testCase: "list-catalogs", + apiFunc: smapiClient.catalog.listCatalogs, + parameters: [TEST_VENDOR_ID, {nextToken: TEST_NEXT_TOKEN, maxResults: TEST_MAX_RESULTS}, noop], + expectedOptions: { + url: `${CONSTANTS.SMAPI.ENDPOINT}/v0/catalogs?nextToken=${TEST_NEXT_TOKEN}&maxResults=${TEST_MAX_RESULTS}&vendorId=${TEST_VENDOR_ID}`, + method: CONSTANTS.HTTP_REQUEST.VERB.GET, + headers: { + authorization: TEST_ACCESS_TOKEN, + }, + body: null, + json: false, + }, + }, + { + testCase: "list-catalogs without next token", + apiFunc: smapiClient.catalog.listCatalogs, + parameters: [TEST_VENDOR_ID, {maxResults: TEST_MAX_RESULTS}, noop], + expectedOptions: { + url: `${CONSTANTS.SMAPI.ENDPOINT}/v0/catalogs?maxResults=${TEST_MAX_RESULTS}&vendorId=${TEST_VENDOR_ID}`, + method: CONSTANTS.HTTP_REQUEST.VERB.GET, + headers: { + authorization: TEST_ACCESS_TOKEN, + }, + body: null, + json: false, + }, + }, + { + testCase: "list-catalogs without max results", + apiFunc: smapiClient.catalog.listCatalogs, + parameters: [TEST_VENDOR_ID, {nextToken: TEST_NEXT_TOKEN}, noop], + expectedOptions: { + url: `${CONSTANTS.SMAPI.ENDPOINT}/v0/catalogs?nextToken=${TEST_NEXT_TOKEN}&vendorId=${TEST_VENDOR_ID}&maxResults=50`, + method: CONSTANTS.HTTP_REQUEST.VERB.GET, + headers: { + authorization: TEST_ACCESS_TOKEN, + }, + body: null, + json: false, + }, + }, + { + testCase: "list-catalogs without max results nor next token", + apiFunc: smapiClient.catalog.listCatalogs, + parameters: [TEST_VENDOR_ID, {}, noop], + expectedOptions: { + url: `${CONSTANTS.SMAPI.ENDPOINT}/v0/catalogs?vendorId=${TEST_VENDOR_ID}&maxResults=50`, + method: CONSTANTS.HTTP_REQUEST.VERB.GET, + headers: { + authorization: TEST_ACCESS_TOKEN, + }, + body: null, + json: false, + }, + }, + { + testCase: "list-catalogs with null query", + apiFunc: smapiClient.catalog.listCatalogs, + parameters: [TEST_VENDOR_ID, null, noop], + expectedOptions: { + url: `${CONSTANTS.SMAPI.ENDPOINT}/v0/catalogs?vendorId=${TEST_VENDOR_ID}&maxResults=50`, + method: CONSTANTS.HTTP_REQUEST.VERB.GET, + headers: { + authorization: TEST_ACCESS_TOKEN, + }, + body: null, + json: false, + }, + }, + { + testCase: "create-catalog-upload", + apiFunc: smapiClient.catalog.createCatalogUpload, + parameters: [TEST_CATALOG_ID, TEST_NUMBER_OF_PARTS, noop], + expectedOptions: { + url: `${CONSTANTS.SMAPI.ENDPOINT}/v0/catalogs/${TEST_CATALOG_ID}/uploads`, + method: CONSTANTS.HTTP_REQUEST.VERB.POST, + headers: { + authorization: TEST_ACCESS_TOKEN, + }, + body: { + numberOfUploadParts: TEST_NUMBER_OF_PARTS, + }, + json: true, + }, + }, + { + testCase: "get-catalog-upload", + apiFunc: smapiClient.catalog.getCatalogUpload, + parameters: [TEST_CATALOG_ID, TEST_UPLOAD_ID, noop], + expectedOptions: { + url: `${CONSTANTS.SMAPI.ENDPOINT}/v0/catalogs/${TEST_CATALOG_ID}/uploads/${TEST_UPLOAD_ID}`, + method: CONSTANTS.HTTP_REQUEST.VERB.GET, + headers: { + authorization: TEST_ACCESS_TOKEN, + }, + body: null, + json: false, + }, + }, + { + testCase: "list-catalog-uploads", + apiFunc: smapiClient.catalog.listCatalogUploads, + parameters: [TEST_CATALOG_ID, {nextToken: TEST_NEXT_TOKEN, maxResults: TEST_MAX_RESULTS}, noop], + expectedOptions: { + url: `${CONSTANTS.SMAPI.ENDPOINT}/v0/catalogs/${TEST_CATALOG_ID}/uploads?nextToken=${TEST_NEXT_TOKEN}&maxResults=${TEST_MAX_RESULTS}`, + method: CONSTANTS.HTTP_REQUEST.VERB.GET, + headers: { + authorization: TEST_ACCESS_TOKEN, + }, + body: null, + json: false, + }, + }, + { + testCase: "list-catalog-uploads without next token", + apiFunc: smapiClient.catalog.listCatalogUploads, + parameters: [TEST_CATALOG_ID, {maxResults: TEST_MAX_RESULTS}, noop], + expectedOptions: { + url: `${CONSTANTS.SMAPI.ENDPOINT}/v0/catalogs/${TEST_CATALOG_ID}/uploads?maxResults=${TEST_MAX_RESULTS}`, + method: CONSTANTS.HTTP_REQUEST.VERB.GET, + headers: { + authorization: TEST_ACCESS_TOKEN, + }, + body: null, + json: false, + }, + }, + { + testCase: "list-catalog-uploads without max results", + apiFunc: smapiClient.catalog.listCatalogUploads, + parameters: [TEST_CATALOG_ID, {nextToken: TEST_NEXT_TOKEN}, noop], + expectedOptions: { + url: `${CONSTANTS.SMAPI.ENDPOINT}/v0/catalogs/${TEST_CATALOG_ID}/uploads?nextToken=${TEST_NEXT_TOKEN}&maxResults=50`, + method: CONSTANTS.HTTP_REQUEST.VERB.GET, + headers: { + authorization: TEST_ACCESS_TOKEN, + }, + body: null, + json: false, + }, + }, + { + testCase: "list-catalog-uploads without max results nor next token", + apiFunc: smapiClient.catalog.listCatalogUploads, + parameters: [TEST_CATALOG_ID, {}, noop], + expectedOptions: { + url: `${CONSTANTS.SMAPI.ENDPOINT}/v0/catalogs/${TEST_CATALOG_ID}/uploads?maxResults=50`, + method: CONSTANTS.HTTP_REQUEST.VERB.GET, + headers: { + authorization: TEST_ACCESS_TOKEN, + }, + body: null, + json: false, + }, + }, + { + testCase: "list-catalog-uploads with null query", + apiFunc: smapiClient.catalog.listCatalogUploads, + parameters: [TEST_CATALOG_ID, null, noop], + expectedOptions: { + url: `${CONSTANTS.SMAPI.ENDPOINT}/v0/catalogs/${TEST_CATALOG_ID}/uploads?maxResults=50`, + method: CONSTANTS.HTTP_REQUEST.VERB.GET, + headers: { + authorization: TEST_ACCESS_TOKEN, + }, + body: null, + json: false, + }, + }, + { + testCase: "associate-catalog-with-skill", + apiFunc: smapiClient.catalog.associateCatalogWithSkill, + parameters: [TEST_SKILL_ID, TEST_CATALOG_ID, noop], + expectedOptions: { + url: `${CONSTANTS.SMAPI.ENDPOINT}/v0/skills/${TEST_SKILL_ID}/catalogs/${TEST_CATALOG_ID}`, + method: CONSTANTS.HTTP_REQUEST.VERB.PUT, + headers: { + authorization: TEST_ACCESS_TOKEN, + }, + body: null, + json: false, + }, + }, + { + testCase: "complete-catalog-upload", + apiFunc: smapiClient.catalog.completeCatalogUpload, + parameters: [TEST_CATALOG_ID, TEST_UPLOAD_ID, TEST_PART_ETAG_LIST, noop], + expectedOptions: { + url: `${CONSTANTS.SMAPI.ENDPOINT}/v0/catalogs/${TEST_CATALOG_ID}/uploads/${TEST_UPLOAD_ID}`, + method: CONSTANTS.HTTP_REQUEST.VERB.POST, + headers: { + authorization: TEST_ACCESS_TOKEN, + }, + body: { + partETags: TEST_PART_ETAG_LIST, + }, + json: true, + }, + }, + ].forEach(({testCase, apiFunc, parameters, expectedOptions}) => { + it(`| call ${testCase} successfully`, (done) => { + // setup + AuthorizationController.prototype.tokenRefreshAndRead.callsArgWith(1, null, TEST_ACCESS_TOKEN); + // call + apiFunc(...parameters); + // verify + expect(AuthorizationController.prototype.tokenRefreshAndRead.called).equal(true); + expect(AuthorizationController.prototype.tokenRefreshAndRead.args[0][0]).equal(TEST_PROFILE); + expect(httpClientStub.args[0][0]).deep.equal(expectedOptions); + done(); + }); + }); - afterEach(() => { - sinon.restore(); - }); + afterEach(() => { + sinon.restore(); }); + }); }; diff --git a/test/unit/clients/smapi-client-test/resources/evaluations.js b/test/unit/clients/smapi-client-test/resources/evaluations.js index ba27b51b..3caa56ae 100644 --- a/test/unit/clients/smapi-client-test/resources/evaluations.js +++ b/test/unit/clients/smapi-client-test/resources/evaluations.js @@ -1,78 +1,78 @@ -const { expect } = require('chai'); -const sinon = require('sinon'); +const {expect} = require("chai"); +const sinon = require("sinon"); -const httpClient = require('@src/clients/http-client'); -const CONSTANTS = require('@src/utils/constants'); -const AuthorizationController = require('@src/controllers/authorization-controller'); +const httpClient = require("../../../../../lib/clients/http-client"); +const CONSTANTS = require("../../../../../lib/utils/constants"); +const AuthorizationController = require("../../../../../lib/controllers/authorization-controller"); const noop = () => {}; module.exports = (smapiClient) => { - describe('# skill evaluations APIs', () => { - let httpClientStub; - const TEST_SKILL_ID = 'skillId'; - const TEST_LOCALE = 'test'; - const TEST_STAGE = 'live'; - const TEST_UTTERANCE = 'utterance'; - const TEST_MULTI_TURN_TOKEN = 'multiTurnToken'; - const TEST_PROFILE = 'testProfile'; - const TEST_ACCESS_TOKEN = 'access_token'; + describe("# skill evaluations APIs", () => { + let httpClientStub; + const TEST_SKILL_ID = "skillId"; + const TEST_LOCALE = "test"; + const TEST_STAGE = "live"; + const TEST_UTTERANCE = "utterance"; + const TEST_MULTI_TURN_TOKEN = "multiTurnToken"; + const TEST_PROFILE = "testProfile"; + const TEST_ACCESS_TOKEN = "access_token"; - beforeEach(() => { - httpClientStub = sinon.stub(httpClient, 'request').callsFake(noop); - sinon.stub(AuthorizationController.prototype, 'tokenRefreshAndRead'); - }); + beforeEach(() => { + httpClientStub = sinon.stub(httpClient, "request").callsFake(noop); + sinon.stub(AuthorizationController.prototype, "tokenRefreshAndRead"); + }); - [ - { - testCase: 'nlu-profile', - apiFunc: smapiClient.skill.evaluations.callProfileNlu, - parameters: [TEST_SKILL_ID, TEST_STAGE, TEST_LOCALE, TEST_UTTERANCE, TEST_MULTI_TURN_TOKEN, noop], - expectedOptions: { - url: `${CONSTANTS.SMAPI.ENDPOINT}/v1/skills/${TEST_SKILL_ID}/stages/${TEST_STAGE}/interactionModel/locales/${TEST_LOCALE}/profileNlu`, - method: CONSTANTS.HTTP_REQUEST.VERB.POST, - headers: { - authorization: TEST_ACCESS_TOKEN - }, - body: { - utterance: TEST_UTTERANCE, - multiTurnToken: TEST_MULTI_TURN_TOKEN - }, - json: true - } - }, - { - testCase: 'nlu-profile without multiTurnToken', - apiFunc: smapiClient.skill.evaluations.callProfileNlu, - parameters: [TEST_SKILL_ID, TEST_STAGE, TEST_LOCALE, TEST_UTTERANCE, null, noop], - expectedOptions: { - url: `${CONSTANTS.SMAPI.ENDPOINT}/v1/skills/${TEST_SKILL_ID}/stages/${TEST_STAGE}/interactionModel/locales/${TEST_LOCALE}/profileNlu`, - method: CONSTANTS.HTTP_REQUEST.VERB.POST, - headers: { - authorization: TEST_ACCESS_TOKEN - }, - body: { - utterance: TEST_UTTERANCE - }, - json: true - } - } - ].forEach(({ testCase, apiFunc, parameters, expectedOptions }) => { - it(`| call ${testCase} successfully`, (done) => { - // setup - AuthorizationController.prototype.tokenRefreshAndRead.callsArgWith(1, null, TEST_ACCESS_TOKEN); - // call - apiFunc(...parameters); - // verify - expect(AuthorizationController.prototype.tokenRefreshAndRead.called).equal(true); - expect(AuthorizationController.prototype.tokenRefreshAndRead.args[0][0]).equal(TEST_PROFILE); - expect(httpClientStub.args[0][0]).deep.equal(expectedOptions); - done(); - }); - }); + [ + { + testCase: "nlu-profile", + apiFunc: smapiClient.skill.evaluations.callProfileNlu, + parameters: [TEST_SKILL_ID, TEST_STAGE, TEST_LOCALE, TEST_UTTERANCE, TEST_MULTI_TURN_TOKEN, noop], + expectedOptions: { + url: `${CONSTANTS.SMAPI.ENDPOINT}/v1/skills/${TEST_SKILL_ID}/stages/${TEST_STAGE}/interactionModel/locales/${TEST_LOCALE}/profileNlu`, + method: CONSTANTS.HTTP_REQUEST.VERB.POST, + headers: { + authorization: TEST_ACCESS_TOKEN, + }, + body: { + utterance: TEST_UTTERANCE, + multiTurnToken: TEST_MULTI_TURN_TOKEN, + }, + json: true, + }, + }, + { + testCase: "nlu-profile without multiTurnToken", + apiFunc: smapiClient.skill.evaluations.callProfileNlu, + parameters: [TEST_SKILL_ID, TEST_STAGE, TEST_LOCALE, TEST_UTTERANCE, null, noop], + expectedOptions: { + url: `${CONSTANTS.SMAPI.ENDPOINT}/v1/skills/${TEST_SKILL_ID}/stages/${TEST_STAGE}/interactionModel/locales/${TEST_LOCALE}/profileNlu`, + method: CONSTANTS.HTTP_REQUEST.VERB.POST, + headers: { + authorization: TEST_ACCESS_TOKEN, + }, + body: { + utterance: TEST_UTTERANCE, + }, + json: true, + }, + }, + ].forEach(({testCase, apiFunc, parameters, expectedOptions}) => { + it(`| call ${testCase} successfully`, (done) => { + // setup + AuthorizationController.prototype.tokenRefreshAndRead.callsArgWith(1, null, TEST_ACCESS_TOKEN); + // call + apiFunc(...parameters); + // verify + expect(AuthorizationController.prototype.tokenRefreshAndRead.called).equal(true); + expect(AuthorizationController.prototype.tokenRefreshAndRead.args[0][0]).equal(TEST_PROFILE); + expect(httpClientStub.args[0][0]).deep.equal(expectedOptions); + done(); + }); + }); - afterEach(() => { - sinon.restore(); - }); + afterEach(() => { + sinon.restore(); }); + }); }; diff --git a/test/unit/clients/smapi-client-test/resources/history.js b/test/unit/clients/smapi-client-test/resources/history.js index 7fddcb6f..7a789539 100644 --- a/test/unit/clients/smapi-client-test/resources/history.js +++ b/test/unit/clients/smapi-client-test/resources/history.js @@ -1,73 +1,77 @@ -const { expect } = require('chai'); -const sinon = require('sinon'); +const {expect} = require("chai"); +const sinon = require("sinon"); -const httpClient = require('@src/clients/http-client'); -const CONSTANTS = require('@src/utils/constants'); -const AuthorizationController = require('@src/controllers/authorization-controller'); +const httpClient = require("../../../../../lib/clients/http-client"); +const CONSTANTS = require("../../../../../lib/utils/constants"); +const AuthorizationController = require("../../../../../lib/controllers/authorization-controller"); const noop = () => {}; module.exports = (smapiClient) => { - describe('# skill intent request history API', () => { - let httpClientStub; - const TEST_SKILL_ID = 'skillId'; - const TEST_NEXT_TOKEN = 'nextToken'; - const TEST_MAX_RESULTS = 'maxResults'; - const TEST_SORT_DIRECTION = 'sortDirection'; - const TEST_SORT_FIELD = 'sortField'; - const TEST_PROFILE = 'testProfile'; - const TEST_ACCESS_TOKEN = 'access_token'; + describe("# skill intent request history API", () => { + let httpClientStub; + const TEST_SKILL_ID = "skillId"; + const TEST_NEXT_TOKEN = "nextToken"; + const TEST_MAX_RESULTS = "maxResults"; + const TEST_SORT_DIRECTION = "sortDirection"; + const TEST_SORT_FIELD = "sortField"; + const TEST_PROFILE = "testProfile"; + const TEST_ACCESS_TOKEN = "access_token"; - beforeEach(() => { - httpClientStub = sinon.stub(httpClient, 'request').callsFake(noop); - sinon.stub(AuthorizationController.prototype, 'tokenRefreshAndRead'); - }); + beforeEach(() => { + httpClientStub = sinon.stub(httpClient, "request").callsFake(noop); + sinon.stub(AuthorizationController.prototype, "tokenRefreshAndRead"); + }); - [ - { - testCase: 'intent-requests-history with null params', - apiFunc: smapiClient.skill.history.getIntentRequestsHistory, - parameters: [TEST_SKILL_ID, {}, noop], - expectedOptions: { - url: `${CONSTANTS.SMAPI.ENDPOINT}/v1/skills/${TEST_SKILL_ID}/history/intentRequests`, - method: CONSTANTS.HTTP_REQUEST.VERB.GET, - headers: { - authorization: TEST_ACCESS_TOKEN - }, - body: null, - json: false - } - }, - { - testCase: 'intent-requests-history', - apiFunc: smapiClient.skill.history.getIntentRequestsHistory, - parameters: [TEST_SKILL_ID, { maxResults: TEST_MAX_RESULTS, sortDirection: TEST_SORT_DIRECTION, sortField: TEST_SORT_FIELD, nextToken: TEST_NEXT_TOKEN }, noop], - expectedOptions: { - url: `${CONSTANTS.SMAPI.ENDPOINT}/v1/skills/${TEST_SKILL_ID}/history/intentRequests?maxResults=${TEST_MAX_RESULTS}&sortDirection=${TEST_SORT_DIRECTION}&sortField=${TEST_SORT_FIELD}&nextToken=${TEST_NEXT_TOKEN}`, - method: CONSTANTS.HTTP_REQUEST.VERB.GET, - headers: { - authorization: TEST_ACCESS_TOKEN - }, - body: null, - json: false - } - }, - ].forEach(({ testCase, apiFunc, parameters, expectedOptions }) => { - it(`| call ${testCase} successfully`, (done) => { - // setup - AuthorizationController.prototype.tokenRefreshAndRead.callsArgWith(1, null, TEST_ACCESS_TOKEN); - // call - apiFunc(...parameters); - // verify - expect(AuthorizationController.prototype.tokenRefreshAndRead.called).equal(true); - expect(AuthorizationController.prototype.tokenRefreshAndRead.args[0][0]).equal(TEST_PROFILE); - expect(httpClientStub.args[0][0]).deep.equal(expectedOptions); - done(); - }); - }); + [ + { + testCase: "intent-requests-history with null params", + apiFunc: smapiClient.skill.history.getIntentRequestsHistory, + parameters: [TEST_SKILL_ID, {}, noop], + expectedOptions: { + url: `${CONSTANTS.SMAPI.ENDPOINT}/v1/skills/${TEST_SKILL_ID}/history/intentRequests`, + method: CONSTANTS.HTTP_REQUEST.VERB.GET, + headers: { + authorization: TEST_ACCESS_TOKEN, + }, + body: null, + json: false, + }, + }, + { + testCase: "intent-requests-history", + apiFunc: smapiClient.skill.history.getIntentRequestsHistory, + parameters: [ + TEST_SKILL_ID, + {maxResults: TEST_MAX_RESULTS, sortDirection: TEST_SORT_DIRECTION, sortField: TEST_SORT_FIELD, nextToken: TEST_NEXT_TOKEN}, + noop, + ], + expectedOptions: { + url: `${CONSTANTS.SMAPI.ENDPOINT}/v1/skills/${TEST_SKILL_ID}/history/intentRequests?maxResults=${TEST_MAX_RESULTS}&sortDirection=${TEST_SORT_DIRECTION}&sortField=${TEST_SORT_FIELD}&nextToken=${TEST_NEXT_TOKEN}`, + method: CONSTANTS.HTTP_REQUEST.VERB.GET, + headers: { + authorization: TEST_ACCESS_TOKEN, + }, + body: null, + json: false, + }, + }, + ].forEach(({testCase, apiFunc, parameters, expectedOptions}) => { + it(`| call ${testCase} successfully`, (done) => { + // setup + AuthorizationController.prototype.tokenRefreshAndRead.callsArgWith(1, null, TEST_ACCESS_TOKEN); + // call + apiFunc(...parameters); + // verify + expect(AuthorizationController.prototype.tokenRefreshAndRead.called).equal(true); + expect(AuthorizationController.prototype.tokenRefreshAndRead.args[0][0]).equal(TEST_PROFILE); + expect(httpClientStub.args[0][0]).deep.equal(expectedOptions); + done(); + }); + }); - afterEach(() => { - sinon.restore(); - }); + afterEach(() => { + sinon.restore(); }); + }); }; diff --git a/test/unit/clients/smapi-client-test/resources/interaction-model.js b/test/unit/clients/smapi-client-test/resources/interaction-model.js index 93171465..77f5eb70 100644 --- a/test/unit/clients/smapi-client-test/resources/interaction-model.js +++ b/test/unit/clients/smapi-client-test/resources/interaction-model.js @@ -1,216 +1,241 @@ -const { expect } = require('chai'); -const sinon = require('sinon'); +const {expect} = require("chai"); +const sinon = require("sinon"); -const httpClient = require('@src/clients/http-client'); -const AuthorizationController = require('@src/controllers/authorization-controller'); -const CONSTANTS = require('@src/utils/constants'); +const httpClient = require("../../../../../lib/clients/http-client"); +const AuthorizationController = require("../../../../../lib/controllers/authorization-controller"); +const CONSTANTS = require("../../../../../lib/utils/constants"); const noop = () => {}; module.exports = (smapiClient) => { - describe('# skill interaction model APIs', () => { - let httpClientStub; - beforeEach(() => { - httpClientStub = sinon.stub(httpClient, 'request').callsFake(noop); - sinon.stub(AuthorizationController.prototype, 'tokenRefreshAndRead'); - }); + describe("# skill interaction model APIs", () => { + let httpClientStub; + beforeEach(() => { + httpClientStub = sinon.stub(httpClient, "request").callsFake(noop); + sinon.stub(AuthorizationController.prototype, "tokenRefreshAndRead"); + }); - const TEST_SKILL_ID = 'skillId'; - const TEST_SKILL_STAGE = 'skillStage'; - const TEST_LOCALE = 'locale'; - const TEST_MODEL = { interactionModel: 'model' }; - const TEST_ETAG = 'eTag'; - const TEST_NEXT_TOKEN = 'nextToken'; - const TEST_MAX_RESULTS = 'maxResults'; - const TEST_SORT_DIRECTION = 'sortDirection'; - const TEST_SORT_FIELD = 'sortField'; - const TEST_PROFILE = 'testProfile'; - const TEST_ACCESS_TOKEN = 'access_token'; + const TEST_SKILL_ID = "skillId"; + const TEST_SKILL_STAGE = "skillStage"; + const TEST_LOCALE = "locale"; + const TEST_MODEL = {interactionModel: "model"}; + const TEST_ETAG = "eTag"; + const TEST_NEXT_TOKEN = "nextToken"; + const TEST_MAX_RESULTS = "maxResults"; + const TEST_SORT_DIRECTION = "sortDirection"; + const TEST_SORT_FIELD = "sortField"; + const TEST_PROFILE = "testProfile"; + const TEST_ACCESS_TOKEN = "access_token"; - [ - { - testCase: 'get-interaction-model', - apiFunc: smapiClient.skill.interactionModel.getInteractionModel, - parameters: [TEST_SKILL_ID, TEST_SKILL_STAGE, TEST_LOCALE, noop], - expectedOptions: { - url: `${CONSTANTS.SMAPI.ENDPOINT}/v1/skills/${TEST_SKILL_ID}/stages/${TEST_SKILL_STAGE}/interactionModel/locales/${TEST_LOCALE}`, - method: CONSTANTS.HTTP_REQUEST.VERB.GET, - headers: { - authorization: TEST_ACCESS_TOKEN - }, - body: null, - json: false - } - }, - { - testCase: 'set-interaction-model', - apiFunc: smapiClient.skill.interactionModel.setInteractionModel, - parameters: [TEST_SKILL_ID, TEST_SKILL_STAGE, TEST_LOCALE, TEST_MODEL, TEST_ETAG, noop], - expectedOptions: { - url: `${CONSTANTS.SMAPI.ENDPOINT}/v1/skills/${TEST_SKILL_ID}/stages/${TEST_SKILL_STAGE}/interactionModel/locales/${TEST_LOCALE}`, - method: CONSTANTS.HTTP_REQUEST.VERB.PUT, - headers: { - 'If-Match': TEST_ETAG, - authorization: TEST_ACCESS_TOKEN - }, - body: { - interactionModel: 'model' - }, - json: true - } - }, - { - testCase: 'set-interaction-model without eTag', - apiFunc: smapiClient.skill.interactionModel.setInteractionModel, - parameters: [TEST_SKILL_ID, TEST_SKILL_STAGE, TEST_LOCALE, TEST_MODEL, null, noop], - expectedOptions: { - url: `${CONSTANTS.SMAPI.ENDPOINT}/v1/skills/${TEST_SKILL_ID}/stages/${TEST_SKILL_STAGE}/interactionModel/locales/${TEST_LOCALE}`, - method: CONSTANTS.HTTP_REQUEST.VERB.PUT, - headers: { - authorization: TEST_ACCESS_TOKEN - }, - body: { - interactionModel: 'model' - }, - json: true - } - }, - { - testCase: 'head-interaction-model', - apiFunc: smapiClient.skill.interactionModel.headInteractionModel, - parameters: [TEST_SKILL_ID, TEST_SKILL_STAGE, TEST_LOCALE, noop], - expectedOptions: { - url: `${CONSTANTS.SMAPI.ENDPOINT}/v1/skills/${TEST_SKILL_ID}/stages/${TEST_SKILL_STAGE}/interactionModel/locales/${TEST_LOCALE}`, - method: CONSTANTS.HTTP_REQUEST.VERB.HEAD, - headers: { - authorization: TEST_ACCESS_TOKEN - }, - body: null, - json: false - } - }, - { - testCase: 'list-interaction-model-versions', - apiFunc: smapiClient.skill.interactionModel.listInteractionModelVersions, - parameters: [TEST_SKILL_ID, TEST_SKILL_STAGE, TEST_LOCALE, { nextToken: TEST_NEXT_TOKEN, - maxResults: TEST_MAX_RESULTS, - sortDirection: TEST_SORT_DIRECTION, - sortField: TEST_SORT_FIELD }, noop], - expectedOptions: { - url: `${CONSTANTS.SMAPI.ENDPOINT}/v1/skills/${TEST_SKILL_ID}/stages/` - + `${TEST_SKILL_STAGE}/interactionModel/locales/${TEST_LOCALE}/versions?` - + `nextToken=${TEST_NEXT_TOKEN}&maxResults=${TEST_MAX_RESULTS}&sortDirection=${TEST_SORT_DIRECTION}&sortField=${TEST_SORT_FIELD}`, - method: CONSTANTS.HTTP_REQUEST.VERB.GET, - headers: { - authorization: TEST_ACCESS_TOKEN - }, - body: null, - json: false - } - }, - { - testCase: 'list-interaction-model-versions without maxResults', - apiFunc: smapiClient.skill.interactionModel.listInteractionModelVersions, - parameters: [TEST_SKILL_ID, TEST_SKILL_STAGE, TEST_LOCALE, { nextToken: TEST_NEXT_TOKEN, - sortDirection: TEST_SORT_DIRECTION, - sortField: TEST_SORT_FIELD }, noop], - expectedOptions: { - url: `${CONSTANTS.SMAPI.ENDPOINT}/v1/skills/${TEST_SKILL_ID}/stages/` - + `${TEST_SKILL_STAGE}/interactionModel/locales/${TEST_LOCALE}/versions?` - + `nextToken=${TEST_NEXT_TOKEN}&sortDirection=${TEST_SORT_DIRECTION}&sortField=${TEST_SORT_FIELD}`, - method: CONSTANTS.HTTP_REQUEST.VERB.GET, - headers: { - authorization: TEST_ACCESS_TOKEN - }, - body: null, - json: false - } - }, - { - testCase: 'list-interaction-model-versions without nextToken', - apiFunc: smapiClient.skill.interactionModel.listInteractionModelVersions, - parameters: [TEST_SKILL_ID, TEST_SKILL_STAGE, TEST_LOCALE, { maxResults: TEST_MAX_RESULTS, - sortDirection: TEST_SORT_DIRECTION, - sortField: TEST_SORT_FIELD }, noop], - expectedOptions: { - url: `${CONSTANTS.SMAPI.ENDPOINT}/v1/skills/${TEST_SKILL_ID}/stages/` - + `${TEST_SKILL_STAGE}/interactionModel/locales/${TEST_LOCALE}/versions?` - + `maxResults=${TEST_MAX_RESULTS}&sortDirection=${TEST_SORT_DIRECTION}&sortField=${TEST_SORT_FIELD}`, - method: CONSTANTS.HTTP_REQUEST.VERB.GET, - headers: { - authorization: TEST_ACCESS_TOKEN - }, - body: null, - json: false - } - }, - { - testCase: 'list-interaction-model-versions without sortDirection', - apiFunc: smapiClient.skill.interactionModel.listInteractionModelVersions, - parameters: [TEST_SKILL_ID, TEST_SKILL_STAGE, TEST_LOCALE, { nextToken: TEST_NEXT_TOKEN, - maxResults: TEST_MAX_RESULTS, - sortField: TEST_SORT_FIELD }, noop], - expectedOptions: { - url: `${CONSTANTS.SMAPI.ENDPOINT}/v1/skills/${TEST_SKILL_ID}/stages/` - + `${TEST_SKILL_STAGE}/interactionModel/locales/${TEST_LOCALE}/versions?` - + `nextToken=${TEST_NEXT_TOKEN}&maxResults=${TEST_MAX_RESULTS}&sortField=${TEST_SORT_FIELD}`, - method: CONSTANTS.HTTP_REQUEST.VERB.GET, - headers: { - authorization: TEST_ACCESS_TOKEN - }, - body: null, - json: false - } - }, - { - testCase: 'list-interaction-model-versions without sortField', - apiFunc: smapiClient.skill.interactionModel.listInteractionModelVersions, - parameters: [TEST_SKILL_ID, TEST_SKILL_STAGE, TEST_LOCALE, { nextToken: TEST_NEXT_TOKEN, - maxResults: TEST_MAX_RESULTS, - sortDirection: TEST_SORT_DIRECTION }, noop], - expectedOptions: { - url: `${CONSTANTS.SMAPI.ENDPOINT}/v1/skills/${TEST_SKILL_ID}/stages/` - + `${TEST_SKILL_STAGE}/interactionModel/locales/${TEST_LOCALE}/versions?` - + `nextToken=${TEST_NEXT_TOKEN}&maxResults=${TEST_MAX_RESULTS}&sortDirection=${TEST_SORT_DIRECTION}`, - method: CONSTANTS.HTTP_REQUEST.VERB.GET, - headers: { - authorization: TEST_ACCESS_TOKEN - }, - body: null, - json: false - } - }, - { - testCase: 'list-interaction-model-versions with null query parameters', - apiFunc: smapiClient.skill.interactionModel.listInteractionModelVersions, - parameters: [TEST_SKILL_ID, TEST_SKILL_STAGE, TEST_LOCALE, null, noop], - expectedOptions: { - url: `${CONSTANTS.SMAPI.ENDPOINT}/v1/skills/${TEST_SKILL_ID}/stages/` - + `${TEST_SKILL_STAGE}/interactionModel/locales/${TEST_LOCALE}/versions`, - method: CONSTANTS.HTTP_REQUEST.VERB.GET, - headers: { - authorization: TEST_ACCESS_TOKEN - }, - body: null, - json: false - } - }, - ].forEach(({ testCase, apiFunc, parameters, expectedOptions }) => { - it(`| call ${testCase} successfully`, (done) => { - // setup - AuthorizationController.prototype.tokenRefreshAndRead.callsArgWith(1, null, TEST_ACCESS_TOKEN); - // call - apiFunc(...parameters); - // verify - expect(AuthorizationController.prototype.tokenRefreshAndRead.called).equal(true); - expect(AuthorizationController.prototype.tokenRefreshAndRead.args[0][0]).equal(TEST_PROFILE); - expect(httpClientStub.args[0][0]).deep.equal(expectedOptions); - done(); - }); - }); + [ + { + testCase: "get-interaction-model", + apiFunc: smapiClient.skill.interactionModel.getInteractionModel, + parameters: [TEST_SKILL_ID, TEST_SKILL_STAGE, TEST_LOCALE, noop], + expectedOptions: { + url: `${CONSTANTS.SMAPI.ENDPOINT}/v1/skills/${TEST_SKILL_ID}/stages/${TEST_SKILL_STAGE}/interactionModel/locales/${TEST_LOCALE}`, + method: CONSTANTS.HTTP_REQUEST.VERB.GET, + headers: { + authorization: TEST_ACCESS_TOKEN, + }, + body: null, + json: false, + }, + }, + { + testCase: "set-interaction-model", + apiFunc: smapiClient.skill.interactionModel.setInteractionModel, + parameters: [TEST_SKILL_ID, TEST_SKILL_STAGE, TEST_LOCALE, TEST_MODEL, TEST_ETAG, noop], + expectedOptions: { + url: `${CONSTANTS.SMAPI.ENDPOINT}/v1/skills/${TEST_SKILL_ID}/stages/${TEST_SKILL_STAGE}/interactionModel/locales/${TEST_LOCALE}`, + method: CONSTANTS.HTTP_REQUEST.VERB.PUT, + headers: { + "If-Match": TEST_ETAG, + authorization: TEST_ACCESS_TOKEN, + }, + body: { + interactionModel: "model", + }, + json: true, + }, + }, + { + testCase: "set-interaction-model without eTag", + apiFunc: smapiClient.skill.interactionModel.setInteractionModel, + parameters: [TEST_SKILL_ID, TEST_SKILL_STAGE, TEST_LOCALE, TEST_MODEL, null, noop], + expectedOptions: { + url: `${CONSTANTS.SMAPI.ENDPOINT}/v1/skills/${TEST_SKILL_ID}/stages/${TEST_SKILL_STAGE}/interactionModel/locales/${TEST_LOCALE}`, + method: CONSTANTS.HTTP_REQUEST.VERB.PUT, + headers: { + authorization: TEST_ACCESS_TOKEN, + }, + body: { + interactionModel: "model", + }, + json: true, + }, + }, + { + testCase: "head-interaction-model", + apiFunc: smapiClient.skill.interactionModel.headInteractionModel, + parameters: [TEST_SKILL_ID, TEST_SKILL_STAGE, TEST_LOCALE, noop], + expectedOptions: { + url: `${CONSTANTS.SMAPI.ENDPOINT}/v1/skills/${TEST_SKILL_ID}/stages/${TEST_SKILL_STAGE}/interactionModel/locales/${TEST_LOCALE}`, + method: CONSTANTS.HTTP_REQUEST.VERB.HEAD, + headers: { + authorization: TEST_ACCESS_TOKEN, + }, + body: null, + json: false, + }, + }, + { + testCase: "list-interaction-model-versions", + apiFunc: smapiClient.skill.interactionModel.listInteractionModelVersions, + parameters: [ + TEST_SKILL_ID, + TEST_SKILL_STAGE, + TEST_LOCALE, + {nextToken: TEST_NEXT_TOKEN, maxResults: TEST_MAX_RESULTS, sortDirection: TEST_SORT_DIRECTION, sortField: TEST_SORT_FIELD}, + noop, + ], + expectedOptions: { + url: + `${CONSTANTS.SMAPI.ENDPOINT}/v1/skills/${TEST_SKILL_ID}/stages/` + + `${TEST_SKILL_STAGE}/interactionModel/locales/${TEST_LOCALE}/versions?` + + `nextToken=${TEST_NEXT_TOKEN}&maxResults=${TEST_MAX_RESULTS}&sortDirection=${TEST_SORT_DIRECTION}&sortField=${TEST_SORT_FIELD}`, + method: CONSTANTS.HTTP_REQUEST.VERB.GET, + headers: { + authorization: TEST_ACCESS_TOKEN, + }, + body: null, + json: false, + }, + }, + { + testCase: "list-interaction-model-versions without maxResults", + apiFunc: smapiClient.skill.interactionModel.listInteractionModelVersions, + parameters: [ + TEST_SKILL_ID, + TEST_SKILL_STAGE, + TEST_LOCALE, + {nextToken: TEST_NEXT_TOKEN, sortDirection: TEST_SORT_DIRECTION, sortField: TEST_SORT_FIELD}, + noop, + ], + expectedOptions: { + url: + `${CONSTANTS.SMAPI.ENDPOINT}/v1/skills/${TEST_SKILL_ID}/stages/` + + `${TEST_SKILL_STAGE}/interactionModel/locales/${TEST_LOCALE}/versions?` + + `nextToken=${TEST_NEXT_TOKEN}&sortDirection=${TEST_SORT_DIRECTION}&sortField=${TEST_SORT_FIELD}`, + method: CONSTANTS.HTTP_REQUEST.VERB.GET, + headers: { + authorization: TEST_ACCESS_TOKEN, + }, + body: null, + json: false, + }, + }, + { + testCase: "list-interaction-model-versions without nextToken", + apiFunc: smapiClient.skill.interactionModel.listInteractionModelVersions, + parameters: [ + TEST_SKILL_ID, + TEST_SKILL_STAGE, + TEST_LOCALE, + {maxResults: TEST_MAX_RESULTS, sortDirection: TEST_SORT_DIRECTION, sortField: TEST_SORT_FIELD}, + noop, + ], + expectedOptions: { + url: + `${CONSTANTS.SMAPI.ENDPOINT}/v1/skills/${TEST_SKILL_ID}/stages/` + + `${TEST_SKILL_STAGE}/interactionModel/locales/${TEST_LOCALE}/versions?` + + `maxResults=${TEST_MAX_RESULTS}&sortDirection=${TEST_SORT_DIRECTION}&sortField=${TEST_SORT_FIELD}`, + method: CONSTANTS.HTTP_REQUEST.VERB.GET, + headers: { + authorization: TEST_ACCESS_TOKEN, + }, + body: null, + json: false, + }, + }, + { + testCase: "list-interaction-model-versions without sortDirection", + apiFunc: smapiClient.skill.interactionModel.listInteractionModelVersions, + parameters: [ + TEST_SKILL_ID, + TEST_SKILL_STAGE, + TEST_LOCALE, + {nextToken: TEST_NEXT_TOKEN, maxResults: TEST_MAX_RESULTS, sortField: TEST_SORT_FIELD}, + noop, + ], + expectedOptions: { + url: + `${CONSTANTS.SMAPI.ENDPOINT}/v1/skills/${TEST_SKILL_ID}/stages/` + + `${TEST_SKILL_STAGE}/interactionModel/locales/${TEST_LOCALE}/versions?` + + `nextToken=${TEST_NEXT_TOKEN}&maxResults=${TEST_MAX_RESULTS}&sortField=${TEST_SORT_FIELD}`, + method: CONSTANTS.HTTP_REQUEST.VERB.GET, + headers: { + authorization: TEST_ACCESS_TOKEN, + }, + body: null, + json: false, + }, + }, + { + testCase: "list-interaction-model-versions without sortField", + apiFunc: smapiClient.skill.interactionModel.listInteractionModelVersions, + parameters: [ + TEST_SKILL_ID, + TEST_SKILL_STAGE, + TEST_LOCALE, + {nextToken: TEST_NEXT_TOKEN, maxResults: TEST_MAX_RESULTS, sortDirection: TEST_SORT_DIRECTION}, + noop, + ], + expectedOptions: { + url: + `${CONSTANTS.SMAPI.ENDPOINT}/v1/skills/${TEST_SKILL_ID}/stages/` + + `${TEST_SKILL_STAGE}/interactionModel/locales/${TEST_LOCALE}/versions?` + + `nextToken=${TEST_NEXT_TOKEN}&maxResults=${TEST_MAX_RESULTS}&sortDirection=${TEST_SORT_DIRECTION}`, + method: CONSTANTS.HTTP_REQUEST.VERB.GET, + headers: { + authorization: TEST_ACCESS_TOKEN, + }, + body: null, + json: false, + }, + }, + { + testCase: "list-interaction-model-versions with null query parameters", + apiFunc: smapiClient.skill.interactionModel.listInteractionModelVersions, + parameters: [TEST_SKILL_ID, TEST_SKILL_STAGE, TEST_LOCALE, null, noop], + expectedOptions: { + url: + `${CONSTANTS.SMAPI.ENDPOINT}/v1/skills/${TEST_SKILL_ID}/stages/` + + `${TEST_SKILL_STAGE}/interactionModel/locales/${TEST_LOCALE}/versions`, + method: CONSTANTS.HTTP_REQUEST.VERB.GET, + headers: { + authorization: TEST_ACCESS_TOKEN, + }, + body: null, + json: false, + }, + }, + ].forEach(({testCase, apiFunc, parameters, expectedOptions}) => { + it(`| call ${testCase} successfully`, (done) => { + // setup + AuthorizationController.prototype.tokenRefreshAndRead.callsArgWith(1, null, TEST_ACCESS_TOKEN); + // call + apiFunc(...parameters); + // verify + expect(AuthorizationController.prototype.tokenRefreshAndRead.called).equal(true); + expect(AuthorizationController.prototype.tokenRefreshAndRead.args[0][0]).equal(TEST_PROFILE); + expect(httpClientStub.args[0][0]).deep.equal(expectedOptions); + done(); + }); + }); - afterEach(() => { - sinon.restore(); - }); + afterEach(() => { + sinon.restore(); }); + }); }; diff --git a/test/unit/clients/smapi-client-test/resources/isp.js b/test/unit/clients/smapi-client-test/resources/isp.js index 43e14177..2c5ea4ce 100644 --- a/test/unit/clients/smapi-client-test/resources/isp.js +++ b/test/unit/clients/smapi-client-test/resources/isp.js @@ -1,335 +1,368 @@ -const { expect } = require('chai'); -const sinon = require('sinon'); +const {expect} = require("chai"); +const sinon = require("sinon"); -const httpClient = require('@src/clients/http-client'); -const AuthorizationController = require('@src/controllers/authorization-controller'); -const CONSTANTS = require('@src/utils/constants'); +const httpClient = require("../../../../../lib/clients/http-client"); +const AuthorizationController = require("../../../../../lib/controllers/authorization-controller"); +const CONSTANTS = require("../../../../../lib/utils/constants"); const noop = () => {}; module.exports = (smapiClient) => { - describe('# smapi client isp APIs', () => { - let httpClientStub; - beforeEach(() => { - httpClientStub = sinon.stub(httpClient, 'request').callsFake(noop); - sinon.stub(AuthorizationController.prototype, 'tokenRefreshAndRead'); - }); + describe("# smapi client isp APIs", () => { + let httpClientStub; + beforeEach(() => { + httpClientStub = sinon.stub(httpClient, "request").callsFake(noop); + sinon.stub(AuthorizationController.prototype, "tokenRefreshAndRead"); + }); - const TEST_SKILL_ID = 'skillId'; - const TEST_ISP_STAGE = 'ispStage'; - const TEST_ISP_DEFINITION = 'ispDefinition'; - const TEST_ISP_ID = 'ispId'; - const TEST_ISP_ETAG = 'ispETag'; - const TEST_VENDOR_ID = 'vendorId'; - const TEST_PRODUCT_ID_LIST = ['id1', 'id2']; - const TEST_ISP_REFERENCE_NAME = 'ispReferenceName'; - const TEST_ISP_TYPE = 'ispType'; - const TEST_ISP_STATUS = 'ispStatus'; - const TEST_NEXT_TOKEN = 'nextToken'; - const TEST_MAX_RESULTS = 'maxResults'; - const TEST_PROFILE = 'testProfile'; - const TEST_ACCESS_TOKEN = 'access_token'; + const TEST_SKILL_ID = "skillId"; + const TEST_ISP_STAGE = "ispStage"; + const TEST_ISP_DEFINITION = "ispDefinition"; + const TEST_ISP_ID = "ispId"; + const TEST_ISP_ETAG = "ispETag"; + const TEST_VENDOR_ID = "vendorId"; + const TEST_PRODUCT_ID_LIST = ["id1", "id2"]; + const TEST_ISP_REFERENCE_NAME = "ispReferenceName"; + const TEST_ISP_TYPE = "ispType"; + const TEST_ISP_STATUS = "ispStatus"; + const TEST_NEXT_TOKEN = "nextToken"; + const TEST_MAX_RESULTS = "maxResults"; + const TEST_PROFILE = "testProfile"; + const TEST_ACCESS_TOKEN = "access_token"; - [ - { - testCase: 'create-isp', - apiFunc: smapiClient.isp.createIsp, - parameters: [TEST_VENDOR_ID, TEST_ISP_DEFINITION, noop], - expectedOptions: { - url: `${CONSTANTS.SMAPI.ENDPOINT}/v1/inSkillProducts/`, - method: CONSTANTS.HTTP_REQUEST.VERB.POST, - headers: { - authorization: TEST_ACCESS_TOKEN - }, - body: { - vendorId: TEST_VENDOR_ID, - inSkillProductDefinition: TEST_ISP_DEFINITION - }, - json: true - } - }, - { - testCase: 'get-isp', - apiFunc: smapiClient.isp.getIsp, - parameters: [TEST_ISP_ID, TEST_ISP_STAGE, noop], - expectedOptions: { - url: `${CONSTANTS.SMAPI.ENDPOINT}/v1/inSkillProducts/${TEST_ISP_ID}/stages/${TEST_ISP_STAGE}`, - method: CONSTANTS.HTTP_REQUEST.VERB.GET, - headers: { - authorization: TEST_ACCESS_TOKEN - }, - body: null, - json: false - } - }, - { - testCase: 'get-isp with summary mode', - apiFunc: smapiClient.isp.getIspSummary, - parameters: [TEST_ISP_ID, TEST_ISP_STAGE, noop], - expectedOptions: { - url: `${CONSTANTS.SMAPI.ENDPOINT}/v1/inSkillProducts/${TEST_ISP_ID}/stages/${TEST_ISP_STAGE}/summary`, - method: CONSTANTS.HTTP_REQUEST.VERB.GET, - headers: { - authorization: TEST_ACCESS_TOKEN - }, - body: null, - json: false - } - }, - { - testCase: 'update-isp', - apiFunc: smapiClient.isp.updateIsp, - parameters: [TEST_ISP_ID, TEST_ISP_STAGE, TEST_ISP_DEFINITION, TEST_ISP_ETAG, noop], - expectedOptions: { - url: `${CONSTANTS.SMAPI.ENDPOINT}/v1/inSkillProducts/${TEST_ISP_ID}/stages/${TEST_ISP_STAGE}`, - method: CONSTANTS.HTTP_REQUEST.VERB.PUT, - headers: { - 'If-Match': TEST_ISP_ETAG, - authorization: TEST_ACCESS_TOKEN - }, - body: { inSkillProductDefinition: TEST_ISP_DEFINITION }, - json: true - } - }, - { - testCase: 'update-isp without eTag', - apiFunc: smapiClient.isp.updateIsp, - parameters: [TEST_ISP_ID, TEST_ISP_STAGE, TEST_ISP_DEFINITION, null, noop], - expectedOptions: { - url: `${CONSTANTS.SMAPI.ENDPOINT}/v1/inSkillProducts/${TEST_ISP_ID}/stages/${TEST_ISP_STAGE}`, - method: CONSTANTS.HTTP_REQUEST.VERB.PUT, - headers: { - authorization: TEST_ACCESS_TOKEN - }, - body: { inSkillProductDefinition: TEST_ISP_DEFINITION }, - json: true - } - }, - { - testCase: 'associate-isp', - apiFunc: smapiClient.isp.associateIsp, - parameters: [TEST_ISP_ID, TEST_SKILL_ID, noop], - expectedOptions: { - url: `${CONSTANTS.SMAPI.ENDPOINT}/v1/inSkillProducts/${TEST_ISP_ID}/skills/${TEST_SKILL_ID}`, - method: CONSTANTS.HTTP_REQUEST.VERB.PUT, - headers: { - authorization: TEST_ACCESS_TOKEN - }, - body: null, - json: false - } - }, - { - testCase: 'list-isp-for-skill', - apiFunc: smapiClient.isp.listIspForSkill, - parameters: [TEST_SKILL_ID, TEST_ISP_STAGE, { nextToken: TEST_NEXT_TOKEN, maxResults: TEST_MAX_RESULTS }, noop], - expectedOptions: { - url: `${CONSTANTS.SMAPI.ENDPOINT}/v1/skills/${TEST_SKILL_ID}/stages/${TEST_ISP_STAGE}/inSkillProducts?` - + `nextToken=${TEST_NEXT_TOKEN}&maxResults=${TEST_MAX_RESULTS}`, - method: CONSTANTS.HTTP_REQUEST.VERB.GET, - headers: { - authorization: TEST_ACCESS_TOKEN - }, - body: null, - json: false - } - }, - { - testCase: 'list-isp-for-vendor', - apiFunc: smapiClient.isp.listIspForVendor, - parameters: [TEST_VENDOR_ID, TEST_PRODUCT_ID_LIST, TEST_ISP_STAGE, TEST_ISP_REFERENCE_NAME, TEST_ISP_STATUS, TEST_ISP_TYPE, 'true', - { nextToken: TEST_NEXT_TOKEN, maxResults: TEST_MAX_RESULTS }, noop], - expectedOptions: { - url: `${CONSTANTS.SMAPI.ENDPOINT}/v1/inSkillProducts?nextToken=${TEST_NEXT_TOKEN}&maxResults=${TEST_MAX_RESULTS}` - + `&productId=id1&productId=id2&vendorId=${TEST_VENDOR_ID}&referenceName=${TEST_ISP_REFERENCE_NAME}` - + `&type=${TEST_ISP_TYPE}&stage=${TEST_ISP_STAGE}&status=${TEST_ISP_STATUS}&isAssociatedWithSkill=true`, - method: CONSTANTS.HTTP_REQUEST.VERB.GET, - headers: { - authorization: TEST_ACCESS_TOKEN - }, - body: null, - json: false - } - }, - { - testCase: 'list-isp-for-vendor with empty isp list', - apiFunc: smapiClient.isp.listIspForVendor, - parameters: [TEST_VENDOR_ID, [], TEST_ISP_STAGE, TEST_ISP_REFERENCE_NAME, TEST_ISP_STATUS, TEST_ISP_TYPE, 'true', - { nextToken: TEST_NEXT_TOKEN, maxResults: TEST_MAX_RESULTS }, noop], - expectedOptions: { - url: `${CONSTANTS.SMAPI.ENDPOINT}/v1/inSkillProducts?nextToken=${TEST_NEXT_TOKEN}&maxResults=${TEST_MAX_RESULTS}` - + `&vendorId=${TEST_VENDOR_ID}&referenceName=${TEST_ISP_REFERENCE_NAME}&type=${TEST_ISP_TYPE}` - + `&stage=${TEST_ISP_STAGE}&status=${TEST_ISP_STATUS}&isAssociatedWithSkill=true`, - method: CONSTANTS.HTTP_REQUEST.VERB.GET, - headers: { - authorization: TEST_ACCESS_TOKEN - }, - body: null, - json: false - } - }, - { - testCase: 'list-isp-for-vendor with null querry', - apiFunc: smapiClient.isp.listIspForVendor, - parameters: [TEST_VENDOR_ID, TEST_PRODUCT_ID_LIST, TEST_ISP_STAGE, TEST_ISP_REFERENCE_NAME, TEST_ISP_STATUS, TEST_ISP_TYPE, 'true', - null, noop], - expectedOptions: { - url: `${CONSTANTS.SMAPI.ENDPOINT}/v1/inSkillProducts?productId=id1&productId=id2&vendorId=${TEST_VENDOR_ID}` - + `&referenceName=${TEST_ISP_REFERENCE_NAME}&type=${TEST_ISP_TYPE}&stage=${TEST_ISP_STAGE}` - + `&status=${TEST_ISP_STATUS}&isAssociatedWithSkill=true`, - method: CONSTANTS.HTTP_REQUEST.VERB.GET, - headers: { - authorization: TEST_ACCESS_TOKEN - }, - body: null, - json: false - } - }, - { - testCase: 'list-isp-for-vendor with all option value equal to null', - apiFunc: smapiClient.isp.listIspForVendor, - parameters: [TEST_VENDOR_ID, null, null, null, null, null, null, null, noop], - expectedOptions: { - url: `${CONSTANTS.SMAPI.ENDPOINT}/v1/inSkillProducts?vendorId=${TEST_VENDOR_ID}`, - method: CONSTANTS.HTTP_REQUEST.VERB.GET, - headers: { - authorization: TEST_ACCESS_TOKEN - }, - body: null, - json: false - } - }, - { - testCase: 'list-skills-for-isp', - apiFunc: smapiClient.isp.listSkillsForIsp, - parameters: [TEST_ISP_ID, TEST_ISP_STAGE, { nextToken: TEST_NEXT_TOKEN, maxResults: TEST_MAX_RESULTS }, noop], - expectedOptions: { - url: `${CONSTANTS.SMAPI.ENDPOINT}/v1/inSkillProducts/${TEST_ISP_ID}/stages/${TEST_ISP_STAGE}/skills?` - + `nextToken=${TEST_NEXT_TOKEN}&maxResults=${TEST_MAX_RESULTS}`, - method: CONSTANTS.HTTP_REQUEST.VERB.GET, - headers: { - authorization: TEST_ACCESS_TOKEN - }, - body: null, - json: false - } - }, - { - testCase: 'list-skills-for-isp without next token', - apiFunc: smapiClient.isp.listSkillsForIsp, - parameters: [TEST_ISP_ID, TEST_ISP_STAGE, { maxResults: TEST_MAX_RESULTS }, noop], - expectedOptions: { - url: `${CONSTANTS.SMAPI.ENDPOINT}/v1/inSkillProducts/${TEST_ISP_ID}/stages/${TEST_ISP_STAGE}/skills?` - + `maxResults=${TEST_MAX_RESULTS}`, - method: CONSTANTS.HTTP_REQUEST.VERB.GET, - headers: { - authorization: TEST_ACCESS_TOKEN - }, - body: null, - json: false - } - }, - { - testCase: 'list-skills-for-isp without max results', - apiFunc: smapiClient.isp.listSkillsForIsp, - parameters: [TEST_ISP_ID, TEST_ISP_STAGE, { nextToken: TEST_NEXT_TOKEN }, noop], - expectedOptions: { - url: `${CONSTANTS.SMAPI.ENDPOINT}/v1/inSkillProducts/${TEST_ISP_ID}/stages/${TEST_ISP_STAGE}/skills?nextToken=${TEST_NEXT_TOKEN}`, - method: CONSTANTS.HTTP_REQUEST.VERB.GET, - headers: { - authorization: TEST_ACCESS_TOKEN - }, - body: null, - json: false - } - }, - { - testCase: 'list-skills-for-isp without max results nor next token', - apiFunc: smapiClient.isp.listSkillsForIsp, - parameters: [TEST_ISP_ID, TEST_ISP_STAGE, {}, noop], - expectedOptions: { - url: `${CONSTANTS.SMAPI.ENDPOINT}/v1/inSkillProducts/${TEST_ISP_ID}/stages/${TEST_ISP_STAGE}/skills`, - method: CONSTANTS.HTTP_REQUEST.VERB.GET, - headers: { - authorization: TEST_ACCESS_TOKEN - }, - body: null, - json: false - } - }, - { - testCase: 'disassociate-isp', - apiFunc: smapiClient.isp.disassociateIsp, - parameters: [TEST_ISP_ID, TEST_SKILL_ID, noop], - expectedOptions: { - url: `${CONSTANTS.SMAPI.ENDPOINT}/v1/inSkillProducts/${TEST_ISP_ID}/skills/${TEST_SKILL_ID}`, - method: CONSTANTS.HTTP_REQUEST.VERB.DELETE, - headers: { - authorization: TEST_ACCESS_TOKEN - }, - body: null, - json: false - } - }, - { - testCase: 'delete-isp', - apiFunc: smapiClient.isp.deleteIsp, - parameters: [TEST_ISP_ID, TEST_ISP_STAGE, TEST_ISP_ETAG, noop], - expectedOptions: { - url: `${CONSTANTS.SMAPI.ENDPOINT}/v1/inSkillProducts/${TEST_ISP_ID}/stages/${TEST_ISP_STAGE}`, - method: CONSTANTS.HTTP_REQUEST.VERB.DELETE, - headers: { - 'If-Match': TEST_ISP_ETAG, - authorization: TEST_ACCESS_TOKEN - }, - body: null, - json: false - } - }, - { - testCase: 'delete-isp without eTag', - apiFunc: smapiClient.isp.deleteIsp, - parameters: [TEST_ISP_ID, TEST_ISP_STAGE, null, noop], - expectedOptions: { - url: `${CONSTANTS.SMAPI.ENDPOINT}/v1/inSkillProducts/${TEST_ISP_ID}/stages/${TEST_ISP_STAGE}`, - method: CONSTANTS.HTTP_REQUEST.VERB.DELETE, - headers: { - authorization: TEST_ACCESS_TOKEN - }, - body: null, - json: false - } - }, - { - testCase: 'reset-isp-entitlement', - apiFunc: smapiClient.isp.resetIspEntitlement, - parameters: [TEST_ISP_ID, TEST_ISP_STAGE, noop], - expectedOptions: { - url: `${CONSTANTS.SMAPI.ENDPOINT}/v1/inSkillProducts/${TEST_ISP_ID}/stages/${TEST_ISP_STAGE}/entitlement`, - method: CONSTANTS.HTTP_REQUEST.VERB.DELETE, - headers: { - authorization: TEST_ACCESS_TOKEN - }, - body: null, - json: false - } - }, - ].forEach(({ testCase, apiFunc, parameters, expectedOptions }) => { - it(`| call ${testCase} successfully`, (done) => { - // setup - AuthorizationController.prototype.tokenRefreshAndRead.callsArgWith(1, null, TEST_ACCESS_TOKEN); - // call - apiFunc(...parameters); - // verify - expect(AuthorizationController.prototype.tokenRefreshAndRead.called).equal(true); - expect(AuthorizationController.prototype.tokenRefreshAndRead.args[0][0]).equal(TEST_PROFILE); - expect(httpClientStub.args[0][0]).deep.equal(expectedOptions); - done(); - }); - }); + [ + { + testCase: "create-isp", + apiFunc: smapiClient.isp.createIsp, + parameters: [TEST_VENDOR_ID, TEST_ISP_DEFINITION, noop], + expectedOptions: { + url: `${CONSTANTS.SMAPI.ENDPOINT}/v1/inSkillProducts/`, + method: CONSTANTS.HTTP_REQUEST.VERB.POST, + headers: { + authorization: TEST_ACCESS_TOKEN, + }, + body: { + vendorId: TEST_VENDOR_ID, + inSkillProductDefinition: TEST_ISP_DEFINITION, + }, + json: true, + }, + }, + { + testCase: "get-isp", + apiFunc: smapiClient.isp.getIsp, + parameters: [TEST_ISP_ID, TEST_ISP_STAGE, noop], + expectedOptions: { + url: `${CONSTANTS.SMAPI.ENDPOINT}/v1/inSkillProducts/${TEST_ISP_ID}/stages/${TEST_ISP_STAGE}`, + method: CONSTANTS.HTTP_REQUEST.VERB.GET, + headers: { + authorization: TEST_ACCESS_TOKEN, + }, + body: null, + json: false, + }, + }, + { + testCase: "get-isp with summary mode", + apiFunc: smapiClient.isp.getIspSummary, + parameters: [TEST_ISP_ID, TEST_ISP_STAGE, noop], + expectedOptions: { + url: `${CONSTANTS.SMAPI.ENDPOINT}/v1/inSkillProducts/${TEST_ISP_ID}/stages/${TEST_ISP_STAGE}/summary`, + method: CONSTANTS.HTTP_REQUEST.VERB.GET, + headers: { + authorization: TEST_ACCESS_TOKEN, + }, + body: null, + json: false, + }, + }, + { + testCase: "update-isp", + apiFunc: smapiClient.isp.updateIsp, + parameters: [TEST_ISP_ID, TEST_ISP_STAGE, TEST_ISP_DEFINITION, TEST_ISP_ETAG, noop], + expectedOptions: { + url: `${CONSTANTS.SMAPI.ENDPOINT}/v1/inSkillProducts/${TEST_ISP_ID}/stages/${TEST_ISP_STAGE}`, + method: CONSTANTS.HTTP_REQUEST.VERB.PUT, + headers: { + "If-Match": TEST_ISP_ETAG, + authorization: TEST_ACCESS_TOKEN, + }, + body: {inSkillProductDefinition: TEST_ISP_DEFINITION}, + json: true, + }, + }, + { + testCase: "update-isp without eTag", + apiFunc: smapiClient.isp.updateIsp, + parameters: [TEST_ISP_ID, TEST_ISP_STAGE, TEST_ISP_DEFINITION, null, noop], + expectedOptions: { + url: `${CONSTANTS.SMAPI.ENDPOINT}/v1/inSkillProducts/${TEST_ISP_ID}/stages/${TEST_ISP_STAGE}`, + method: CONSTANTS.HTTP_REQUEST.VERB.PUT, + headers: { + authorization: TEST_ACCESS_TOKEN, + }, + body: {inSkillProductDefinition: TEST_ISP_DEFINITION}, + json: true, + }, + }, + { + testCase: "associate-isp", + apiFunc: smapiClient.isp.associateIsp, + parameters: [TEST_ISP_ID, TEST_SKILL_ID, noop], + expectedOptions: { + url: `${CONSTANTS.SMAPI.ENDPOINT}/v1/inSkillProducts/${TEST_ISP_ID}/skills/${TEST_SKILL_ID}`, + method: CONSTANTS.HTTP_REQUEST.VERB.PUT, + headers: { + authorization: TEST_ACCESS_TOKEN, + }, + body: null, + json: false, + }, + }, + { + testCase: "list-isp-for-skill", + apiFunc: smapiClient.isp.listIspForSkill, + parameters: [TEST_SKILL_ID, TEST_ISP_STAGE, {nextToken: TEST_NEXT_TOKEN, maxResults: TEST_MAX_RESULTS}, noop], + expectedOptions: { + url: + `${CONSTANTS.SMAPI.ENDPOINT}/v1/skills/${TEST_SKILL_ID}/stages/${TEST_ISP_STAGE}/inSkillProducts?` + + `nextToken=${TEST_NEXT_TOKEN}&maxResults=${TEST_MAX_RESULTS}`, + method: CONSTANTS.HTTP_REQUEST.VERB.GET, + headers: { + authorization: TEST_ACCESS_TOKEN, + }, + body: null, + json: false, + }, + }, + { + testCase: "list-isp-for-vendor", + apiFunc: smapiClient.isp.listIspForVendor, + parameters: [ + TEST_VENDOR_ID, + TEST_PRODUCT_ID_LIST, + TEST_ISP_STAGE, + TEST_ISP_REFERENCE_NAME, + TEST_ISP_STATUS, + TEST_ISP_TYPE, + "true", + {nextToken: TEST_NEXT_TOKEN, maxResults: TEST_MAX_RESULTS}, + noop, + ], + expectedOptions: { + url: + `${CONSTANTS.SMAPI.ENDPOINT}/v1/inSkillProducts?nextToken=${TEST_NEXT_TOKEN}&maxResults=${TEST_MAX_RESULTS}` + + `&productId=id1&productId=id2&vendorId=${TEST_VENDOR_ID}&referenceName=${TEST_ISP_REFERENCE_NAME}` + + `&type=${TEST_ISP_TYPE}&stage=${TEST_ISP_STAGE}&status=${TEST_ISP_STATUS}&isAssociatedWithSkill=true`, + method: CONSTANTS.HTTP_REQUEST.VERB.GET, + headers: { + authorization: TEST_ACCESS_TOKEN, + }, + body: null, + json: false, + }, + }, + { + testCase: "list-isp-for-vendor with empty isp list", + apiFunc: smapiClient.isp.listIspForVendor, + parameters: [ + TEST_VENDOR_ID, + [], + TEST_ISP_STAGE, + TEST_ISP_REFERENCE_NAME, + TEST_ISP_STATUS, + TEST_ISP_TYPE, + "true", + {nextToken: TEST_NEXT_TOKEN, maxResults: TEST_MAX_RESULTS}, + noop, + ], + expectedOptions: { + url: + `${CONSTANTS.SMAPI.ENDPOINT}/v1/inSkillProducts?nextToken=${TEST_NEXT_TOKEN}&maxResults=${TEST_MAX_RESULTS}` + + `&vendorId=${TEST_VENDOR_ID}&referenceName=${TEST_ISP_REFERENCE_NAME}&type=${TEST_ISP_TYPE}` + + `&stage=${TEST_ISP_STAGE}&status=${TEST_ISP_STATUS}&isAssociatedWithSkill=true`, + method: CONSTANTS.HTTP_REQUEST.VERB.GET, + headers: { + authorization: TEST_ACCESS_TOKEN, + }, + body: null, + json: false, + }, + }, + { + testCase: "list-isp-for-vendor with null querry", + apiFunc: smapiClient.isp.listIspForVendor, + parameters: [ + TEST_VENDOR_ID, + TEST_PRODUCT_ID_LIST, + TEST_ISP_STAGE, + TEST_ISP_REFERENCE_NAME, + TEST_ISP_STATUS, + TEST_ISP_TYPE, + "true", + null, + noop, + ], + expectedOptions: { + url: + `${CONSTANTS.SMAPI.ENDPOINT}/v1/inSkillProducts?productId=id1&productId=id2&vendorId=${TEST_VENDOR_ID}` + + `&referenceName=${TEST_ISP_REFERENCE_NAME}&type=${TEST_ISP_TYPE}&stage=${TEST_ISP_STAGE}` + + `&status=${TEST_ISP_STATUS}&isAssociatedWithSkill=true`, + method: CONSTANTS.HTTP_REQUEST.VERB.GET, + headers: { + authorization: TEST_ACCESS_TOKEN, + }, + body: null, + json: false, + }, + }, + { + testCase: "list-isp-for-vendor with all option value equal to null", + apiFunc: smapiClient.isp.listIspForVendor, + parameters: [TEST_VENDOR_ID, null, null, null, null, null, null, null, noop], + expectedOptions: { + url: `${CONSTANTS.SMAPI.ENDPOINT}/v1/inSkillProducts?vendorId=${TEST_VENDOR_ID}`, + method: CONSTANTS.HTTP_REQUEST.VERB.GET, + headers: { + authorization: TEST_ACCESS_TOKEN, + }, + body: null, + json: false, + }, + }, + { + testCase: "list-skills-for-isp", + apiFunc: smapiClient.isp.listSkillsForIsp, + parameters: [TEST_ISP_ID, TEST_ISP_STAGE, {nextToken: TEST_NEXT_TOKEN, maxResults: TEST_MAX_RESULTS}, noop], + expectedOptions: { + url: + `${CONSTANTS.SMAPI.ENDPOINT}/v1/inSkillProducts/${TEST_ISP_ID}/stages/${TEST_ISP_STAGE}/skills?` + + `nextToken=${TEST_NEXT_TOKEN}&maxResults=${TEST_MAX_RESULTS}`, + method: CONSTANTS.HTTP_REQUEST.VERB.GET, + headers: { + authorization: TEST_ACCESS_TOKEN, + }, + body: null, + json: false, + }, + }, + { + testCase: "list-skills-for-isp without next token", + apiFunc: smapiClient.isp.listSkillsForIsp, + parameters: [TEST_ISP_ID, TEST_ISP_STAGE, {maxResults: TEST_MAX_RESULTS}, noop], + expectedOptions: { + url: + `${CONSTANTS.SMAPI.ENDPOINT}/v1/inSkillProducts/${TEST_ISP_ID}/stages/${TEST_ISP_STAGE}/skills?` + + `maxResults=${TEST_MAX_RESULTS}`, + method: CONSTANTS.HTTP_REQUEST.VERB.GET, + headers: { + authorization: TEST_ACCESS_TOKEN, + }, + body: null, + json: false, + }, + }, + { + testCase: "list-skills-for-isp without max results", + apiFunc: smapiClient.isp.listSkillsForIsp, + parameters: [TEST_ISP_ID, TEST_ISP_STAGE, {nextToken: TEST_NEXT_TOKEN}, noop], + expectedOptions: { + url: `${CONSTANTS.SMAPI.ENDPOINT}/v1/inSkillProducts/${TEST_ISP_ID}/stages/${TEST_ISP_STAGE}/skills?nextToken=${TEST_NEXT_TOKEN}`, + method: CONSTANTS.HTTP_REQUEST.VERB.GET, + headers: { + authorization: TEST_ACCESS_TOKEN, + }, + body: null, + json: false, + }, + }, + { + testCase: "list-skills-for-isp without max results nor next token", + apiFunc: smapiClient.isp.listSkillsForIsp, + parameters: [TEST_ISP_ID, TEST_ISP_STAGE, {}, noop], + expectedOptions: { + url: `${CONSTANTS.SMAPI.ENDPOINT}/v1/inSkillProducts/${TEST_ISP_ID}/stages/${TEST_ISP_STAGE}/skills`, + method: CONSTANTS.HTTP_REQUEST.VERB.GET, + headers: { + authorization: TEST_ACCESS_TOKEN, + }, + body: null, + json: false, + }, + }, + { + testCase: "disassociate-isp", + apiFunc: smapiClient.isp.disassociateIsp, + parameters: [TEST_ISP_ID, TEST_SKILL_ID, noop], + expectedOptions: { + url: `${CONSTANTS.SMAPI.ENDPOINT}/v1/inSkillProducts/${TEST_ISP_ID}/skills/${TEST_SKILL_ID}`, + method: CONSTANTS.HTTP_REQUEST.VERB.DELETE, + headers: { + authorization: TEST_ACCESS_TOKEN, + }, + body: null, + json: false, + }, + }, + { + testCase: "delete-isp", + apiFunc: smapiClient.isp.deleteIsp, + parameters: [TEST_ISP_ID, TEST_ISP_STAGE, TEST_ISP_ETAG, noop], + expectedOptions: { + url: `${CONSTANTS.SMAPI.ENDPOINT}/v1/inSkillProducts/${TEST_ISP_ID}/stages/${TEST_ISP_STAGE}`, + method: CONSTANTS.HTTP_REQUEST.VERB.DELETE, + headers: { + "If-Match": TEST_ISP_ETAG, + authorization: TEST_ACCESS_TOKEN, + }, + body: null, + json: false, + }, + }, + { + testCase: "delete-isp without eTag", + apiFunc: smapiClient.isp.deleteIsp, + parameters: [TEST_ISP_ID, TEST_ISP_STAGE, null, noop], + expectedOptions: { + url: `${CONSTANTS.SMAPI.ENDPOINT}/v1/inSkillProducts/${TEST_ISP_ID}/stages/${TEST_ISP_STAGE}`, + method: CONSTANTS.HTTP_REQUEST.VERB.DELETE, + headers: { + authorization: TEST_ACCESS_TOKEN, + }, + body: null, + json: false, + }, + }, + { + testCase: "reset-isp-entitlement", + apiFunc: smapiClient.isp.resetIspEntitlement, + parameters: [TEST_ISP_ID, TEST_ISP_STAGE, noop], + expectedOptions: { + url: `${CONSTANTS.SMAPI.ENDPOINT}/v1/inSkillProducts/${TEST_ISP_ID}/stages/${TEST_ISP_STAGE}/entitlement`, + method: CONSTANTS.HTTP_REQUEST.VERB.DELETE, + headers: { + authorization: TEST_ACCESS_TOKEN, + }, + body: null, + json: false, + }, + }, + ].forEach(({testCase, apiFunc, parameters, expectedOptions}) => { + it(`| call ${testCase} successfully`, (done) => { + // setup + AuthorizationController.prototype.tokenRefreshAndRead.callsArgWith(1, null, TEST_ACCESS_TOKEN); + // call + apiFunc(...parameters); + // verify + expect(AuthorizationController.prototype.tokenRefreshAndRead.called).equal(true); + expect(AuthorizationController.prototype.tokenRefreshAndRead.args[0][0]).equal(TEST_PROFILE); + expect(httpClientStub.args[0][0]).deep.equal(expectedOptions); + done(); + }); + }); - afterEach(() => { - sinon.restore(); - }); + afterEach(() => { + sinon.restore(); }); + }); }; diff --git a/test/unit/clients/smapi-client-test/resources/manifest.js b/test/unit/clients/smapi-client-test/resources/manifest.js index 38b7bf1e..ee147071 100644 --- a/test/unit/clients/smapi-client-test/resources/manifest.js +++ b/test/unit/clients/smapi-client-test/resources/manifest.js @@ -1,87 +1,87 @@ -const { expect } = require('chai'); -const sinon = require('sinon'); +const {expect} = require("chai"); +const sinon = require("sinon"); -const httpClient = require('@src/clients/http-client'); -const AuthorizationController = require('@src/controllers/authorization-controller'); -const CONSTANTS = require('@src/utils/constants'); +const httpClient = require("../../../../../lib/clients/http-client"); +const AuthorizationController = require("../../../../../lib/controllers/authorization-controller"); +const CONSTANTS = require("../../../../../lib/utils/constants"); const noop = () => {}; module.exports = (smapiClient) => { - describe('# skill manifest APIs', () => { - let httpClientStub; - beforeEach(() => { - httpClientStub = sinon.stub(httpClient, 'request').callsFake(noop); - sinon.stub(AuthorizationController.prototype, 'tokenRefreshAndRead'); - }); + describe("# skill manifest APIs", () => { + let httpClientStub; + beforeEach(() => { + httpClientStub = sinon.stub(httpClient, "request").callsFake(noop); + sinon.stub(AuthorizationController.prototype, "tokenRefreshAndRead"); + }); - const TEST_MANIFEST = { manifest: 'manifest' }; - const TEST_SKILL_ID = 'skillId'; - const TEST_SKILL_STAGE = 'skillStage'; - const TEST_ETAG = 'eTag'; - const TEST_PROFILE = 'testProfile'; - const TEST_ACCESS_TOKEN = 'access_token'; + const TEST_MANIFEST = {manifest: "manifest"}; + const TEST_SKILL_ID = "skillId"; + const TEST_SKILL_STAGE = "skillStage"; + const TEST_ETAG = "eTag"; + const TEST_PROFILE = "testProfile"; + const TEST_ACCESS_TOKEN = "access_token"; - [ - { - testCase: 'get-manifest', - apiFunc: smapiClient.skill.manifest.getManifest, - parameters: [TEST_SKILL_ID, TEST_SKILL_STAGE, noop], - expectedOptions: { - url: `${CONSTANTS.SMAPI.ENDPOINT}/v1/skills/${TEST_SKILL_ID}/stages/${TEST_SKILL_STAGE}/manifest`, - method: CONSTANTS.HTTP_REQUEST.VERB.GET, - headers: { - authorization: TEST_ACCESS_TOKEN - }, - body: null, - json: false - } - }, - { - testCase: 'update-manifest', - apiFunc: smapiClient.skill.manifest.updateManifest, - parameters: [TEST_SKILL_ID, TEST_SKILL_STAGE, TEST_MANIFEST, TEST_ETAG, noop], - expectedOptions: { - url: `${CONSTANTS.SMAPI.ENDPOINT}/v1/skills/${TEST_SKILL_ID}/stages/${TEST_SKILL_STAGE}/manifest`, - method: CONSTANTS.HTTP_REQUEST.VERB.PUT, - headers: { - 'If-Match': TEST_ETAG, - authorization: TEST_ACCESS_TOKEN - }, - body: { manifest: 'manifest' }, - json: true - } - }, - { - testCase: 'update-manifest without eTag', - apiFunc: smapiClient.skill.manifest.updateManifest, - parameters: [TEST_SKILL_ID, TEST_SKILL_STAGE, TEST_MANIFEST, null, noop], - expectedOptions: { - url: `${CONSTANTS.SMAPI.ENDPOINT}/v1/skills/${TEST_SKILL_ID}/stages/${TEST_SKILL_STAGE}/manifest`, - method: CONSTANTS.HTTP_REQUEST.VERB.PUT, - headers: { - authorization: TEST_ACCESS_TOKEN - }, - body: { manifest: 'manifest' }, - json: true - } - } - ].forEach(({ testCase, apiFunc, parameters, expectedOptions }) => { - it(`| call ${testCase} successfully`, (done) => { - // setup - AuthorizationController.prototype.tokenRefreshAndRead.callsArgWith(1, null, TEST_ACCESS_TOKEN); - // call - apiFunc(...parameters); - // verify - expect(AuthorizationController.prototype.tokenRefreshAndRead.called).equal(true); - expect(AuthorizationController.prototype.tokenRefreshAndRead.args[0][0]).equal(TEST_PROFILE); - expect(httpClientStub.args[0][0]).deep.equal(expectedOptions); - done(); - }); - }); + [ + { + testCase: "get-manifest", + apiFunc: smapiClient.skill.manifest.getManifest, + parameters: [TEST_SKILL_ID, TEST_SKILL_STAGE, noop], + expectedOptions: { + url: `${CONSTANTS.SMAPI.ENDPOINT}/v1/skills/${TEST_SKILL_ID}/stages/${TEST_SKILL_STAGE}/manifest`, + method: CONSTANTS.HTTP_REQUEST.VERB.GET, + headers: { + authorization: TEST_ACCESS_TOKEN, + }, + body: null, + json: false, + }, + }, + { + testCase: "update-manifest", + apiFunc: smapiClient.skill.manifest.updateManifest, + parameters: [TEST_SKILL_ID, TEST_SKILL_STAGE, TEST_MANIFEST, TEST_ETAG, noop], + expectedOptions: { + url: `${CONSTANTS.SMAPI.ENDPOINT}/v1/skills/${TEST_SKILL_ID}/stages/${TEST_SKILL_STAGE}/manifest`, + method: CONSTANTS.HTTP_REQUEST.VERB.PUT, + headers: { + "If-Match": TEST_ETAG, + authorization: TEST_ACCESS_TOKEN, + }, + body: {manifest: "manifest"}, + json: true, + }, + }, + { + testCase: "update-manifest without eTag", + apiFunc: smapiClient.skill.manifest.updateManifest, + parameters: [TEST_SKILL_ID, TEST_SKILL_STAGE, TEST_MANIFEST, null, noop], + expectedOptions: { + url: `${CONSTANTS.SMAPI.ENDPOINT}/v1/skills/${TEST_SKILL_ID}/stages/${TEST_SKILL_STAGE}/manifest`, + method: CONSTANTS.HTTP_REQUEST.VERB.PUT, + headers: { + authorization: TEST_ACCESS_TOKEN, + }, + body: {manifest: "manifest"}, + json: true, + }, + }, + ].forEach(({testCase, apiFunc, parameters, expectedOptions}) => { + it(`| call ${testCase} successfully`, (done) => { + // setup + AuthorizationController.prototype.tokenRefreshAndRead.callsArgWith(1, null, TEST_ACCESS_TOKEN); + // call + apiFunc(...parameters); + // verify + expect(AuthorizationController.prototype.tokenRefreshAndRead.called).equal(true); + expect(AuthorizationController.prototype.tokenRefreshAndRead.args[0][0]).equal(TEST_PROFILE); + expect(httpClientStub.args[0][0]).deep.equal(expectedOptions); + done(); + }); + }); - afterEach(() => { - sinon.restore(); - }); + afterEach(() => { + sinon.restore(); }); + }); }; diff --git a/test/unit/clients/smapi-client-test/resources/private-skill.js b/test/unit/clients/smapi-client-test/resources/private-skill.js index 93918e09..117af88d 100644 --- a/test/unit/clients/smapi-client-test/resources/private-skill.js +++ b/test/unit/clients/smapi-client-test/resources/private-skill.js @@ -1,115 +1,115 @@ -const { expect } = require('chai'); -const sinon = require('sinon'); +const {expect} = require("chai"); +const sinon = require("sinon"); -const httpClient = require('@src/clients/http-client'); -const AuthorizationController = require('@src/controllers/authorization-controller'); -const CONSTANTS = require('@src/utils/constants'); +const httpClient = require("../../../../../lib/clients/http-client"); +const AuthorizationController = require("../../../../../lib/controllers/authorization-controller"); +const CONSTANTS = require("../../../../../lib/utils/constants"); const noop = () => {}; module.exports = (smapiClient) => { - describe('# skill privateSkill APIs', () => { - let httpClientStub; - beforeEach(() => { - httpClientStub = sinon.stub(httpClient, 'request').callsFake(noop); - sinon.stub(AuthorizationController.prototype, 'tokenRefreshAndRead'); - }); + describe("# skill privateSkill APIs", () => { + let httpClientStub; + beforeEach(() => { + httpClientStub = sinon.stub(httpClient, "request").callsFake(noop); + sinon.stub(AuthorizationController.prototype, "tokenRefreshAndRead"); + }); - const TEST_SKILL_ID = 'skillId'; - const TEST_SKILL_STAGE = 'skillStage'; - const TEST_ACCOUNT_ID = 'accountId'; - const TEST_NEXT_TOKEN = 'nextToken'; - const TEST_MAX_RESULTS = 'maxResults'; - const TEST_PROFILE = 'testProfile'; - const TEST_ACCESS_TOKEN = 'access_token'; + const TEST_SKILL_ID = "skillId"; + const TEST_SKILL_STAGE = "skillStage"; + const TEST_ACCOUNT_ID = "accountId"; + const TEST_NEXT_TOKEN = "nextToken"; + const TEST_MAX_RESULTS = "maxResults"; + const TEST_PROFILE = "testProfile"; + const TEST_ACCESS_TOKEN = "access_token"; - [ - { - testCase: 'add-private-distribution-account', - apiFunc: smapiClient.skill.privateSkill.addPrivateDistributionAccount, - parameters: [TEST_SKILL_ID, TEST_SKILL_STAGE, TEST_ACCOUNT_ID, noop], - expectedOptions: { - url: `${CONSTANTS.SMAPI.ENDPOINT}/v1/skills/${TEST_SKILL_ID}/stages/${TEST_SKILL_STAGE}/privateDistributionAccounts/${TEST_ACCOUNT_ID}`, - method: CONSTANTS.HTTP_REQUEST.VERB.PUT, - headers: { - authorization: TEST_ACCESS_TOKEN - }, - body: null, - json: false - } - }, - { - testCase: 'list-private-distribution-accounts', - apiFunc: smapiClient.skill.privateSkill.listPrivateDistributionAccounts, - parameters: [TEST_SKILL_ID, TEST_SKILL_STAGE, { nextToken: TEST_NEXT_TOKEN, maxResults: TEST_MAX_RESULTS }, noop], - expectedOptions: { - url: `${CONSTANTS.SMAPI.ENDPOINT}/v1/skills/${TEST_SKILL_ID}/stages/${TEST_SKILL_STAGE}/privateDistributionAccounts?nextToken=${TEST_NEXT_TOKEN}&maxResults=${TEST_MAX_RESULTS}`, - method: CONSTANTS.HTTP_REQUEST.VERB.GET, - headers: { - authorization: TEST_ACCESS_TOKEN - }, - body: null, - json: false - } - }, - { - testCase: 'list-private-distribution-accounts without nextToken', - apiFunc: smapiClient.skill.privateSkill.listPrivateDistributionAccounts, - parameters: [TEST_SKILL_ID, TEST_SKILL_STAGE, { maxResults: TEST_MAX_RESULTS }, noop], - expectedOptions: { - url: `${CONSTANTS.SMAPI.ENDPOINT}/v1/skills/${TEST_SKILL_ID}/stages/${TEST_SKILL_STAGE}/privateDistributionAccounts?maxResults=${TEST_MAX_RESULTS}`, - method: CONSTANTS.HTTP_REQUEST.VERB.GET, - headers: { - authorization: TEST_ACCESS_TOKEN - }, - body: null, - json: false - } - }, - { - testCase: 'list-private-distribution-accounts without maxResults', - apiFunc: smapiClient.skill.privateSkill.listPrivateDistributionAccounts, - parameters: [TEST_SKILL_ID, TEST_SKILL_STAGE, { nextToken: TEST_NEXT_TOKEN }, noop], - expectedOptions: { - url: `${CONSTANTS.SMAPI.ENDPOINT}/v1/skills/${TEST_SKILL_ID}/stages/${TEST_SKILL_STAGE}/privateDistributionAccounts?nextToken=${TEST_NEXT_TOKEN}&maxResults=50`, - method: CONSTANTS.HTTP_REQUEST.VERB.GET, - headers: { - authorization: TEST_ACCESS_TOKEN - }, - body: null, - json: false - } - }, - { - testCase: 'delete-private-distribution-account', - apiFunc: smapiClient.skill.privateSkill.deletePrivateDistributionAccount, - parameters: [TEST_SKILL_ID, TEST_SKILL_STAGE, TEST_ACCOUNT_ID, noop], - expectedOptions: { - url: `${CONSTANTS.SMAPI.ENDPOINT}/v1/skills/${TEST_SKILL_ID}/stages/${TEST_SKILL_STAGE}/privateDistributionAccounts/${TEST_ACCOUNT_ID}`, - method: CONSTANTS.HTTP_REQUEST.VERB.DELETE, - headers: { - authorization: TEST_ACCESS_TOKEN - }, - body: null, - json: false - } - } - ].forEach(({ testCase, apiFunc, parameters, expectedOptions }) => { - it(`| call ${testCase} successfully`, (done) => { - // setup - AuthorizationController.prototype.tokenRefreshAndRead.callsArgWith(1, null, TEST_ACCESS_TOKEN); - // call - apiFunc(...parameters); - // verify - expect(AuthorizationController.prototype.tokenRefreshAndRead.called).equal(true); - expect(AuthorizationController.prototype.tokenRefreshAndRead.args[0][0]).equal(TEST_PROFILE); - expect(httpClientStub.args[0][0]).deep.equal(expectedOptions); - done(); - }); - }); + [ + { + testCase: "add-private-distribution-account", + apiFunc: smapiClient.skill.privateSkill.addPrivateDistributionAccount, + parameters: [TEST_SKILL_ID, TEST_SKILL_STAGE, TEST_ACCOUNT_ID, noop], + expectedOptions: { + url: `${CONSTANTS.SMAPI.ENDPOINT}/v1/skills/${TEST_SKILL_ID}/stages/${TEST_SKILL_STAGE}/privateDistributionAccounts/${TEST_ACCOUNT_ID}`, + method: CONSTANTS.HTTP_REQUEST.VERB.PUT, + headers: { + authorization: TEST_ACCESS_TOKEN, + }, + body: null, + json: false, + }, + }, + { + testCase: "list-private-distribution-accounts", + apiFunc: smapiClient.skill.privateSkill.listPrivateDistributionAccounts, + parameters: [TEST_SKILL_ID, TEST_SKILL_STAGE, {nextToken: TEST_NEXT_TOKEN, maxResults: TEST_MAX_RESULTS}, noop], + expectedOptions: { + url: `${CONSTANTS.SMAPI.ENDPOINT}/v1/skills/${TEST_SKILL_ID}/stages/${TEST_SKILL_STAGE}/privateDistributionAccounts?nextToken=${TEST_NEXT_TOKEN}&maxResults=${TEST_MAX_RESULTS}`, + method: CONSTANTS.HTTP_REQUEST.VERB.GET, + headers: { + authorization: TEST_ACCESS_TOKEN, + }, + body: null, + json: false, + }, + }, + { + testCase: "list-private-distribution-accounts without nextToken", + apiFunc: smapiClient.skill.privateSkill.listPrivateDistributionAccounts, + parameters: [TEST_SKILL_ID, TEST_SKILL_STAGE, {maxResults: TEST_MAX_RESULTS}, noop], + expectedOptions: { + url: `${CONSTANTS.SMAPI.ENDPOINT}/v1/skills/${TEST_SKILL_ID}/stages/${TEST_SKILL_STAGE}/privateDistributionAccounts?maxResults=${TEST_MAX_RESULTS}`, + method: CONSTANTS.HTTP_REQUEST.VERB.GET, + headers: { + authorization: TEST_ACCESS_TOKEN, + }, + body: null, + json: false, + }, + }, + { + testCase: "list-private-distribution-accounts without maxResults", + apiFunc: smapiClient.skill.privateSkill.listPrivateDistributionAccounts, + parameters: [TEST_SKILL_ID, TEST_SKILL_STAGE, {nextToken: TEST_NEXT_TOKEN}, noop], + expectedOptions: { + url: `${CONSTANTS.SMAPI.ENDPOINT}/v1/skills/${TEST_SKILL_ID}/stages/${TEST_SKILL_STAGE}/privateDistributionAccounts?nextToken=${TEST_NEXT_TOKEN}&maxResults=50`, + method: CONSTANTS.HTTP_REQUEST.VERB.GET, + headers: { + authorization: TEST_ACCESS_TOKEN, + }, + body: null, + json: false, + }, + }, + { + testCase: "delete-private-distribution-account", + apiFunc: smapiClient.skill.privateSkill.deletePrivateDistributionAccount, + parameters: [TEST_SKILL_ID, TEST_SKILL_STAGE, TEST_ACCOUNT_ID, noop], + expectedOptions: { + url: `${CONSTANTS.SMAPI.ENDPOINT}/v1/skills/${TEST_SKILL_ID}/stages/${TEST_SKILL_STAGE}/privateDistributionAccounts/${TEST_ACCOUNT_ID}`, + method: CONSTANTS.HTTP_REQUEST.VERB.DELETE, + headers: { + authorization: TEST_ACCESS_TOKEN, + }, + body: null, + json: false, + }, + }, + ].forEach(({testCase, apiFunc, parameters, expectedOptions}) => { + it(`| call ${testCase} successfully`, (done) => { + // setup + AuthorizationController.prototype.tokenRefreshAndRead.callsArgWith(1, null, TEST_ACCESS_TOKEN); + // call + apiFunc(...parameters); + // verify + expect(AuthorizationController.prototype.tokenRefreshAndRead.called).equal(true); + expect(AuthorizationController.prototype.tokenRefreshAndRead.args[0][0]).equal(TEST_PROFILE); + expect(httpClientStub.args[0][0]).deep.equal(expectedOptions); + done(); + }); + }); - afterEach(() => { - sinon.restore(); - }); + afterEach(() => { + sinon.restore(); }); + }); }; diff --git a/test/unit/clients/smapi-client-test/resources/publishing.js b/test/unit/clients/smapi-client-test/resources/publishing.js index 7c28c1b5..d02f2d05 100644 --- a/test/unit/clients/smapi-client-test/resources/publishing.js +++ b/test/unit/clients/smapi-client-test/resources/publishing.js @@ -1,167 +1,165 @@ -const { expect } = require('chai'); -const sinon = require('sinon'); +const {expect} = require("chai"); +const sinon = require("sinon"); -const httpClient = require('@src/clients/http-client'); -const AuthorizationController = require('@src/controllers/authorization-controller'); -const CONSTANTS = require('@src/utils/constants'); +const httpClient = require("../../../../../lib/clients/http-client"); +const AuthorizationController = require("../../../../../lib/controllers/authorization-controller"); +const CONSTANTS = require("../../../../../lib/utils/constants"); const noop = () => {}; module.exports = (smapiClient) => { - describe('# skill publishing lifecycle related APIs', () => { - let httpClientStub; - beforeEach(() => { - httpClientStub = sinon.stub(httpClient, 'request').callsFake(noop); - sinon.stub(AuthorizationController.prototype, 'tokenRefreshAndRead'); - }); + describe("# skill publishing lifecycle related APIs", () => { + let httpClientStub; + beforeEach(() => { + httpClientStub = sinon.stub(httpClient, "request").callsFake(noop); + sinon.stub(AuthorizationController.prototype, "tokenRefreshAndRead"); + }); - const TEST_SKILL_ID = 'skillId'; - const TEST_WITHDRAW_REASON = 'withdrawReason'; - const TEST_WITHDRAW_MESSAGE = 'withdrawMessage'; - const TEST_NEXT_TOKEN = 'nextToken'; - const TEST_MAX_RESULTS = 'maxResults'; - const TEST_CERTIFICATION_ID = 'certificationId'; - const TEST_ACCEPT_LANGUAGE = 'acceptLanguage'; - const TEST_PROFILE = 'testProfile'; - const TEST_ACCESS_TOKEN = 'access_token'; + const TEST_SKILL_ID = "skillId"; + const TEST_WITHDRAW_REASON = "withdrawReason"; + const TEST_WITHDRAW_MESSAGE = "withdrawMessage"; + const TEST_NEXT_TOKEN = "nextToken"; + const TEST_MAX_RESULTS = "maxResults"; + const TEST_CERTIFICATION_ID = "certificationId"; + const TEST_ACCEPT_LANGUAGE = "acceptLanguage"; + const TEST_PROFILE = "testProfile"; + const TEST_ACCESS_TOKEN = "access_token"; - [ - { - testCase: 'submit-skill', - apiFunc: smapiClient.skill.publishing.submitSkill, - parameters: [TEST_SKILL_ID, noop], - expectedOptions: { - url: `${CONSTANTS.SMAPI.ENDPOINT}/v1/skills/${TEST_SKILL_ID}/submit`, - method: CONSTANTS.HTTP_REQUEST.VERB.POST, - headers: { - authorization: TEST_ACCESS_TOKEN - }, - body: null, - json: false - } - }, - { - testCase: 'withdraw-skill', - apiFunc: smapiClient.skill.publishing.withdrawSkill, - parameters: [TEST_SKILL_ID, TEST_WITHDRAW_REASON, TEST_WITHDRAW_MESSAGE, noop], - expectedOptions: { - url: `${CONSTANTS.SMAPI.ENDPOINT}/v1/skills/${TEST_SKILL_ID}/withdraw`, - method: CONSTANTS.HTTP_REQUEST.VERB.POST, - headers: { - authorization: TEST_ACCESS_TOKEN - }, - body: { - reason: TEST_WITHDRAW_REASON, - message: TEST_WITHDRAW_MESSAGE - }, - json: true - } - }, - { - testCase: 'list-certifications', - apiFunc: smapiClient.skill.publishing.listCertifications, - parameters: [TEST_SKILL_ID, { nextToken: TEST_NEXT_TOKEN, - maxResults: TEST_MAX_RESULTS }, noop], - expectedOptions: { - url: `${CONSTANTS.SMAPI.ENDPOINT}/v1/skills/${TEST_SKILL_ID}/certifications?` - + `nextToken=${TEST_NEXT_TOKEN}&maxResults=${TEST_MAX_RESULTS}`, - method: CONSTANTS.HTTP_REQUEST.VERB.GET, - headers: { - authorization: TEST_ACCESS_TOKEN - }, - body: null, - json: false - } - }, - { - testCase: 'list-certifications without maxResults', - apiFunc: smapiClient.skill.publishing.listCertifications, - parameters: [TEST_SKILL_ID, { nextToken: TEST_NEXT_TOKEN }, noop], - expectedOptions: { - url: `${CONSTANTS.SMAPI.ENDPOINT}/v1/skills/${TEST_SKILL_ID}/certifications?` - + `nextToken=${TEST_NEXT_TOKEN}`, - method: CONSTANTS.HTTP_REQUEST.VERB.GET, - headers: { - authorization: TEST_ACCESS_TOKEN - }, - body: null, - json: false - } - }, - { - testCase: 'list-certifications without nextToken', - apiFunc: smapiClient.skill.publishing.listCertifications, - parameters: [TEST_SKILL_ID, { maxResults: TEST_MAX_RESULTS }, noop], - expectedOptions: { - url: `${CONSTANTS.SMAPI.ENDPOINT}/v1/skills/${TEST_SKILL_ID}/certifications?` - + `maxResults=${TEST_MAX_RESULTS}`, - method: CONSTANTS.HTTP_REQUEST.VERB.GET, - headers: { - authorization: TEST_ACCESS_TOKEN - }, - body: null, - json: false - } - }, - { - testCase: 'list-certifications with null query parameters', - apiFunc: smapiClient.skill.publishing.listCertifications, - parameters: [TEST_SKILL_ID, null, noop], - expectedOptions: { - url: `${CONSTANTS.SMAPI.ENDPOINT}/v1/skills/${TEST_SKILL_ID}/certifications`, - method: CONSTANTS.HTTP_REQUEST.VERB.GET, - headers: { - authorization: TEST_ACCESS_TOKEN - }, - body: null, - json: false - } - }, - { - testCase: 'get-certification', - apiFunc: smapiClient.skill.publishing.getCertification, - parameters: [TEST_SKILL_ID, TEST_CERTIFICATION_ID, TEST_ACCEPT_LANGUAGE, noop], - expectedOptions: { - url: `${CONSTANTS.SMAPI.ENDPOINT}/v1/skills/${TEST_SKILL_ID}/certifications/${TEST_CERTIFICATION_ID}`, - method: CONSTANTS.HTTP_REQUEST.VERB.GET, - headers: { - 'Accept-Language': TEST_ACCEPT_LANGUAGE, - authorization: TEST_ACCESS_TOKEN - }, - body: null, - json: false - } - }, - { - testCase: 'get-certification with null accept language', - apiFunc: smapiClient.skill.publishing.getCertification, - parameters: [TEST_SKILL_ID, TEST_CERTIFICATION_ID, null, noop], - expectedOptions: { - url: `${CONSTANTS.SMAPI.ENDPOINT}/v1/skills/${TEST_SKILL_ID}/certifications/${TEST_CERTIFICATION_ID}`, - method: CONSTANTS.HTTP_REQUEST.VERB.GET, - headers: { - authorization: TEST_ACCESS_TOKEN - }, - body: null, - json: false - } - }, - ].forEach(({ testCase, apiFunc, parameters, expectedOptions }) => { - it(`| call ${testCase} successfully`, (done) => { - // setup - AuthorizationController.prototype.tokenRefreshAndRead.callsArgWith(1, null, TEST_ACCESS_TOKEN); - // call - apiFunc(...parameters); - // verify - expect(AuthorizationController.prototype.tokenRefreshAndRead.called).equal(true); - expect(AuthorizationController.prototype.tokenRefreshAndRead.args[0][0]).equal(TEST_PROFILE); - expect(httpClientStub.args[0][0]).deep.equal(expectedOptions); - done(); - }); - }); + [ + { + testCase: "submit-skill", + apiFunc: smapiClient.skill.publishing.submitSkill, + parameters: [TEST_SKILL_ID, noop], + expectedOptions: { + url: `${CONSTANTS.SMAPI.ENDPOINT}/v1/skills/${TEST_SKILL_ID}/submit`, + method: CONSTANTS.HTTP_REQUEST.VERB.POST, + headers: { + authorization: TEST_ACCESS_TOKEN, + }, + body: null, + json: false, + }, + }, + { + testCase: "withdraw-skill", + apiFunc: smapiClient.skill.publishing.withdrawSkill, + parameters: [TEST_SKILL_ID, TEST_WITHDRAW_REASON, TEST_WITHDRAW_MESSAGE, noop], + expectedOptions: { + url: `${CONSTANTS.SMAPI.ENDPOINT}/v1/skills/${TEST_SKILL_ID}/withdraw`, + method: CONSTANTS.HTTP_REQUEST.VERB.POST, + headers: { + authorization: TEST_ACCESS_TOKEN, + }, + body: { + reason: TEST_WITHDRAW_REASON, + message: TEST_WITHDRAW_MESSAGE, + }, + json: true, + }, + }, + { + testCase: "list-certifications", + apiFunc: smapiClient.skill.publishing.listCertifications, + parameters: [TEST_SKILL_ID, {nextToken: TEST_NEXT_TOKEN, maxResults: TEST_MAX_RESULTS}, noop], + expectedOptions: { + url: + `${CONSTANTS.SMAPI.ENDPOINT}/v1/skills/${TEST_SKILL_ID}/certifications?` + + `nextToken=${TEST_NEXT_TOKEN}&maxResults=${TEST_MAX_RESULTS}`, + method: CONSTANTS.HTTP_REQUEST.VERB.GET, + headers: { + authorization: TEST_ACCESS_TOKEN, + }, + body: null, + json: false, + }, + }, + { + testCase: "list-certifications without maxResults", + apiFunc: smapiClient.skill.publishing.listCertifications, + parameters: [TEST_SKILL_ID, {nextToken: TEST_NEXT_TOKEN}, noop], + expectedOptions: { + url: `${CONSTANTS.SMAPI.ENDPOINT}/v1/skills/${TEST_SKILL_ID}/certifications?` + `nextToken=${TEST_NEXT_TOKEN}`, + method: CONSTANTS.HTTP_REQUEST.VERB.GET, + headers: { + authorization: TEST_ACCESS_TOKEN, + }, + body: null, + json: false, + }, + }, + { + testCase: "list-certifications without nextToken", + apiFunc: smapiClient.skill.publishing.listCertifications, + parameters: [TEST_SKILL_ID, {maxResults: TEST_MAX_RESULTS}, noop], + expectedOptions: { + url: `${CONSTANTS.SMAPI.ENDPOINT}/v1/skills/${TEST_SKILL_ID}/certifications?` + `maxResults=${TEST_MAX_RESULTS}`, + method: CONSTANTS.HTTP_REQUEST.VERB.GET, + headers: { + authorization: TEST_ACCESS_TOKEN, + }, + body: null, + json: false, + }, + }, + { + testCase: "list-certifications with null query parameters", + apiFunc: smapiClient.skill.publishing.listCertifications, + parameters: [TEST_SKILL_ID, null, noop], + expectedOptions: { + url: `${CONSTANTS.SMAPI.ENDPOINT}/v1/skills/${TEST_SKILL_ID}/certifications`, + method: CONSTANTS.HTTP_REQUEST.VERB.GET, + headers: { + authorization: TEST_ACCESS_TOKEN, + }, + body: null, + json: false, + }, + }, + { + testCase: "get-certification", + apiFunc: smapiClient.skill.publishing.getCertification, + parameters: [TEST_SKILL_ID, TEST_CERTIFICATION_ID, TEST_ACCEPT_LANGUAGE, noop], + expectedOptions: { + url: `${CONSTANTS.SMAPI.ENDPOINT}/v1/skills/${TEST_SKILL_ID}/certifications/${TEST_CERTIFICATION_ID}`, + method: CONSTANTS.HTTP_REQUEST.VERB.GET, + headers: { + "Accept-Language": TEST_ACCEPT_LANGUAGE, + authorization: TEST_ACCESS_TOKEN, + }, + body: null, + json: false, + }, + }, + { + testCase: "get-certification with null accept language", + apiFunc: smapiClient.skill.publishing.getCertification, + parameters: [TEST_SKILL_ID, TEST_CERTIFICATION_ID, null, noop], + expectedOptions: { + url: `${CONSTANTS.SMAPI.ENDPOINT}/v1/skills/${TEST_SKILL_ID}/certifications/${TEST_CERTIFICATION_ID}`, + method: CONSTANTS.HTTP_REQUEST.VERB.GET, + headers: { + authorization: TEST_ACCESS_TOKEN, + }, + body: null, + json: false, + }, + }, + ].forEach(({testCase, apiFunc, parameters, expectedOptions}) => { + it(`| call ${testCase} successfully`, (done) => { + // setup + AuthorizationController.prototype.tokenRefreshAndRead.callsArgWith(1, null, TEST_ACCESS_TOKEN); + // call + apiFunc(...parameters); + // verify + expect(AuthorizationController.prototype.tokenRefreshAndRead.called).equal(true); + expect(AuthorizationController.prototype.tokenRefreshAndRead.args[0][0]).equal(TEST_PROFILE); + expect(httpClientStub.args[0][0]).deep.equal(expectedOptions); + done(); + }); + }); - afterEach(() => { - sinon.restore(); - }); + afterEach(() => { + sinon.restore(); }); + }); }; diff --git a/test/unit/clients/smapi-client-test/resources/skill-package.js b/test/unit/clients/smapi-client-test/resources/skill-package.js index 6048440e..f0431131 100644 --- a/test/unit/clients/smapi-client-test/resources/skill-package.js +++ b/test/unit/clients/smapi-client-test/resources/skill-package.js @@ -1,129 +1,129 @@ -const { expect } = require('chai'); -const sinon = require('sinon'); +const {expect} = require("chai"); +const sinon = require("sinon"); -const httpClient = require('@src/clients/http-client'); -const AuthorizationController = require('@src/controllers/authorization-controller'); -const CONSTANTS = require('@src/utils/constants'); +const httpClient = require("../../../../../lib/clients/http-client"); +const AuthorizationController = require("../../../../../lib/controllers/authorization-controller"); +const CONSTANTS = require("../../../../../lib/utils/constants"); const noop = () => {}; module.exports = (smapiClient) => { - describe('# smapi client skill package APIs', () => { - let httpClientStub; - beforeEach(() => { - httpClientStub = sinon.stub(httpClient, 'request').callsFake(noop); - sinon.stub(AuthorizationController.prototype, 'tokenRefreshAndRead'); - }); + describe("# smapi client skill package APIs", () => { + let httpClientStub; + beforeEach(() => { + httpClientStub = sinon.stub(httpClient, "request").callsFake(noop); + sinon.stub(AuthorizationController.prototype, "tokenRefreshAndRead"); + }); - const TEST_SKILL_ID = 'skillId'; - const TEST_VENDOR_ID = 'vendorId'; - const TEST_SKILL_STAGE = 'stage'; - const TEST_LOCATION = 'packageLocation'; - const TEST_IMPORT_ID = 'importId'; - const TEST_EXPORT_ID = 'exportId'; - const TEST_PROFILE = 'testProfile'; - const TEST_ACCESS_TOKEN = 'access_token'; + const TEST_SKILL_ID = "skillId"; + const TEST_VENDOR_ID = "vendorId"; + const TEST_SKILL_STAGE = "stage"; + const TEST_LOCATION = "packageLocation"; + const TEST_IMPORT_ID = "importId"; + const TEST_EXPORT_ID = "exportId"; + const TEST_PROFILE = "testProfile"; + const TEST_ACCESS_TOKEN = "access_token"; - [ - { - testCase: 'create-upload', - apiFunc: smapiClient.skillPackage.createUpload, - parameters: [noop], - expectedOptions: { - url: `${CONSTANTS.SMAPI.ENDPOINT}/v1/skills/uploads`, - method: CONSTANTS.HTTP_REQUEST.VERB.POST, - headers: { - authorization: TEST_ACCESS_TOKEN - }, - body: null, - json: false - } - }, - { - testCase: 'import-package with skillId only', - apiFunc: smapiClient.skillPackage.importPackage, - parameters: [TEST_SKILL_ID, null, TEST_LOCATION, noop], - expectedOptions: { - url: `${CONSTANTS.SMAPI.ENDPOINT}/v1/skills/${TEST_SKILL_ID}/imports`, - method: CONSTANTS.HTTP_REQUEST.VERB.POST, - headers: { - authorization: TEST_ACCESS_TOKEN - }, - body: { location: TEST_LOCATION }, - json: true - } - }, - { - testCase: 'import-package with vendorId only', - apiFunc: smapiClient.skillPackage.importPackage, - parameters: [null, TEST_VENDOR_ID, TEST_LOCATION, noop], - expectedOptions: { - url: `${CONSTANTS.SMAPI.ENDPOINT}/v1/skills/imports`, - method: CONSTANTS.HTTP_REQUEST.VERB.POST, - headers: { - authorization: TEST_ACCESS_TOKEN - }, - body: { location: TEST_LOCATION, vendorId: TEST_VENDOR_ID }, - json: true - } - }, - { - testCase: 'get-import-status', - apiFunc: smapiClient.skillPackage.getImportStatus, - parameters: [TEST_IMPORT_ID, noop], - expectedOptions: { - url: `${CONSTANTS.SMAPI.ENDPOINT}/v1/skills/imports/${TEST_IMPORT_ID}`, - method: CONSTANTS.HTTP_REQUEST.VERB.GET, - headers: { - authorization: TEST_ACCESS_TOKEN - }, - body: null, - json: false - } - }, - { - testCase: 'export-package', - apiFunc: smapiClient.skillPackage.exportPackage, - parameters: [TEST_SKILL_ID, TEST_SKILL_STAGE, noop], - expectedOptions: { - url: `${CONSTANTS.SMAPI.ENDPOINT}/v1/skills/${TEST_SKILL_ID}/stages/${TEST_SKILL_STAGE}/exports`, - method: CONSTANTS.HTTP_REQUEST.VERB.POST, - headers: { - authorization: TEST_ACCESS_TOKEN - }, - body: null, - json: false - } - }, - { - testCase: 'get-export-status', - apiFunc: smapiClient.skillPackage.getExportStatus, - parameters: [TEST_EXPORT_ID, noop], - expectedOptions: { - url: `${CONSTANTS.SMAPI.ENDPOINT}/v1/skills/exports/${TEST_EXPORT_ID}`, - method: CONSTANTS.HTTP_REQUEST.VERB.GET, - headers: { - authorization: TEST_ACCESS_TOKEN - }, - body: null, - json: false - } - }, - ].forEach(({ testCase, apiFunc, parameters, expectedOptions }) => { - it(`| call ${testCase} successfully`, () => { - // setup - AuthorizationController.prototype.tokenRefreshAndRead.callsArgWith(1, null, TEST_ACCESS_TOKEN); - // call - apiFunc(...parameters); - // verify - expect(AuthorizationController.prototype.tokenRefreshAndRead.called).equal(true); - expect(AuthorizationController.prototype.tokenRefreshAndRead.args[0][0]).equal(TEST_PROFILE); - expect(httpClientStub.args[0][0]).deep.equal(expectedOptions); - }); - }); + [ + { + testCase: "create-upload", + apiFunc: smapiClient.skillPackage.createUpload, + parameters: [noop], + expectedOptions: { + url: `${CONSTANTS.SMAPI.ENDPOINT}/v1/skills/uploads`, + method: CONSTANTS.HTTP_REQUEST.VERB.POST, + headers: { + authorization: TEST_ACCESS_TOKEN, + }, + body: null, + json: false, + }, + }, + { + testCase: "import-package with skillId only", + apiFunc: smapiClient.skillPackage.importPackage, + parameters: [TEST_SKILL_ID, null, TEST_LOCATION, noop], + expectedOptions: { + url: `${CONSTANTS.SMAPI.ENDPOINT}/v1/skills/${TEST_SKILL_ID}/imports`, + method: CONSTANTS.HTTP_REQUEST.VERB.POST, + headers: { + authorization: TEST_ACCESS_TOKEN, + }, + body: {location: TEST_LOCATION}, + json: true, + }, + }, + { + testCase: "import-package with vendorId only", + apiFunc: smapiClient.skillPackage.importPackage, + parameters: [null, TEST_VENDOR_ID, TEST_LOCATION, noop], + expectedOptions: { + url: `${CONSTANTS.SMAPI.ENDPOINT}/v1/skills/imports`, + method: CONSTANTS.HTTP_REQUEST.VERB.POST, + headers: { + authorization: TEST_ACCESS_TOKEN, + }, + body: {location: TEST_LOCATION, vendorId: TEST_VENDOR_ID}, + json: true, + }, + }, + { + testCase: "get-import-status", + apiFunc: smapiClient.skillPackage.getImportStatus, + parameters: [TEST_IMPORT_ID, noop], + expectedOptions: { + url: `${CONSTANTS.SMAPI.ENDPOINT}/v1/skills/imports/${TEST_IMPORT_ID}`, + method: CONSTANTS.HTTP_REQUEST.VERB.GET, + headers: { + authorization: TEST_ACCESS_TOKEN, + }, + body: null, + json: false, + }, + }, + { + testCase: "export-package", + apiFunc: smapiClient.skillPackage.exportPackage, + parameters: [TEST_SKILL_ID, TEST_SKILL_STAGE, noop], + expectedOptions: { + url: `${CONSTANTS.SMAPI.ENDPOINT}/v1/skills/${TEST_SKILL_ID}/stages/${TEST_SKILL_STAGE}/exports`, + method: CONSTANTS.HTTP_REQUEST.VERB.POST, + headers: { + authorization: TEST_ACCESS_TOKEN, + }, + body: null, + json: false, + }, + }, + { + testCase: "get-export-status", + apiFunc: smapiClient.skillPackage.getExportStatus, + parameters: [TEST_EXPORT_ID, noop], + expectedOptions: { + url: `${CONSTANTS.SMAPI.ENDPOINT}/v1/skills/exports/${TEST_EXPORT_ID}`, + method: CONSTANTS.HTTP_REQUEST.VERB.GET, + headers: { + authorization: TEST_ACCESS_TOKEN, + }, + body: null, + json: false, + }, + }, + ].forEach(({testCase, apiFunc, parameters, expectedOptions}) => { + it(`| call ${testCase} successfully`, () => { + // setup + AuthorizationController.prototype.tokenRefreshAndRead.callsArgWith(1, null, TEST_ACCESS_TOKEN); + // call + apiFunc(...parameters); + // verify + expect(AuthorizationController.prototype.tokenRefreshAndRead.called).equal(true); + expect(AuthorizationController.prototype.tokenRefreshAndRead.args[0][0]).equal(TEST_PROFILE); + expect(httpClientStub.args[0][0]).deep.equal(expectedOptions); + }); + }); - afterEach(() => { - sinon.restore(); - }); + afterEach(() => { + sinon.restore(); }); + }); }; diff --git a/test/unit/clients/smapi-client-test/resources/skill.js b/test/unit/clients/smapi-client-test/resources/skill.js index 7fc0bd01..7a541874 100644 --- a/test/unit/clients/smapi-client-test/resources/skill.js +++ b/test/unit/clients/smapi-client-test/resources/skill.js @@ -1,548 +1,698 @@ -const { expect } = require('chai'); -const sinon = require('sinon'); +const {expect} = require("chai"); +const sinon = require("sinon"); -const httpClient = require('@src/clients/http-client'); -const AuthorizationController = require('@src/controllers/authorization-controller'); -const CONSTANTS = require('@src/utils/constants'); +const httpClient = require("../../../../../lib/clients/http-client"); +const AuthorizationController = require("../../../../../lib/controllers/authorization-controller"); +const CONSTANTS = require("../../../../../lib/utils/constants"); const noop = () => {}; module.exports = (smapiClient) => { - let httpClientStub; - const TEST_PROFILE = 'testProfile'; - const TEST_ACCESS_TOKEN = 'access_token'; - describe('# skill CRUD related APIs', () => { - beforeEach(() => { - httpClientStub = sinon.stub(httpClient, 'request').callsFake(noop); - sinon.stub(AuthorizationController.prototype, 'tokenRefreshAndRead'); - }); + let httpClientStub; + const TEST_PROFILE = "testProfile"; + const TEST_ACCESS_TOKEN = "access_token"; + describe("# skill CRUD related APIs", () => { + beforeEach(() => { + sinon.restore(); + httpClientStub = sinon.stub(httpClient, "request").callsFake(noop); + sinon.stub(AuthorizationController.prototype, "tokenRefreshAndRead"); + }); - const TEST_SKILL_ID = 'skillId'; - const TEST_SKILL_STAGE = 'skillStage'; - const TEST_MANIFEST = { manifest: 'manifest' }; - const TEST_VENDOR_ID = 'vendorId'; - const TEST_NEXT_TOKEN = 'nextToken'; - const TEST_MAX_RESULTS = 'maxResults'; + const TEST_SKILL_ID = "skillId"; + const TEST_SKILL_STAGE = "skillStage"; + const TEST_MANIFEST = {manifest: "manifest"}; + const TEST_VENDOR_ID = "vendorId"; + const TEST_NEXT_TOKEN = "nextToken"; + const TEST_MAX_RESULTS = "maxResults"; - [ - { - testCase: 'create-skill', - apiFunc: smapiClient.skill.createSkill, - parameters: [TEST_MANIFEST, TEST_VENDOR_ID, noop], - expectedOptions: { - url: `${CONSTANTS.SMAPI.ENDPOINT}/v1/skills/`, - method: CONSTANTS.HTTP_REQUEST.VERB.POST, - headers: { - authorization: TEST_ACCESS_TOKEN - }, - body: { - manifest: 'manifest', - vendorId: TEST_VENDOR_ID - }, - json: true - } - }, - { - testCase: 'delete-skill', - apiFunc: smapiClient.skill.deleteSkill, - parameters: [TEST_SKILL_ID, noop], - expectedOptions: { - url: `${CONSTANTS.SMAPI.ENDPOINT}/v1/skills/${TEST_SKILL_ID}`, - method: CONSTANTS.HTTP_REQUEST.VERB.DELETE, - headers: { - authorization: TEST_ACCESS_TOKEN - }, - body: null, - json: false - } - }, - { - testCase: 'list-skills', - apiFunc: smapiClient.skill.listSkills, - parameters: [TEST_VENDOR_ID, { nextToken: TEST_NEXT_TOKEN, maxResults: TEST_MAX_RESULTS }, noop], - expectedOptions: { - url: `${CONSTANTS.SMAPI.ENDPOINT}/v1/skills?nextToken=${TEST_NEXT_TOKEN}&` - + `maxResults=${TEST_MAX_RESULTS}&vendorId=${TEST_VENDOR_ID}`, - method: CONSTANTS.HTTP_REQUEST.VERB.GET, - headers: { - authorization: TEST_ACCESS_TOKEN - }, - body: null, - json: false - } - }, - { - testCase: 'list-skills without maxResults', - apiFunc: smapiClient.skill.listSkills, - parameters: [TEST_VENDOR_ID, { nextToken: TEST_NEXT_TOKEN }, noop], - expectedOptions: { - url: `${CONSTANTS.SMAPI.ENDPOINT}/v1/skills?nextToken=${TEST_NEXT_TOKEN}&vendorId=${TEST_VENDOR_ID}&maxResults=50`, - method: CONSTANTS.HTTP_REQUEST.VERB.GET, - headers: { - authorization: TEST_ACCESS_TOKEN - }, - body: null, - json: false - } - }, - { - testCase: 'list-skills without nextToken', - apiFunc: smapiClient.skill.listSkills, - parameters: [TEST_VENDOR_ID, { maxResults: TEST_MAX_RESULTS }, noop], - expectedOptions: { - url: `${CONSTANTS.SMAPI.ENDPOINT}/v1/skills?maxResults=${TEST_MAX_RESULTS}&vendorId=${TEST_VENDOR_ID}`, - method: CONSTANTS.HTTP_REQUEST.VERB.GET, - headers: { - authorization: TEST_ACCESS_TOKEN - }, - body: null, - json: false - } - }, - { - testCase: 'list-skills with null query parameters', - apiFunc: smapiClient.skill.listSkills, - parameters: [TEST_VENDOR_ID, null, noop], - expectedOptions: { - url: `${CONSTANTS.SMAPI.ENDPOINT}/v1/skills?vendorId=${TEST_VENDOR_ID}&maxResults=50`, - method: CONSTANTS.HTTP_REQUEST.VERB.GET, - headers: { - authorization: TEST_ACCESS_TOKEN - }, - body: null, - json: false - } - }, - { - testCase: 'get-skill-status', - apiFunc: smapiClient.skill.getSkillStatus, - parameters: [TEST_SKILL_ID, null, noop], - expectedOptions: { - url: `${CONSTANTS.SMAPI.ENDPOINT}/v1/skills/${TEST_SKILL_ID}/status`, - method: CONSTANTS.HTTP_REQUEST.VERB.GET, - headers: { - authorization: TEST_ACCESS_TOKEN - }, - body: null, - json: false - } - }, - { - testCase: 'get-skill-status with manifest resource', - apiFunc: smapiClient.skill.getSkillStatus, - parameters: [TEST_SKILL_ID, [CONSTANTS.SKILL.RESOURCES.MANIFEST], noop], - expectedOptions: { - url: `${CONSTANTS.SMAPI.ENDPOINT}/v1/skills/${TEST_SKILL_ID}/status?resource=${CONSTANTS.SKILL.RESOURCES.MANIFEST}`, - method: CONSTANTS.HTTP_REQUEST.VERB.GET, - headers: { - authorization: TEST_ACCESS_TOKEN - }, - body: null, - json: false - } - }, - { - testCase: 'get-skill-status with manifest and interactionModel resource', - apiFunc: smapiClient.skill.getSkillStatus, - parameters: [TEST_SKILL_ID, [CONSTANTS.SKILL.RESOURCES.MANIFEST, CONSTANTS.SKILL.RESOURCES.INTERACTION_MODEL], noop], - expectedOptions: { - url: `${CONSTANTS.SMAPI.ENDPOINT}/v1/skills/${TEST_SKILL_ID}/status?resource=${CONSTANTS.SKILL.RESOURCES.MANIFEST}` - + `&resource=${CONSTANTS.SKILL.RESOURCES.INTERACTION_MODEL}`, - method: CONSTANTS.HTTP_REQUEST.VERB.GET, - headers: { - authorization: TEST_ACCESS_TOKEN - }, - body: null, - json: false - } - }, - { - testCase: 'list-isp-for-skill', - apiFunc: smapiClient.skill.listIspForSkill, - parameters: [TEST_SKILL_ID, TEST_SKILL_STAGE, { nextToken: TEST_NEXT_TOKEN, maxResults: TEST_MAX_RESULTS }, noop], - expectedOptions: { - url: `${CONSTANTS.SMAPI.ENDPOINT}/v1/skills/${TEST_SKILL_ID}/stages/${TEST_SKILL_STAGE}/inSkillProducts?` - + `nextToken=${TEST_NEXT_TOKEN}&maxResults=${TEST_MAX_RESULTS}`, - method: CONSTANTS.HTTP_REQUEST.VERB.GET, - headers: { - authorization: TEST_ACCESS_TOKEN - }, - body: null, - json: false - } - }, - { - testCase: 'list-isp-for-skill without next token', - apiFunc: smapiClient.skill.listIspForSkill, - parameters: [TEST_SKILL_ID, TEST_SKILL_STAGE, { maxResults: TEST_MAX_RESULTS }, noop], - expectedOptions: { - url: `${CONSTANTS.SMAPI.ENDPOINT}/v1/skills/${TEST_SKILL_ID}/stages/${TEST_SKILL_STAGE}/inSkillProducts?` - + `maxResults=${TEST_MAX_RESULTS}`, - method: CONSTANTS.HTTP_REQUEST.VERB.GET, - headers: { - authorization: TEST_ACCESS_TOKEN - }, - body: null, - json: false - } - }, - { - testCase: 'list-isp-for-skill without max results', - apiFunc: smapiClient.skill.listIspForSkill, - parameters: [TEST_SKILL_ID, TEST_SKILL_STAGE, { nextToken: TEST_NEXT_TOKEN }, noop], - expectedOptions: { - url: `${CONSTANTS.SMAPI.ENDPOINT}/v1/skills/${TEST_SKILL_ID}/stages/${TEST_SKILL_STAGE}/inSkillProducts?` - + `nextToken=${TEST_NEXT_TOKEN}&maxResults=50`, - method: CONSTANTS.HTTP_REQUEST.VERB.GET, - headers: { - authorization: TEST_ACCESS_TOKEN - }, - body: null, - json: false - } - }, - { - testCase: 'list-isp-for-skill without max results nor next token', - apiFunc: smapiClient.skill.listIspForSkill, - parameters: [TEST_SKILL_ID, TEST_SKILL_STAGE, {}, noop], - expectedOptions: { - url: `${CONSTANTS.SMAPI.ENDPOINT}/v1/skills/${TEST_SKILL_ID}/stages/${TEST_SKILL_STAGE}/inSkillProducts?maxResults=50`, - method: CONSTANTS.HTTP_REQUEST.VERB.GET, - headers: { - authorization: TEST_ACCESS_TOKEN - }, - body: null, - json: false - } - }, - ].forEach(({ testCase, apiFunc, parameters, expectedOptions }) => { - it(`| call ${testCase} successfully`, (done) => { - // setup - AuthorizationController.prototype.tokenRefreshAndRead.callsArgWith(1, null, TEST_ACCESS_TOKEN); - // call - apiFunc(...parameters); - // verify - expect(AuthorizationController.prototype.tokenRefreshAndRead.called).equal(true); - expect(AuthorizationController.prototype.tokenRefreshAndRead.args[0][0]).equal(TEST_PROFILE); - expect(httpClientStub.args[0][0]).deep.equal(expectedOptions); - done(); - }); - }); + [ + { + testCase: "create-skill", + apiFunc: smapiClient.skill.createSkill, + parameters: [TEST_MANIFEST, TEST_VENDOR_ID, noop], + expectedOptions: { + url: `${CONSTANTS.SMAPI.ENDPOINT}/v1/skills/`, + method: CONSTANTS.HTTP_REQUEST.VERB.POST, + headers: { + authorization: TEST_ACCESS_TOKEN, + }, + body: { + manifest: "manifest", + vendorId: TEST_VENDOR_ID, + }, + json: true, + }, + }, + { + testCase: "delete-skill", + apiFunc: smapiClient.skill.deleteSkill, + parameters: [TEST_SKILL_ID, noop], + expectedOptions: { + url: `${CONSTANTS.SMAPI.ENDPOINT}/v1/skills/${TEST_SKILL_ID}`, + method: CONSTANTS.HTTP_REQUEST.VERB.DELETE, + headers: { + authorization: TEST_ACCESS_TOKEN, + }, + body: null, + json: false, + }, + }, + { + testCase: "list-skills", + apiFunc: smapiClient.skill.listSkills, + parameters: [TEST_VENDOR_ID, {nextToken: TEST_NEXT_TOKEN, maxResults: TEST_MAX_RESULTS}, noop], + expectedOptions: { + url: + `${CONSTANTS.SMAPI.ENDPOINT}/v1/skills?nextToken=${TEST_NEXT_TOKEN}&` + + `maxResults=${TEST_MAX_RESULTS}&vendorId=${TEST_VENDOR_ID}`, + method: CONSTANTS.HTTP_REQUEST.VERB.GET, + headers: { + authorization: TEST_ACCESS_TOKEN, + }, + body: null, + json: false, + }, + }, + { + testCase: "list-skills without maxResults", + apiFunc: smapiClient.skill.listSkills, + parameters: [TEST_VENDOR_ID, {nextToken: TEST_NEXT_TOKEN}, noop], + expectedOptions: { + url: `${CONSTANTS.SMAPI.ENDPOINT}/v1/skills?nextToken=${TEST_NEXT_TOKEN}&vendorId=${TEST_VENDOR_ID}&maxResults=50`, + method: CONSTANTS.HTTP_REQUEST.VERB.GET, + headers: { + authorization: TEST_ACCESS_TOKEN, + }, + body: null, + json: false, + }, + }, + { + testCase: "list-skills without nextToken", + apiFunc: smapiClient.skill.listSkills, + parameters: [TEST_VENDOR_ID, {maxResults: TEST_MAX_RESULTS}, noop], + expectedOptions: { + url: `${CONSTANTS.SMAPI.ENDPOINT}/v1/skills?maxResults=${TEST_MAX_RESULTS}&vendorId=${TEST_VENDOR_ID}`, + method: CONSTANTS.HTTP_REQUEST.VERB.GET, + headers: { + authorization: TEST_ACCESS_TOKEN, + }, + body: null, + json: false, + }, + }, + { + testCase: "list-skills with null query parameters", + apiFunc: smapiClient.skill.listSkills, + parameters: [TEST_VENDOR_ID, null, noop], + expectedOptions: { + url: `${CONSTANTS.SMAPI.ENDPOINT}/v1/skills?vendorId=${TEST_VENDOR_ID}&maxResults=50`, + method: CONSTANTS.HTTP_REQUEST.VERB.GET, + headers: { + authorization: TEST_ACCESS_TOKEN, + }, + body: null, + json: false, + }, + }, + { + testCase: "get-skill-status", + apiFunc: smapiClient.skill.getSkillStatus, + parameters: [TEST_SKILL_ID, null, noop], + expectedOptions: { + url: `${CONSTANTS.SMAPI.ENDPOINT}/v1/skills/${TEST_SKILL_ID}/status`, + method: CONSTANTS.HTTP_REQUEST.VERB.GET, + headers: { + authorization: TEST_ACCESS_TOKEN, + }, + body: null, + json: false, + }, + }, + { + testCase: "get-skill-status with manifest resource", + apiFunc: smapiClient.skill.getSkillStatus, + parameters: [TEST_SKILL_ID, [CONSTANTS.SKILL.RESOURCES.MANIFEST], noop], + expectedOptions: { + url: `${CONSTANTS.SMAPI.ENDPOINT}/v1/skills/${TEST_SKILL_ID}/status?resource=${CONSTANTS.SKILL.RESOURCES.MANIFEST}`, + method: CONSTANTS.HTTP_REQUEST.VERB.GET, + headers: { + authorization: TEST_ACCESS_TOKEN, + }, + body: null, + json: false, + }, + }, + { + testCase: "get-skill-status with manifest and interactionModel resource", + apiFunc: smapiClient.skill.getSkillStatus, + parameters: [TEST_SKILL_ID, [CONSTANTS.SKILL.RESOURCES.MANIFEST, CONSTANTS.SKILL.RESOURCES.INTERACTION_MODEL], noop], + expectedOptions: { + url: + `${CONSTANTS.SMAPI.ENDPOINT}/v1/skills/${TEST_SKILL_ID}/status?resource=${CONSTANTS.SKILL.RESOURCES.MANIFEST}` + + `&resource=${CONSTANTS.SKILL.RESOURCES.INTERACTION_MODEL}`, + method: CONSTANTS.HTTP_REQUEST.VERB.GET, + headers: { + authorization: TEST_ACCESS_TOKEN, + }, + body: null, + json: false, + }, + }, + { + testCase: "list-isp-for-skill", + apiFunc: smapiClient.skill.listIspForSkill, + parameters: [TEST_SKILL_ID, TEST_SKILL_STAGE, {nextToken: TEST_NEXT_TOKEN, maxResults: TEST_MAX_RESULTS}, noop], + expectedOptions: { + url: + `${CONSTANTS.SMAPI.ENDPOINT}/v1/skills/${TEST_SKILL_ID}/stages/${TEST_SKILL_STAGE}/inSkillProducts?` + + `nextToken=${TEST_NEXT_TOKEN}&maxResults=${TEST_MAX_RESULTS}`, + method: CONSTANTS.HTTP_REQUEST.VERB.GET, + headers: { + authorization: TEST_ACCESS_TOKEN, + }, + body: null, + json: false, + }, + }, + { + testCase: "list-isp-for-skill without next token", + apiFunc: smapiClient.skill.listIspForSkill, + parameters: [TEST_SKILL_ID, TEST_SKILL_STAGE, {maxResults: TEST_MAX_RESULTS}, noop], + expectedOptions: { + url: + `${CONSTANTS.SMAPI.ENDPOINT}/v1/skills/${TEST_SKILL_ID}/stages/${TEST_SKILL_STAGE}/inSkillProducts?` + + `maxResults=${TEST_MAX_RESULTS}`, + method: CONSTANTS.HTTP_REQUEST.VERB.GET, + headers: { + authorization: TEST_ACCESS_TOKEN, + }, + body: null, + json: false, + }, + }, + { + testCase: "list-isp-for-skill without max results", + apiFunc: smapiClient.skill.listIspForSkill, + parameters: [TEST_SKILL_ID, TEST_SKILL_STAGE, {nextToken: TEST_NEXT_TOKEN}, noop], + expectedOptions: { + url: + `${CONSTANTS.SMAPI.ENDPOINT}/v1/skills/${TEST_SKILL_ID}/stages/${TEST_SKILL_STAGE}/inSkillProducts?` + + `nextToken=${TEST_NEXT_TOKEN}&maxResults=50`, + method: CONSTANTS.HTTP_REQUEST.VERB.GET, + headers: { + authorization: TEST_ACCESS_TOKEN, + }, + body: null, + json: false, + }, + }, + { + testCase: "list-isp-for-skill without max results nor next token", + apiFunc: smapiClient.skill.listIspForSkill, + parameters: [TEST_SKILL_ID, TEST_SKILL_STAGE, {}, noop], + expectedOptions: { + url: `${CONSTANTS.SMAPI.ENDPOINT}/v1/skills/${TEST_SKILL_ID}/stages/${TEST_SKILL_STAGE}/inSkillProducts?maxResults=50`, + method: CONSTANTS.HTTP_REQUEST.VERB.GET, + headers: { + authorization: TEST_ACCESS_TOKEN, + }, + body: null, + json: false, + }, + }, + ].forEach(({testCase, apiFunc, parameters, expectedOptions}) => { + it(`| call ${testCase} successfully`, (done) => { + // setup + AuthorizationController.prototype.tokenRefreshAndRead.callsArgWith(1, null, TEST_ACCESS_TOKEN); + // call + apiFunc(...parameters); + // verify + expect(AuthorizationController.prototype.tokenRefreshAndRead.called).equal(true); + expect(AuthorizationController.prototype.tokenRefreshAndRead.args[0][0]).equal(TEST_PROFILE); + expect(httpClientStub.args[0][0]).deep.equal(expectedOptions); + done(); + }); + }); - afterEach(() => { - sinon.restore(); - }); + afterEach(() => { + sinon.restore(); }); + }); - describe('# skill development lifecycle related APIs', () => { - beforeEach(() => { - httpClientStub = sinon.stub(httpClient, 'request').callsFake(noop); - sinon.stub(AuthorizationController.prototype, 'tokenRefreshAndRead'); - }); + describe("# skill development lifecycle related APIs", () => { + beforeEach(() => { + sinon.restore(); + httpClientStub = sinon.stub(httpClient, "request").callsFake(noop); + sinon.stub(AuthorizationController.prototype, "tokenRefreshAndRead"); + }); - const TEST_SKILL_ID = 'skillId'; - const TEST_SKILL_STAGE = 'skillStage'; - const TEST_VALIDATION_ID = 'validationId'; - const TEST_LOCALES = ' locale1 , locale2 '; - const TEST_LOCALE = 'TEST_LOCALE'; - const TEST_START_TIME = 'TEST_START_TIME'; - const TEST_END_TIME = 'TEST_END_TIME'; - const TEST_PERIOD = 'SINGLE'; - const TEST_METRIC = 'uniqueCustomers'; - const TEST_SKILL_TYPE = 'custom'; - const TEST_INTENT = 'TEST_INTENT'; - const TEST_NEXT_TOKEN = 'TEST_NEXT_TOKEN'; - const TEST_MAX_RESULTS = 'TEST_MAX_RESULTS'; - const TEST_DEFAULT_MAX_RESULTS = '50'; + const TEST_SKILL_ID = "skillId"; + const TEST_SKILL_STAGE = "skillStage"; + const TEST_VALIDATION_ID = "validationId"; + const TEST_LOCALES = " locale1 , locale2 "; + const TEST_LOCALE = "TEST_LOCALE"; + const TEST_START_TIME = "TEST_START_TIME"; + const TEST_END_TIME = "TEST_END_TIME"; + const TEST_PERIOD = "SINGLE"; + const TEST_METRIC = "uniqueCustomers"; + const TEST_SKILL_TYPE = "custom"; + const TEST_INTENT = "TEST_INTENT"; + const TEST_NEXT_TOKEN = "TEST_NEXT_TOKEN"; + const TEST_MAX_RESULTS = "TEST_MAX_RESULTS"; + const TEST_DEFAULT_MAX_RESULTS = "50"; - [ - { - testCase: 'enable-skill', - apiFunc: smapiClient.skill.enableSkill, - parameters: [TEST_SKILL_ID, TEST_SKILL_STAGE, noop], - expectedOptions: { - url: `${CONSTANTS.SMAPI.ENDPOINT}/v1/skills/${TEST_SKILL_ID}/stages/${TEST_SKILL_STAGE}/enablement`, - method: CONSTANTS.HTTP_REQUEST.VERB.PUT, - headers: { - authorization: TEST_ACCESS_TOKEN - }, - body: null, - json: false - } - }, - { - testCase: 'disable-skill', - apiFunc: smapiClient.skill.disableSkill, - parameters: [TEST_SKILL_ID, TEST_SKILL_STAGE, noop], - expectedOptions: { - url: `${CONSTANTS.SMAPI.ENDPOINT}/v1/skills/${TEST_SKILL_ID}/stages/${TEST_SKILL_STAGE}/enablement`, - method: CONSTANTS.HTTP_REQUEST.VERB.DELETE, - headers: { - authorization: TEST_ACCESS_TOKEN - }, - body: null, - json: false - } - }, - { - testCase: 'get-skill-enablement', - apiFunc: smapiClient.skill.getSkillEnablement, - parameters: [TEST_SKILL_ID, TEST_SKILL_STAGE, noop], - expectedOptions: { - url: `${CONSTANTS.SMAPI.ENDPOINT}/v1/skills/${TEST_SKILL_ID}/stages/${TEST_SKILL_STAGE}/enablement`, - method: CONSTANTS.HTTP_REQUEST.VERB.GET, - headers: { - authorization: TEST_ACCESS_TOKEN - }, - body: null, - json: false - } - }, - { - testCase: 'validate-skill', - apiFunc: smapiClient.skill.validateSkill, - parameters: [TEST_SKILL_ID, TEST_SKILL_STAGE, TEST_LOCALES, noop], - expectedOptions: { - url: `${CONSTANTS.SMAPI.ENDPOINT}/v1/skills/${TEST_SKILL_ID}/stages/${TEST_SKILL_STAGE}/validations`, - method: CONSTANTS.HTTP_REQUEST.VERB.POST, - headers: { - authorization: TEST_ACCESS_TOKEN - }, - body: { locales: ['locale1', 'locale2'] }, - json: true - } - }, - { - testCase: 'get-validation', - apiFunc: smapiClient.skill.getValidation, - parameters: [TEST_SKILL_ID, TEST_SKILL_STAGE, TEST_VALIDATION_ID, noop], - expectedOptions: { - url: `${CONSTANTS.SMAPI.ENDPOINT}/v1/skills/${TEST_SKILL_ID}/stages/${TEST_SKILL_STAGE}/validations/${TEST_VALIDATION_ID}`, - method: CONSTANTS.HTTP_REQUEST.VERB.GET, - headers: { - authorization: TEST_ACCESS_TOKEN - }, - body: null, - json: false - } - }, - { - testCase: 'get-skill-credentials', - apiFunc: smapiClient.skill.getSkillCredentials, - parameters: [TEST_SKILL_ID, noop], - expectedOptions: { - url: `${CONSTANTS.SMAPI.ENDPOINT}/v1/skills/${TEST_SKILL_ID}/credentials`, - method: CONSTANTS.HTTP_REQUEST.VERB.GET, - headers: { - authorization: TEST_ACCESS_TOKEN - }, - body: null, - json: false - } - }, - { - testCase: 'get-metrics', - apiFunc: smapiClient.skill.getMetrics, - parameters: [TEST_SKILL_ID, TEST_START_TIME, TEST_END_TIME, TEST_PERIOD, TEST_METRIC, TEST_SKILL_STAGE, TEST_SKILL_TYPE, - TEST_INTENT, TEST_LOCALE, TEST_MAX_RESULTS, TEST_NEXT_TOKEN, noop], - expectedOptions: { - url: `${CONSTANTS.SMAPI.ENDPOINT}/v1/skills/${TEST_SKILL_ID}/metrics?startTime=${TEST_START_TIME}&endTime=${TEST_END_TIME}` - + `&period=${TEST_PERIOD}&metric=${TEST_METRIC}&stage=${TEST_SKILL_STAGE}&skillType=${TEST_SKILL_TYPE}&intent=${TEST_INTENT}` - + `&locale=${TEST_LOCALE}&maxResults=${TEST_MAX_RESULTS}&nextToken=${TEST_NEXT_TOKEN}`, - method: CONSTANTS.HTTP_REQUEST.VERB.GET, - headers: { - authorization: TEST_ACCESS_TOKEN - }, - body: null, - json: false - } - }, - { - testCase: 'get-metrics without startTime', - apiFunc: smapiClient.skill.getMetrics, - parameters: [TEST_SKILL_ID, null, TEST_END_TIME, TEST_PERIOD, TEST_METRIC, TEST_SKILL_STAGE, TEST_SKILL_TYPE, TEST_INTENT, - TEST_LOCALE, TEST_MAX_RESULTS, TEST_NEXT_TOKEN, noop], - expectedOptions: { - url: `${CONSTANTS.SMAPI.ENDPOINT}/v1/skills/${TEST_SKILL_ID}/metrics?endTime=${TEST_END_TIME}&period=${TEST_PERIOD}` - + `&metric=${TEST_METRIC}&stage=${TEST_SKILL_STAGE}&skillType=${TEST_SKILL_TYPE}&intent=${TEST_INTENT}&locale=${TEST_LOCALE}` - + `&maxResults=${TEST_MAX_RESULTS}&nextToken=${TEST_NEXT_TOKEN}`, - method: CONSTANTS.HTTP_REQUEST.VERB.GET, - headers: { - authorization: TEST_ACCESS_TOKEN - }, - body: null, - json: false - } - }, - { - testCase: 'get-metrics without endTime', - apiFunc: smapiClient.skill.getMetrics, - parameters: [TEST_SKILL_ID, TEST_START_TIME, null, TEST_PERIOD, TEST_METRIC, TEST_SKILL_STAGE, TEST_SKILL_TYPE, TEST_INTENT, - TEST_LOCALE, TEST_MAX_RESULTS, TEST_NEXT_TOKEN, noop], - expectedOptions: { - url: `${CONSTANTS.SMAPI.ENDPOINT}/v1/skills/${TEST_SKILL_ID}/metrics?startTime=${TEST_START_TIME}&period=${TEST_PERIOD}` - + `&metric=${TEST_METRIC}&stage=${TEST_SKILL_STAGE}&skillType=${TEST_SKILL_TYPE}&intent=${TEST_INTENT}&locale=${TEST_LOCALE}` - + `&maxResults=${TEST_MAX_RESULTS}&nextToken=${TEST_NEXT_TOKEN}`, - method: CONSTANTS.HTTP_REQUEST.VERB.GET, - headers: { - authorization: TEST_ACCESS_TOKEN - }, - body: null, - json: false - } - }, - { - testCase: 'get-metrics without period', - apiFunc: smapiClient.skill.getMetrics, - parameters: [TEST_SKILL_ID, TEST_START_TIME, TEST_END_TIME, null, TEST_METRIC, TEST_SKILL_STAGE, TEST_SKILL_TYPE, TEST_INTENT, - TEST_LOCALE, TEST_MAX_RESULTS, TEST_NEXT_TOKEN, noop], - expectedOptions: { - url: `${CONSTANTS.SMAPI.ENDPOINT}/v1/skills/${TEST_SKILL_ID}/metrics?startTime=${TEST_START_TIME}&endTime=${TEST_END_TIME}` - + `&metric=${TEST_METRIC}&stage=${TEST_SKILL_STAGE}&skillType=${TEST_SKILL_TYPE}&intent=${TEST_INTENT}&locale=${TEST_LOCALE}` - + `&maxResults=${TEST_MAX_RESULTS}&nextToken=${TEST_NEXT_TOKEN}`, - method: CONSTANTS.HTTP_REQUEST.VERB.GET, - headers: { - authorization: TEST_ACCESS_TOKEN - }, - body: null, - json: false - } - }, - { - testCase: 'get-metrics without metric', - apiFunc: smapiClient.skill.getMetrics, - parameters: [TEST_SKILL_ID, TEST_START_TIME, TEST_END_TIME, TEST_PERIOD, null, TEST_SKILL_STAGE, TEST_SKILL_TYPE, - TEST_INTENT, TEST_LOCALE, TEST_MAX_RESULTS, TEST_NEXT_TOKEN, noop], - expectedOptions: { - url: `${CONSTANTS.SMAPI.ENDPOINT}/v1/skills/${TEST_SKILL_ID}/metrics?startTime=${TEST_START_TIME}&endTime=${TEST_END_TIME}` - + `&period=${TEST_PERIOD}&stage=${TEST_SKILL_STAGE}&skillType=${TEST_SKILL_TYPE}&intent=${TEST_INTENT}&locale=${TEST_LOCALE}` - + `&maxResults=${TEST_MAX_RESULTS}&nextToken=${TEST_NEXT_TOKEN}`, - method: CONSTANTS.HTTP_REQUEST.VERB.GET, - headers: { - authorization: TEST_ACCESS_TOKEN - }, - body: null, - json: false - } - }, - { - testCase: 'get-metrics without stage', - apiFunc: smapiClient.skill.getMetrics, - parameters: [TEST_SKILL_ID, TEST_START_TIME, TEST_END_TIME, TEST_PERIOD, TEST_METRIC, null, TEST_SKILL_TYPE, TEST_INTENT, - TEST_LOCALE, TEST_MAX_RESULTS, TEST_NEXT_TOKEN, noop], - expectedOptions: { - url: `${CONSTANTS.SMAPI.ENDPOINT}/v1/skills/${TEST_SKILL_ID}/metrics?startTime=${TEST_START_TIME}&endTime=${TEST_END_TIME}` - + `&period=${TEST_PERIOD}&metric=${TEST_METRIC}&skillType=${TEST_SKILL_TYPE}&intent=${TEST_INTENT}&locale=${TEST_LOCALE}` - + `&maxResults=${TEST_MAX_RESULTS}&nextToken=${TEST_NEXT_TOKEN}`, - method: CONSTANTS.HTTP_REQUEST.VERB.GET, - headers: { - authorization: TEST_ACCESS_TOKEN - }, - body: null, - json: false - } - }, - { - testCase: 'get-metrics without skillType', - apiFunc: smapiClient.skill.getMetrics, - parameters: [TEST_SKILL_ID, TEST_START_TIME, TEST_END_TIME, TEST_PERIOD, TEST_METRIC, TEST_SKILL_STAGE, null, TEST_INTENT, - TEST_LOCALE, TEST_MAX_RESULTS, TEST_NEXT_TOKEN, noop], - expectedOptions: { - url: `${CONSTANTS.SMAPI.ENDPOINT}/v1/skills/${TEST_SKILL_ID}/metrics?startTime=${TEST_START_TIME}&endTime=${TEST_END_TIME}` - + `&period=${TEST_PERIOD}&metric=${TEST_METRIC}&stage=${TEST_SKILL_STAGE}&intent=${TEST_INTENT}&locale=${TEST_LOCALE}` - + `&maxResults=${TEST_MAX_RESULTS}&nextToken=${TEST_NEXT_TOKEN}`, - method: CONSTANTS.HTTP_REQUEST.VERB.GET, - headers: { - authorization: TEST_ACCESS_TOKEN - }, - body: null, - json: false - } - }, - { - testCase: 'get-metrics without intent', - apiFunc: smapiClient.skill.getMetrics, - parameters: [TEST_SKILL_ID, TEST_START_TIME, TEST_END_TIME, TEST_PERIOD, TEST_METRIC, TEST_SKILL_STAGE, TEST_SKILL_TYPE, - null, TEST_LOCALE, TEST_MAX_RESULTS, TEST_NEXT_TOKEN, noop], - expectedOptions: { - url: `${CONSTANTS.SMAPI.ENDPOINT}/v1/skills/${TEST_SKILL_ID}/metrics?startTime=${TEST_START_TIME}&endTime=${TEST_END_TIME}` - + `&period=${TEST_PERIOD}&metric=${TEST_METRIC}&stage=${TEST_SKILL_STAGE}&skillType=${TEST_SKILL_TYPE}&locale=${TEST_LOCALE}` - + `&maxResults=${TEST_MAX_RESULTS}&nextToken=${TEST_NEXT_TOKEN}`, - method: CONSTANTS.HTTP_REQUEST.VERB.GET, - headers: { - authorization: TEST_ACCESS_TOKEN - }, - body: null, - json: false - } - }, - { - testCase: 'get-metrics without locale', - apiFunc: smapiClient.skill.getMetrics, - parameters: [TEST_SKILL_ID, TEST_START_TIME, TEST_END_TIME, TEST_PERIOD, TEST_METRIC, TEST_SKILL_STAGE, TEST_SKILL_TYPE, - TEST_INTENT, null, TEST_MAX_RESULTS, TEST_NEXT_TOKEN, noop], - expectedOptions: { - url: `${CONSTANTS.SMAPI.ENDPOINT}/v1/skills/${TEST_SKILL_ID}/metrics?startTime=${TEST_START_TIME}&endTime=${TEST_END_TIME}` - + `&period=${TEST_PERIOD}&metric=${TEST_METRIC}&stage=${TEST_SKILL_STAGE}&skillType=${TEST_SKILL_TYPE}&intent=${TEST_INTENT}` - + `&maxResults=${TEST_MAX_RESULTS}&nextToken=${TEST_NEXT_TOKEN}`, - method: CONSTANTS.HTTP_REQUEST.VERB.GET, - headers: { - authorization: TEST_ACCESS_TOKEN - }, - body: null, - json: false - } - }, - { - testCase: 'get-metrics without maxResults', - apiFunc: smapiClient.skill.getMetrics, - parameters: [TEST_SKILL_ID, TEST_START_TIME, TEST_END_TIME, TEST_PERIOD, TEST_METRIC, TEST_SKILL_STAGE, TEST_SKILL_TYPE, - TEST_INTENT, TEST_LOCALE, null, TEST_NEXT_TOKEN, noop], - expectedOptions: { - url: `${CONSTANTS.SMAPI.ENDPOINT}/v1/skills/${TEST_SKILL_ID}/metrics?startTime=${TEST_START_TIME}&endTime=${TEST_END_TIME}` - + `&period=${TEST_PERIOD}&metric=${TEST_METRIC}&stage=${TEST_SKILL_STAGE}&skillType=${TEST_SKILL_TYPE}&intent=${TEST_INTENT}` - + `&locale=${TEST_LOCALE}&maxResults=${TEST_DEFAULT_MAX_RESULTS}&nextToken=${TEST_NEXT_TOKEN}`, - method: CONSTANTS.HTTP_REQUEST.VERB.GET, - headers: { - authorization: TEST_ACCESS_TOKEN - }, - body: null, - json: false - } - }, - { - testCase: 'get-metrics without nextToken', - apiFunc: smapiClient.skill.getMetrics, - parameters: [TEST_SKILL_ID, TEST_START_TIME, TEST_END_TIME, TEST_PERIOD, TEST_METRIC, TEST_SKILL_STAGE, TEST_SKILL_TYPE, - TEST_INTENT, TEST_LOCALE, TEST_MAX_RESULTS, null, noop], - expectedOptions: { - url: `${CONSTANTS.SMAPI.ENDPOINT}/v1/skills/${TEST_SKILL_ID}/metrics?startTime=${TEST_START_TIME}&endTime=${TEST_END_TIME}` - + `&period=${TEST_PERIOD}&metric=${TEST_METRIC}&stage=${TEST_SKILL_STAGE}&skillType=${TEST_SKILL_TYPE}&intent=${TEST_INTENT}` - + `&locale=${TEST_LOCALE}&maxResults=${TEST_MAX_RESULTS}`, - method: CONSTANTS.HTTP_REQUEST.VERB.GET, - headers: { - authorization: TEST_ACCESS_TOKEN - }, - body: null, - json: false - } - }, - ].forEach(({ testCase, apiFunc, parameters, expectedOptions }) => { - it(`| call ${testCase} successfully`, (done) => { - // setup - AuthorizationController.prototype.tokenRefreshAndRead.callsArgWith(1, null, TEST_ACCESS_TOKEN); - // call - apiFunc(...parameters); - // verify - expect(AuthorizationController.prototype.tokenRefreshAndRead.called).equal(true); - expect(AuthorizationController.prototype.tokenRefreshAndRead.args[0][0]).equal(TEST_PROFILE); - expect(httpClientStub.args[0][0]).deep.equal(expectedOptions); - done(); - }); - }); + [ + { + testCase: "enable-skill", + apiFunc: smapiClient.skill.enableSkill, + parameters: [TEST_SKILL_ID, TEST_SKILL_STAGE, noop], + expectedOptions: { + url: `${CONSTANTS.SMAPI.ENDPOINT}/v1/skills/${TEST_SKILL_ID}/stages/${TEST_SKILL_STAGE}/enablement`, + method: CONSTANTS.HTTP_REQUEST.VERB.PUT, + headers: { + authorization: TEST_ACCESS_TOKEN, + }, + body: null, + json: false, + }, + }, + { + testCase: "disable-skill", + apiFunc: smapiClient.skill.disableSkill, + parameters: [TEST_SKILL_ID, TEST_SKILL_STAGE, noop], + expectedOptions: { + url: `${CONSTANTS.SMAPI.ENDPOINT}/v1/skills/${TEST_SKILL_ID}/stages/${TEST_SKILL_STAGE}/enablement`, + method: CONSTANTS.HTTP_REQUEST.VERB.DELETE, + headers: { + authorization: TEST_ACCESS_TOKEN, + }, + body: null, + json: false, + }, + }, + { + testCase: "get-skill-enablement", + apiFunc: smapiClient.skill.getSkillEnablement, + parameters: [TEST_SKILL_ID, TEST_SKILL_STAGE, noop], + expectedOptions: { + url: `${CONSTANTS.SMAPI.ENDPOINT}/v1/skills/${TEST_SKILL_ID}/stages/${TEST_SKILL_STAGE}/enablement`, + method: CONSTANTS.HTTP_REQUEST.VERB.GET, + headers: { + authorization: TEST_ACCESS_TOKEN, + }, + body: null, + json: false, + }, + }, + { + testCase: "validate-skill", + apiFunc: smapiClient.skill.validateSkill, + parameters: [TEST_SKILL_ID, TEST_SKILL_STAGE, TEST_LOCALES, noop], + expectedOptions: { + url: `${CONSTANTS.SMAPI.ENDPOINT}/v1/skills/${TEST_SKILL_ID}/stages/${TEST_SKILL_STAGE}/validations`, + method: CONSTANTS.HTTP_REQUEST.VERB.POST, + headers: { + authorization: TEST_ACCESS_TOKEN, + }, + body: {locales: ["locale1", "locale2"]}, + json: true, + }, + }, + { + testCase: "get-validation", + apiFunc: smapiClient.skill.getValidation, + parameters: [TEST_SKILL_ID, TEST_SKILL_STAGE, TEST_VALIDATION_ID, noop], + expectedOptions: { + url: `${CONSTANTS.SMAPI.ENDPOINT}/v1/skills/${TEST_SKILL_ID}/stages/${TEST_SKILL_STAGE}/validations/${TEST_VALIDATION_ID}`, + method: CONSTANTS.HTTP_REQUEST.VERB.GET, + headers: { + authorization: TEST_ACCESS_TOKEN, + }, + body: null, + json: false, + }, + }, + { + testCase: "get-skill-credentials", + apiFunc: smapiClient.skill.getSkillCredentials, + parameters: [TEST_SKILL_ID, noop], + expectedOptions: { + url: `${CONSTANTS.SMAPI.ENDPOINT}/v1/skills/${TEST_SKILL_ID}/credentials`, + method: CONSTANTS.HTTP_REQUEST.VERB.GET, + headers: { + authorization: TEST_ACCESS_TOKEN, + }, + body: null, + json: false, + }, + }, + { + testCase: "get-metrics", + apiFunc: smapiClient.skill.getMetrics, + parameters: [ + TEST_SKILL_ID, + TEST_START_TIME, + TEST_END_TIME, + TEST_PERIOD, + TEST_METRIC, + TEST_SKILL_STAGE, + TEST_SKILL_TYPE, + TEST_INTENT, + TEST_LOCALE, + TEST_MAX_RESULTS, + TEST_NEXT_TOKEN, + noop, + ], + expectedOptions: { + url: + `${CONSTANTS.SMAPI.ENDPOINT}/v1/skills/${TEST_SKILL_ID}/metrics?startTime=${TEST_START_TIME}&endTime=${TEST_END_TIME}` + + `&period=${TEST_PERIOD}&metric=${TEST_METRIC}&stage=${TEST_SKILL_STAGE}&skillType=${TEST_SKILL_TYPE}&intent=${TEST_INTENT}` + + `&locale=${TEST_LOCALE}&maxResults=${TEST_MAX_RESULTS}&nextToken=${TEST_NEXT_TOKEN}`, + method: CONSTANTS.HTTP_REQUEST.VERB.GET, + headers: { + authorization: TEST_ACCESS_TOKEN, + }, + body: null, + json: false, + }, + }, + { + testCase: "get-metrics without startTime", + apiFunc: smapiClient.skill.getMetrics, + parameters: [ + TEST_SKILL_ID, + null, + TEST_END_TIME, + TEST_PERIOD, + TEST_METRIC, + TEST_SKILL_STAGE, + TEST_SKILL_TYPE, + TEST_INTENT, + TEST_LOCALE, + TEST_MAX_RESULTS, + TEST_NEXT_TOKEN, + noop, + ], + expectedOptions: { + url: + `${CONSTANTS.SMAPI.ENDPOINT}/v1/skills/${TEST_SKILL_ID}/metrics?endTime=${TEST_END_TIME}&period=${TEST_PERIOD}` + + `&metric=${TEST_METRIC}&stage=${TEST_SKILL_STAGE}&skillType=${TEST_SKILL_TYPE}&intent=${TEST_INTENT}&locale=${TEST_LOCALE}` + + `&maxResults=${TEST_MAX_RESULTS}&nextToken=${TEST_NEXT_TOKEN}`, + method: CONSTANTS.HTTP_REQUEST.VERB.GET, + headers: { + authorization: TEST_ACCESS_TOKEN, + }, + body: null, + json: false, + }, + }, + { + testCase: "get-metrics without endTime", + apiFunc: smapiClient.skill.getMetrics, + parameters: [ + TEST_SKILL_ID, + TEST_START_TIME, + null, + TEST_PERIOD, + TEST_METRIC, + TEST_SKILL_STAGE, + TEST_SKILL_TYPE, + TEST_INTENT, + TEST_LOCALE, + TEST_MAX_RESULTS, + TEST_NEXT_TOKEN, + noop, + ], + expectedOptions: { + url: + `${CONSTANTS.SMAPI.ENDPOINT}/v1/skills/${TEST_SKILL_ID}/metrics?startTime=${TEST_START_TIME}&period=${TEST_PERIOD}` + + `&metric=${TEST_METRIC}&stage=${TEST_SKILL_STAGE}&skillType=${TEST_SKILL_TYPE}&intent=${TEST_INTENT}&locale=${TEST_LOCALE}` + + `&maxResults=${TEST_MAX_RESULTS}&nextToken=${TEST_NEXT_TOKEN}`, + method: CONSTANTS.HTTP_REQUEST.VERB.GET, + headers: { + authorization: TEST_ACCESS_TOKEN, + }, + body: null, + json: false, + }, + }, + { + testCase: "get-metrics without period", + apiFunc: smapiClient.skill.getMetrics, + parameters: [ + TEST_SKILL_ID, + TEST_START_TIME, + TEST_END_TIME, + null, + TEST_METRIC, + TEST_SKILL_STAGE, + TEST_SKILL_TYPE, + TEST_INTENT, + TEST_LOCALE, + TEST_MAX_RESULTS, + TEST_NEXT_TOKEN, + noop, + ], + expectedOptions: { + url: + `${CONSTANTS.SMAPI.ENDPOINT}/v1/skills/${TEST_SKILL_ID}/metrics?startTime=${TEST_START_TIME}&endTime=${TEST_END_TIME}` + + `&metric=${TEST_METRIC}&stage=${TEST_SKILL_STAGE}&skillType=${TEST_SKILL_TYPE}&intent=${TEST_INTENT}&locale=${TEST_LOCALE}` + + `&maxResults=${TEST_MAX_RESULTS}&nextToken=${TEST_NEXT_TOKEN}`, + method: CONSTANTS.HTTP_REQUEST.VERB.GET, + headers: { + authorization: TEST_ACCESS_TOKEN, + }, + body: null, + json: false, + }, + }, + { + testCase: "get-metrics without metric", + apiFunc: smapiClient.skill.getMetrics, + parameters: [ + TEST_SKILL_ID, + TEST_START_TIME, + TEST_END_TIME, + TEST_PERIOD, + null, + TEST_SKILL_STAGE, + TEST_SKILL_TYPE, + TEST_INTENT, + TEST_LOCALE, + TEST_MAX_RESULTS, + TEST_NEXT_TOKEN, + noop, + ], + expectedOptions: { + url: + `${CONSTANTS.SMAPI.ENDPOINT}/v1/skills/${TEST_SKILL_ID}/metrics?startTime=${TEST_START_TIME}&endTime=${TEST_END_TIME}` + + `&period=${TEST_PERIOD}&stage=${TEST_SKILL_STAGE}&skillType=${TEST_SKILL_TYPE}&intent=${TEST_INTENT}&locale=${TEST_LOCALE}` + + `&maxResults=${TEST_MAX_RESULTS}&nextToken=${TEST_NEXT_TOKEN}`, + method: CONSTANTS.HTTP_REQUEST.VERB.GET, + headers: { + authorization: TEST_ACCESS_TOKEN, + }, + body: null, + json: false, + }, + }, + { + testCase: "get-metrics without stage", + apiFunc: smapiClient.skill.getMetrics, + parameters: [ + TEST_SKILL_ID, + TEST_START_TIME, + TEST_END_TIME, + TEST_PERIOD, + TEST_METRIC, + null, + TEST_SKILL_TYPE, + TEST_INTENT, + TEST_LOCALE, + TEST_MAX_RESULTS, + TEST_NEXT_TOKEN, + noop, + ], + expectedOptions: { + url: + `${CONSTANTS.SMAPI.ENDPOINT}/v1/skills/${TEST_SKILL_ID}/metrics?startTime=${TEST_START_TIME}&endTime=${TEST_END_TIME}` + + `&period=${TEST_PERIOD}&metric=${TEST_METRIC}&skillType=${TEST_SKILL_TYPE}&intent=${TEST_INTENT}&locale=${TEST_LOCALE}` + + `&maxResults=${TEST_MAX_RESULTS}&nextToken=${TEST_NEXT_TOKEN}`, + method: CONSTANTS.HTTP_REQUEST.VERB.GET, + headers: { + authorization: TEST_ACCESS_TOKEN, + }, + body: null, + json: false, + }, + }, + { + testCase: "get-metrics without skillType", + apiFunc: smapiClient.skill.getMetrics, + parameters: [ + TEST_SKILL_ID, + TEST_START_TIME, + TEST_END_TIME, + TEST_PERIOD, + TEST_METRIC, + TEST_SKILL_STAGE, + null, + TEST_INTENT, + TEST_LOCALE, + TEST_MAX_RESULTS, + TEST_NEXT_TOKEN, + noop, + ], + expectedOptions: { + url: + `${CONSTANTS.SMAPI.ENDPOINT}/v1/skills/${TEST_SKILL_ID}/metrics?startTime=${TEST_START_TIME}&endTime=${TEST_END_TIME}` + + `&period=${TEST_PERIOD}&metric=${TEST_METRIC}&stage=${TEST_SKILL_STAGE}&intent=${TEST_INTENT}&locale=${TEST_LOCALE}` + + `&maxResults=${TEST_MAX_RESULTS}&nextToken=${TEST_NEXT_TOKEN}`, + method: CONSTANTS.HTTP_REQUEST.VERB.GET, + headers: { + authorization: TEST_ACCESS_TOKEN, + }, + body: null, + json: false, + }, + }, + { + testCase: "get-metrics without intent", + apiFunc: smapiClient.skill.getMetrics, + parameters: [ + TEST_SKILL_ID, + TEST_START_TIME, + TEST_END_TIME, + TEST_PERIOD, + TEST_METRIC, + TEST_SKILL_STAGE, + TEST_SKILL_TYPE, + null, + TEST_LOCALE, + TEST_MAX_RESULTS, + TEST_NEXT_TOKEN, + noop, + ], + expectedOptions: { + url: + `${CONSTANTS.SMAPI.ENDPOINT}/v1/skills/${TEST_SKILL_ID}/metrics?startTime=${TEST_START_TIME}&endTime=${TEST_END_TIME}` + + `&period=${TEST_PERIOD}&metric=${TEST_METRIC}&stage=${TEST_SKILL_STAGE}&skillType=${TEST_SKILL_TYPE}&locale=${TEST_LOCALE}` + + `&maxResults=${TEST_MAX_RESULTS}&nextToken=${TEST_NEXT_TOKEN}`, + method: CONSTANTS.HTTP_REQUEST.VERB.GET, + headers: { + authorization: TEST_ACCESS_TOKEN, + }, + body: null, + json: false, + }, + }, + { + testCase: "get-metrics without locale", + apiFunc: smapiClient.skill.getMetrics, + parameters: [ + TEST_SKILL_ID, + TEST_START_TIME, + TEST_END_TIME, + TEST_PERIOD, + TEST_METRIC, + TEST_SKILL_STAGE, + TEST_SKILL_TYPE, + TEST_INTENT, + null, + TEST_MAX_RESULTS, + TEST_NEXT_TOKEN, + noop, + ], + expectedOptions: { + url: + `${CONSTANTS.SMAPI.ENDPOINT}/v1/skills/${TEST_SKILL_ID}/metrics?startTime=${TEST_START_TIME}&endTime=${TEST_END_TIME}` + + `&period=${TEST_PERIOD}&metric=${TEST_METRIC}&stage=${TEST_SKILL_STAGE}&skillType=${TEST_SKILL_TYPE}&intent=${TEST_INTENT}` + + `&maxResults=${TEST_MAX_RESULTS}&nextToken=${TEST_NEXT_TOKEN}`, + method: CONSTANTS.HTTP_REQUEST.VERB.GET, + headers: { + authorization: TEST_ACCESS_TOKEN, + }, + body: null, + json: false, + }, + }, + { + testCase: "get-metrics without maxResults", + apiFunc: smapiClient.skill.getMetrics, + parameters: [ + TEST_SKILL_ID, + TEST_START_TIME, + TEST_END_TIME, + TEST_PERIOD, + TEST_METRIC, + TEST_SKILL_STAGE, + TEST_SKILL_TYPE, + TEST_INTENT, + TEST_LOCALE, + null, + TEST_NEXT_TOKEN, + noop, + ], + expectedOptions: { + url: + `${CONSTANTS.SMAPI.ENDPOINT}/v1/skills/${TEST_SKILL_ID}/metrics?startTime=${TEST_START_TIME}&endTime=${TEST_END_TIME}` + + `&period=${TEST_PERIOD}&metric=${TEST_METRIC}&stage=${TEST_SKILL_STAGE}&skillType=${TEST_SKILL_TYPE}&intent=${TEST_INTENT}` + + `&locale=${TEST_LOCALE}&maxResults=${TEST_DEFAULT_MAX_RESULTS}&nextToken=${TEST_NEXT_TOKEN}`, + method: CONSTANTS.HTTP_REQUEST.VERB.GET, + headers: { + authorization: TEST_ACCESS_TOKEN, + }, + body: null, + json: false, + }, + }, + { + testCase: "get-metrics without nextToken", + apiFunc: smapiClient.skill.getMetrics, + parameters: [ + TEST_SKILL_ID, + TEST_START_TIME, + TEST_END_TIME, + TEST_PERIOD, + TEST_METRIC, + TEST_SKILL_STAGE, + TEST_SKILL_TYPE, + TEST_INTENT, + TEST_LOCALE, + TEST_MAX_RESULTS, + null, + noop, + ], + expectedOptions: { + url: + `${CONSTANTS.SMAPI.ENDPOINT}/v1/skills/${TEST_SKILL_ID}/metrics?startTime=${TEST_START_TIME}&endTime=${TEST_END_TIME}` + + `&period=${TEST_PERIOD}&metric=${TEST_METRIC}&stage=${TEST_SKILL_STAGE}&skillType=${TEST_SKILL_TYPE}&intent=${TEST_INTENT}` + + `&locale=${TEST_LOCALE}&maxResults=${TEST_MAX_RESULTS}`, + method: CONSTANTS.HTTP_REQUEST.VERB.GET, + headers: { + authorization: TEST_ACCESS_TOKEN, + }, + body: null, + json: false, + }, + }, + ].forEach(({testCase, apiFunc, parameters, expectedOptions}) => { + it(`| call ${testCase} successfully`, (done) => { + // setup + AuthorizationController.prototype.tokenRefreshAndRead.callsArgWith(1, null, TEST_ACCESS_TOKEN); + // call + apiFunc(...parameters); + // verify + expect(AuthorizationController.prototype.tokenRefreshAndRead.called).equal(true); + expect(AuthorizationController.prototype.tokenRefreshAndRead.args[0][0]).equal(TEST_PROFILE); + expect(httpClientStub.args[0][0]).deep.equal(expectedOptions); + done(); + }); + }); - afterEach(() => { - sinon.restore(); - }); + afterEach(() => { + sinon.restore(); }); + }); }; diff --git a/test/unit/clients/smapi-client-test/resources/task.js b/test/unit/clients/smapi-client-test/resources/task.js index da12d5c8..a2f257f6 100644 --- a/test/unit/clients/smapi-client-test/resources/task.js +++ b/test/unit/clients/smapi-client-test/resources/task.js @@ -1,120 +1,139 @@ -const { expect } = require('chai'); -const sinon = require('sinon'); +const {expect} = require("chai"); +const sinon = require("sinon"); -const httpClient = require('@src/clients/http-client'); -const AuthorizationController = require('@src/controllers/authorization-controller'); -const CONSTANTS = require('@src/utils/constants'); +const httpClient = require("../../../../../lib/clients/http-client"); +const AuthorizationController = require("../../../../../lib/controllers/authorization-controller"); +const CONSTANTS = require("../../../../../lib/utils/constants"); const noop = () => {}; module.exports = (smapiClient) => { - describe('# task get and search APIs', () => { - let httpClientStub; - beforeEach(() => { - httpClientStub = sinon.stub(httpClient, 'request').callsFake(noop); - sinon.stub(AuthorizationController.prototype, 'tokenRefreshAndRead'); - }); + describe("# task get and search APIs", () => { + let httpClientStub; + beforeEach(() => { + httpClientStub = sinon.stub(httpClient, "request").callsFake(noop); + sinon.stub(AuthorizationController.prototype, "tokenRefreshAndRead"); + }); - const TEST_SKILL_ID = 'skillId'; - const TEST_TASK_NAME = 'taskName'; - const TEST_TASK_VERSION = 'taskVersion'; - const TEST_SINGLE_KEYWORD = 'KEYWORD'; - const TEST_MULTIPLE_KEYWORDS = 'KEYWORD1,KEYWORD2'; - const TEST_MULTIPLE_KEYWORDS_QUERY_PARAM = 'KEYWORD1%2CKEYWORD2'; - const TEST_MULTIPLE_KEYWORDS_INCLUDING_SPACES = 'KEYWORD1,KEYWORD 2'; - const TEST_MULTIPLE_KEYWORDS_INCLUDING_SPACES_QUERY_PARAM = 'KEYWORD1%2CKEYWORD%202'; - const TEST_PROVIDER_SKILL_ID = 'providerSkillId'; - const TEST_MAX_RESULTS = 'maxResults'; - const TEST_NEXT_TOKEN = 'nextToken'; - const TEST_PROFILE = 'testProfile'; - const TEST_ACCESS_TOKEN = 'access_token'; + const TEST_SKILL_ID = "skillId"; + const TEST_TASK_NAME = "taskName"; + const TEST_TASK_VERSION = "taskVersion"; + const TEST_SINGLE_KEYWORD = "KEYWORD"; + const TEST_MULTIPLE_KEYWORDS = "KEYWORD1,KEYWORD2"; + const TEST_MULTIPLE_KEYWORDS_QUERY_PARAM = "KEYWORD1%2CKEYWORD2"; + const TEST_MULTIPLE_KEYWORDS_INCLUDING_SPACES = "KEYWORD1,KEYWORD 2"; + const TEST_MULTIPLE_KEYWORDS_INCLUDING_SPACES_QUERY_PARAM = "KEYWORD1%2CKEYWORD%202"; + const TEST_PROVIDER_SKILL_ID = "providerSkillId"; + const TEST_MAX_RESULTS = "maxResults"; + const TEST_NEXT_TOKEN = "nextToken"; + const TEST_PROFILE = "testProfile"; + const TEST_ACCESS_TOKEN = "access_token"; - [ - { - testCase: 'get-task', - apiFunc: smapiClient.task.getTask, - parameters: [TEST_SKILL_ID, TEST_TASK_NAME, TEST_TASK_VERSION, noop], - expectedOptions: { - url: `${CONSTANTS.SMAPI.ENDPOINT}/${CONSTANTS.SMAPI.VERSION.V1}` - + `/tasks/${TEST_TASK_NAME}/versions/${TEST_TASK_VERSION}/?skillId=${TEST_SKILL_ID}`, - method: CONSTANTS.HTTP_REQUEST.VERB.GET, - headers: { - authorization: TEST_ACCESS_TOKEN - }, - body: null, - json: false - } - }, - { - testCase: 'search-task single keyword', - apiFunc: smapiClient.task.searchTask, - parameters: [TEST_SKILL_ID, TEST_SINGLE_KEYWORD, TEST_PROVIDER_SKILL_ID, - { maxResults: TEST_MAX_RESULTS, nextToken: TEST_NEXT_TOKEN }, noop], - expectedOptions: { - url: `${CONSTANTS.SMAPI.ENDPOINT}/${CONSTANTS.SMAPI.VERSION.V1}/tasks/?` - + `maxResults=${TEST_MAX_RESULTS}&nextToken=${TEST_NEXT_TOKEN}&` - + `skillId=${TEST_SKILL_ID}&keywords=${TEST_SINGLE_KEYWORD}&providerSkillId=${TEST_PROVIDER_SKILL_ID}`, - method: CONSTANTS.HTTP_REQUEST.VERB.GET, - headers: { - authorization: TEST_ACCESS_TOKEN - }, - body: null, - json: false - } - }, - { - testCase: 'search-task multiple keywords', - apiFunc: smapiClient.task.searchTask, - parameters: [TEST_SKILL_ID, TEST_MULTIPLE_KEYWORDS, TEST_PROVIDER_SKILL_ID, - { maxResults: TEST_MAX_RESULTS, nextToken: TEST_NEXT_TOKEN }, noop], - expectedOptions: { - url: `${CONSTANTS.SMAPI.ENDPOINT}/${CONSTANTS.SMAPI.VERSION.V1}/tasks/?` - + `maxResults=${TEST_MAX_RESULTS}&nextToken=${TEST_NEXT_TOKEN}&` - + `skillId=${TEST_SKILL_ID}&keywords=${TEST_MULTIPLE_KEYWORDS_QUERY_PARAM}&providerSkillId=${TEST_PROVIDER_SKILL_ID}`, - method: CONSTANTS.HTTP_REQUEST.VERB.GET, - headers: { - authorization: TEST_ACCESS_TOKEN - }, - body: null, - json: false - } - }, - { - testCase: 'search-task multiple keywords including spaces', - apiFunc: smapiClient.task.searchTask, - parameters: [TEST_SKILL_ID, TEST_MULTIPLE_KEYWORDS_INCLUDING_SPACES, TEST_PROVIDER_SKILL_ID, - { maxResults: TEST_MAX_RESULTS, nextToken: TEST_NEXT_TOKEN }, noop], - expectedOptions: { - url: `${CONSTANTS.SMAPI.ENDPOINT}/${CONSTANTS.SMAPI.VERSION.V1}/tasks/?` - + `maxResults=${TEST_MAX_RESULTS}&nextToken=${TEST_NEXT_TOKEN}&` - + `skillId=${TEST_SKILL_ID}&keywords=${TEST_MULTIPLE_KEYWORDS_INCLUDING_SPACES_QUERY_PARAM}&` - + `providerSkillId=${TEST_PROVIDER_SKILL_ID}`, - method: CONSTANTS.HTTP_REQUEST.VERB.GET, - headers: { - authorization: TEST_ACCESS_TOKEN - }, - body: null, - json: false - } - } - ].forEach(({ testCase, apiFunc, parameters, expectedOptions }) => { - it(`| call ${testCase} successfully`, (done) => { - // setup - AuthorizationController.prototype.tokenRefreshAndRead.callsArgWith(1, null, TEST_ACCESS_TOKEN); + [ + { + testCase: "get-task", + apiFunc: smapiClient.task.getTask, + parameters: [TEST_SKILL_ID, TEST_TASK_NAME, TEST_TASK_VERSION, noop], + expectedOptions: { + url: + `${CONSTANTS.SMAPI.ENDPOINT}/${CONSTANTS.SMAPI.VERSION.V1}` + + `/tasks/${TEST_TASK_NAME}/versions/${TEST_TASK_VERSION}/?skillId=${TEST_SKILL_ID}`, + method: CONSTANTS.HTTP_REQUEST.VERB.GET, + headers: { + authorization: TEST_ACCESS_TOKEN, + }, + body: null, + json: false, + }, + }, + { + testCase: "search-task single keyword", + apiFunc: smapiClient.task.searchTask, + parameters: [ + TEST_SKILL_ID, + TEST_SINGLE_KEYWORD, + TEST_PROVIDER_SKILL_ID, + {maxResults: TEST_MAX_RESULTS, nextToken: TEST_NEXT_TOKEN}, + noop, + ], + expectedOptions: { + url: + `${CONSTANTS.SMAPI.ENDPOINT}/${CONSTANTS.SMAPI.VERSION.V1}/tasks/?` + + `maxResults=${TEST_MAX_RESULTS}&nextToken=${TEST_NEXT_TOKEN}&` + + `skillId=${TEST_SKILL_ID}&keywords=${TEST_SINGLE_KEYWORD}&providerSkillId=${TEST_PROVIDER_SKILL_ID}`, + method: CONSTANTS.HTTP_REQUEST.VERB.GET, + headers: { + authorization: TEST_ACCESS_TOKEN, + }, + body: null, + json: false, + }, + }, + { + testCase: "search-task multiple keywords", + apiFunc: smapiClient.task.searchTask, + parameters: [ + TEST_SKILL_ID, + TEST_MULTIPLE_KEYWORDS, + TEST_PROVIDER_SKILL_ID, + {maxResults: TEST_MAX_RESULTS, nextToken: TEST_NEXT_TOKEN}, + noop, + ], + expectedOptions: { + url: + `${CONSTANTS.SMAPI.ENDPOINT}/${CONSTANTS.SMAPI.VERSION.V1}/tasks/?` + + `maxResults=${TEST_MAX_RESULTS}&nextToken=${TEST_NEXT_TOKEN}&` + + `skillId=${TEST_SKILL_ID}&keywords=${TEST_MULTIPLE_KEYWORDS_QUERY_PARAM}&providerSkillId=${TEST_PROVIDER_SKILL_ID}`, + method: CONSTANTS.HTTP_REQUEST.VERB.GET, + headers: { + authorization: TEST_ACCESS_TOKEN, + }, + body: null, + json: false, + }, + }, + { + testCase: "search-task multiple keywords including spaces", + apiFunc: smapiClient.task.searchTask, + parameters: [ + TEST_SKILL_ID, + TEST_MULTIPLE_KEYWORDS_INCLUDING_SPACES, + TEST_PROVIDER_SKILL_ID, + {maxResults: TEST_MAX_RESULTS, nextToken: TEST_NEXT_TOKEN}, + noop, + ], + expectedOptions: { + url: + `${CONSTANTS.SMAPI.ENDPOINT}/${CONSTANTS.SMAPI.VERSION.V1}/tasks/?` + + `maxResults=${TEST_MAX_RESULTS}&nextToken=${TEST_NEXT_TOKEN}&` + + `skillId=${TEST_SKILL_ID}&keywords=${TEST_MULTIPLE_KEYWORDS_INCLUDING_SPACES_QUERY_PARAM}&` + + `providerSkillId=${TEST_PROVIDER_SKILL_ID}`, + method: CONSTANTS.HTTP_REQUEST.VERB.GET, + headers: { + authorization: TEST_ACCESS_TOKEN, + }, + body: null, + json: false, + }, + }, + ].forEach(({testCase, apiFunc, parameters, expectedOptions}) => { + it(`| call ${testCase} successfully`, (done) => { + // setup + AuthorizationController.prototype.tokenRefreshAndRead.callsArgWith(1, null, TEST_ACCESS_TOKEN); - // call - apiFunc(...parameters); + // call + apiFunc(...parameters); - // verify - expect(AuthorizationController.prototype.tokenRefreshAndRead.called).equal(true); - expect(AuthorizationController.prototype.tokenRefreshAndRead.args[0][0]).equal(TEST_PROFILE); - expect(httpClientStub.args[0][0]).deep.equal(expectedOptions); - done(); - }); - }); + // verify + expect(AuthorizationController.prototype.tokenRefreshAndRead.called).equal(true); + expect(AuthorizationController.prototype.tokenRefreshAndRead.args[0][0]).equal(TEST_PROFILE); + expect(httpClientStub.args[0][0]).deep.equal(expectedOptions); + done(); + }); + }); - afterEach(() => { - sinon.restore(); - }); + afterEach(() => { + sinon.restore(); }); + }); }; diff --git a/test/unit/clients/smapi-client-test/resources/test.js b/test/unit/clients/smapi-client-test/resources/test.js index 1e1b91ef..9660d303 100644 --- a/test/unit/clients/smapi-client-test/resources/test.js +++ b/test/unit/clients/smapi-client-test/resources/test.js @@ -1,123 +1,140 @@ -const { expect } = require('chai'); -const sinon = require('sinon'); +const {expect} = require("chai"); +const sinon = require("sinon"); -const httpClient = require('@src/clients/http-client'); -const AuthorizationController = require('@src/controllers/authorization-controller'); -const CONSTANTS = require('@src/utils/constants'); +const httpClient = require("../../../../../lib/clients/http-client"); +const AuthorizationController = require("../../../../../lib/controllers/authorization-controller"); +const CONSTANTS = require("../../../../../lib/utils/constants"); const noop = () => {}; module.exports = (smapiClient) => { - describe('# skill test related APIs', () => { - let httpClientStub; - beforeEach(() => { - httpClientStub = sinon.stub(httpClient, 'request').callsFake(noop); - sinon.stub(AuthorizationController.prototype, 'tokenRefreshAndRead'); - }); + describe("# skill test related APIs", () => { + let httpClientStub; + beforeEach(() => { + httpClientStub = sinon.stub(httpClient, "request").callsFake(noop); + sinon.stub(AuthorizationController.prototype, "tokenRefreshAndRead"); + }); - const TEST_SKILL_ID = 'skillId'; - const TEST_INPUT = 'input'; - const TEST_LOCALE = ' locale1 , locale2 '; - const TEST_SIMULATION_TYPE = 'DEFAULT'; - const TEST_SIMULATION_ID = 'simulationId'; - const TEST_ENDPOINT_REGION = 'endpointRegion'; - const TEST_INVOKE_PAYLOAD = 'invokePayload'; - const FORCE_NEW_SESSION = 'FORCE_NEW_SESSION'; - const TEST_PROFILE = 'testProfile'; - const TEST_ACCESS_TOKEN = 'access_token'; - [ - { - testCase: 'simulate-skill without force new session', - apiFunc: smapiClient.skill.test.simulateSkill, - parameters: [TEST_SKILL_ID, CONSTANTS.SKILL.STAGE.DEVELOPMENT, TEST_INPUT, false, TEST_LOCALE, TEST_SIMULATION_TYPE, noop], - expectedOptions: { - url: `${CONSTANTS.SMAPI.ENDPOINT}/${CONSTANTS.SMAPI.VERSION.V2}/skills/${TEST_SKILL_ID}` - + `/stages/${CONSTANTS.SKILL.STAGE.DEVELOPMENT}/simulations`, - method: CONSTANTS.HTTP_REQUEST.VERB.POST, - headers: { - authorization: TEST_ACCESS_TOKEN - }, - body: { - input: { content: TEST_INPUT }, - device: { locale: TEST_LOCALE }, - simulation: { - type: TEST_SIMULATION_TYPE - } - }, - json: true - } - }, - { - testCase: 'simulate-skill with force new session', - apiFunc: smapiClient.skill.test.simulateSkill, - parameters: [TEST_SKILL_ID, CONSTANTS.SKILL.STAGE.DEVELOPMENT, TEST_INPUT, true, TEST_LOCALE, TEST_SIMULATION_TYPE, noop], - expectedOptions: { - url: `${CONSTANTS.SMAPI.ENDPOINT}/${CONSTANTS.SMAPI.VERSION.V2}/skills/${TEST_SKILL_ID}` - + `/stages/${CONSTANTS.SKILL.STAGE.DEVELOPMENT}/simulations`, - method: CONSTANTS.HTTP_REQUEST.VERB.POST, - headers: { - authorization: TEST_ACCESS_TOKEN - }, - body: { - input: { content: TEST_INPUT }, - device: { locale: TEST_LOCALE }, - session: { mode: FORCE_NEW_SESSION }, - simulation: { - type: TEST_SIMULATION_TYPE - } - }, - json: true - } - }, - { - testCase: 'invoke-skill', - apiFunc: smapiClient.skill.test.invokeSkill, - parameters: [TEST_SKILL_ID, CONSTANTS.SKILL.STAGE.DEVELOPMENT, TEST_INVOKE_PAYLOAD, TEST_ENDPOINT_REGION, noop], - expectedOptions: { - url: `${CONSTANTS.SMAPI.ENDPOINT}/${CONSTANTS.SMAPI.VERSION.V2}/skills/${TEST_SKILL_ID}` - + `/stages/${CONSTANTS.SKILL.STAGE.DEVELOPMENT}/invocations`, - method: CONSTANTS.HTTP_REQUEST.VERB.POST, - headers: { - authorization: TEST_ACCESS_TOKEN - }, - body: { - endpointRegion: TEST_ENDPOINT_REGION, - skillRequest: TEST_INVOKE_PAYLOAD - }, - json: true - } - }, - { - testCase: 'get-simulation', - apiFunc: smapiClient.skill.test.getSimulation, - parameters: [TEST_SKILL_ID, TEST_SIMULATION_ID, CONSTANTS.SKILL.STAGE.DEVELOPMENT, noop], - expectedOptions: { - url: `${CONSTANTS.SMAPI.ENDPOINT}/${CONSTANTS.SMAPI.VERSION.V2}/skills/${TEST_SKILL_ID}/stages/` - + `${CONSTANTS.SKILL.STAGE.DEVELOPMENT}/simulations/${TEST_SIMULATION_ID}`, - method: CONSTANTS.HTTP_REQUEST.VERB.GET, - headers: { - authorization: TEST_ACCESS_TOKEN - }, - body: null, - json: false - } - } - ].forEach(({ testCase, apiFunc, parameters, expectedOptions }) => { - it(`| call ${testCase} successfully`, (done) => { - // setup - AuthorizationController.prototype.tokenRefreshAndRead.callsArgWith(1, null, TEST_ACCESS_TOKEN); - // call - apiFunc(...parameters); - // verify - expect(AuthorizationController.prototype.tokenRefreshAndRead.called).equal(true); - expect(AuthorizationController.prototype.tokenRefreshAndRead.args[0][0]).equal(TEST_PROFILE); - expect(httpClientStub.args[0][0]).deep.equal(expectedOptions); - done(); - }); - }); + const TEST_SKILL_ID = "skillId"; + const TEST_INPUT = "input"; + const TEST_LOCALE = " locale1 , locale2 "; + const TEST_SIMULATION_ID = "simulationId"; + const TEST_ENDPOINT_REGION = "endpointRegion"; + const TEST_INVOKE_PAYLOAD = "invokePayload"; + const TEST_MODIFY_TURN_PAYLOAD = "modifyturnPayload"; + const FORCE_NEW_SESSION = "FORCE_NEW_SESSION"; + const TEST_PROFILE = "testProfile"; + const TEST_ACCESS_TOKEN = "access_token"; + [ + { + testCase: "simulate-skill without force new session", + apiFunc: smapiClient.skill.test.simulateSkill, + parameters: [TEST_SKILL_ID, CONSTANTS.SKILL.STAGE.DEVELOPMENT, TEST_INPUT, false, TEST_LOCALE, noop], + expectedOptions: { + url: + `${CONSTANTS.SMAPI.ENDPOINT}/${CONSTANTS.SMAPI.VERSION.V2}/skills/${TEST_SKILL_ID}` + + `/stages/${CONSTANTS.SKILL.STAGE.DEVELOPMENT}/simulations`, + method: CONSTANTS.HTTP_REQUEST.VERB.POST, + headers: { + authorization: TEST_ACCESS_TOKEN, + }, + body: { + input: {content: TEST_INPUT}, + device: {locale: TEST_LOCALE}, + }, + json: true, + }, + }, + { + testCase: "simulate-skill with force new session", + apiFunc: smapiClient.skill.test.simulateSkill, + parameters: [TEST_SKILL_ID, CONSTANTS.SKILL.STAGE.DEVELOPMENT, TEST_INPUT, true, TEST_LOCALE, noop], + expectedOptions: { + url: + `${CONSTANTS.SMAPI.ENDPOINT}/${CONSTANTS.SMAPI.VERSION.V2}/skills/${TEST_SKILL_ID}` + + `/stages/${CONSTANTS.SKILL.STAGE.DEVELOPMENT}/simulations`, + method: CONSTANTS.HTTP_REQUEST.VERB.POST, + headers: { + authorization: TEST_ACCESS_TOKEN, + }, + body: { + input: {content: TEST_INPUT}, + device: {locale: TEST_LOCALE}, + session: {mode: FORCE_NEW_SESSION}, + }, + json: true, + }, + }, + { + testCase: "invoke-skill", + apiFunc: smapiClient.skill.test.invokeSkill, + parameters: [TEST_SKILL_ID, CONSTANTS.SKILL.STAGE.DEVELOPMENT, TEST_INVOKE_PAYLOAD, TEST_ENDPOINT_REGION, noop], + expectedOptions: { + url: + `${CONSTANTS.SMAPI.ENDPOINT}/${CONSTANTS.SMAPI.VERSION.V2}/skills/${TEST_SKILL_ID}` + + `/stages/${CONSTANTS.SKILL.STAGE.DEVELOPMENT}/invocations`, + method: CONSTANTS.HTTP_REQUEST.VERB.POST, + headers: { + authorization: TEST_ACCESS_TOKEN, + }, + body: { + endpointRegion: TEST_ENDPOINT_REGION, + skillRequest: TEST_INVOKE_PAYLOAD, + }, + json: true, + }, + }, + { + testCase: "get-simulation", + apiFunc: smapiClient.skill.test.getSimulation, + parameters: [TEST_SKILL_ID, TEST_SIMULATION_ID, CONSTANTS.SKILL.STAGE.DEVELOPMENT, noop], + expectedOptions: { + url: + `${CONSTANTS.SMAPI.ENDPOINT}/${CONSTANTS.SMAPI.VERSION.V2}/skills/${TEST_SKILL_ID}/stages/` + + `${CONSTANTS.SKILL.STAGE.DEVELOPMENT}/simulations/${TEST_SIMULATION_ID}`, + method: CONSTANTS.HTTP_REQUEST.VERB.GET, + headers: { + authorization: TEST_ACCESS_TOKEN, + }, + body: null, + json: false, + }, + }, + { + testCase: "modify-last-turn", + apiFunc: smapiClient.skill.test.modifyLastTurn, + parameters: [ + {skillId: TEST_SKILL_ID, stage: CONSTANTS.SKILL.STAGE.DEVELOPMENT, locale: "en_us", payload: TEST_MODIFY_TURN_PAYLOAD}, + noop, + ], + expectedOptions: { + url: + `${CONSTANTS.SMAPI.ENDPOINT}/${CONSTANTS.SMAPI.VERSION.V1}/skills/${TEST_SKILL_ID}/stages/` + + `${CONSTANTS.SKILL.STAGE.DEVELOPMENT}/locales/en_us/conversations/turnPredictions`, + method: CONSTANTS.HTTP_REQUEST.VERB.PUT, + headers: { + authorization: TEST_ACCESS_TOKEN, + }, + body: TEST_MODIFY_TURN_PAYLOAD, + json: true, + }, + }, + ].forEach(({testCase, apiFunc, parameters, expectedOptions}) => { + it(`| call ${testCase} successfully`, (done) => { + // setup + AuthorizationController.prototype.tokenRefreshAndRead.callsArgWith(1, null, TEST_ACCESS_TOKEN); + // call + apiFunc(...parameters); + // verify + expect(AuthorizationController.prototype.tokenRefreshAndRead.called).equal(true); + expect(AuthorizationController.prototype.tokenRefreshAndRead.args[0][0]).equal(TEST_PROFILE); + expect(httpClientStub.args[0][0]).deep.equal(expectedOptions); + done(); + }); + }); - afterEach(() => { - sinon.restore(); - }); + afterEach(() => { + sinon.restore(); }); + }); }; diff --git a/test/unit/clients/smapi-client-test/resources/vendor.js b/test/unit/clients/smapi-client-test/resources/vendor.js index 6ecfaeaa..58ac97ac 100644 --- a/test/unit/clients/smapi-client-test/resources/vendor.js +++ b/test/unit/clients/smapi-client-test/resources/vendor.js @@ -1,54 +1,54 @@ -const { expect } = require('chai'); -const sinon = require('sinon'); +const {expect} = require("chai"); +const sinon = require("sinon"); -const httpClient = require('@src/clients/http-client'); -const AuthorizationController = require('@src/controllers/authorization-controller'); -const CONSTANTS = require('@src/utils/constants'); +const httpClient = require("../../../../../lib/clients/http-client"); +const AuthorizationController = require("../../../../../lib/controllers/authorization-controller"); +const CONSTANTS = require("../../../../../lib/utils/constants"); const noop = () => {}; module.exports = (smapiClient) => { - describe('# smapi client vendor APIs', () => { - let httpClientStub; - const TEST_PROFILE = 'testProfile'; - const TEST_ACCESS_TOKEN = 'access_token'; + describe("# smapi client vendor APIs", () => { + let httpClientStub; + const TEST_PROFILE = "testProfile"; + const TEST_ACCESS_TOKEN = "access_token"; - beforeEach(() => { - httpClientStub = sinon.stub(httpClient, 'request').callsFake(noop); - sinon.stub(AuthorizationController.prototype, 'tokenRefreshAndRead'); - }); + beforeEach(() => { + httpClientStub = sinon.stub(httpClient, "request").callsFake(noop); + sinon.stub(AuthorizationController.prototype, "tokenRefreshAndRead"); + }); - [ - { - testCase: 'list-vendors', - apiFunc: smapiClient.vendor.listVendors, - parameters: [noop], - expectedOptions: { - url: `${CONSTANTS.SMAPI.ENDPOINT}/v1/vendors`, - method: CONSTANTS.HTTP_REQUEST.VERB.GET, - headers: { - authorization: TEST_ACCESS_TOKEN - }, - body: null, - json: false - } - } - ].forEach(({ testCase, apiFunc, parameters, expectedOptions }) => { - it(`| call ${testCase} successfully`, (done) => { - // setup - AuthorizationController.prototype.tokenRefreshAndRead.callsArgWith(1, null, TEST_ACCESS_TOKEN); - // call - apiFunc(...parameters); - // verify - expect(AuthorizationController.prototype.tokenRefreshAndRead.called).equal(true); - expect(AuthorizationController.prototype.tokenRefreshAndRead.args[0][0]).equal(TEST_PROFILE); - expect(httpClientStub.args[0][0]).deep.equal(expectedOptions); - done(); - }); - }); + [ + { + testCase: "list-vendors", + apiFunc: smapiClient.vendor.listVendors, + parameters: [noop], + expectedOptions: { + url: `${CONSTANTS.SMAPI.ENDPOINT}/v1/vendors`, + method: CONSTANTS.HTTP_REQUEST.VERB.GET, + headers: { + authorization: TEST_ACCESS_TOKEN, + }, + body: null, + json: false, + }, + }, + ].forEach(({testCase, apiFunc, parameters, expectedOptions}) => { + it(`| call ${testCase} successfully`, (done) => { + // setup + AuthorizationController.prototype.tokenRefreshAndRead.callsArgWith(1, null, TEST_ACCESS_TOKEN); + // call + apiFunc(...parameters); + // verify + expect(AuthorizationController.prototype.tokenRefreshAndRead.called).equal(true); + expect(AuthorizationController.prototype.tokenRefreshAndRead.args[0][0]).equal(TEST_PROFILE); + expect(httpClientStub.args[0][0]).deep.equal(expectedOptions); + done(); + }); + }); - afterEach(() => { - sinon.restore(); - }); + afterEach(() => { + sinon.restore(); }); + }); }; diff --git a/test/unit/commands/abstract-command-test.js b/test/unit/commands/abstract-command-test.js deleted file mode 100644 index f27fdfc5..00000000 --- a/test/unit/commands/abstract-command-test.js +++ /dev/null @@ -1,523 +0,0 @@ -const { expect } = require('chai'); -const sinon = require('sinon'); -const commander = require('commander'); -const path = require('path'); - -const httpClient = require('@src/clients/http-client'); -const { AbstractCommand } = require('@src/commands/abstract-command'); -const AppConfig = require('@src/model/app-config'); -const CONSTANTS = require('@src/utils/constants'); -const Messenger = require('@src/view/messenger'); - -const packageJson = require('@root/package.json'); - -describe('Command test - AbstractCommand class', () => { - const TEST_DO_DEBUG_FALSE = 'false'; - const TEST_HTTP_ERROR = 'http error'; - const TEST_PROFILE = 'profile'; - const TEST_NPM_REGISTRY_DATA = inputVersion => { - const result = { - body: JSON.stringify({ version: inputVersion }) - }; - return result; - }; - const FIXTURE_PATH = path.join(process.cwd(), 'test', 'unit', 'fixture', 'model'); - const APP_CONFIG_NO_PROFILES_PATH = path.join(FIXTURE_PATH, 'app-config-no-profiles.json'); - - describe('# Command class constructor', () => { - const mockOptionModel = { - 'foo-option': { - name: 'foo-option', - description: 'foo option', - alias: 'f', - stringInput: 'REQUIRED' - }, - 'bar-option': { - name: 'bar-option', - description: 'bar option', - alias: 'b', - stringInput: 'REQUIRED' - }, - 'another-bar-option': { - name: 'another-bar-option', - description: 'another bar option', - alias: 'a', - stringInput: 'OPTIONAL' - }, - 'baz-option': { - name: 'baz-option', - description: 'baz option', - alias: 'z', - stringInput: 'NONE' - } - }; - - let mockProcessExit; - let mockConsoleError; - - beforeEach(() => { - sinon.stub(path, 'join').returns(APP_CONFIG_NO_PROFILES_PATH); - mockProcessExit = sinon.stub(process, 'exit'); - mockConsoleError = sinon.stub(console, 'error'); - sinon.stub(AbstractCommand.prototype, '_remindsIfNewVersion').callsArgWith(2); - }); - - it('| should be able to register command', async () => { - class MockCommand extends AbstractCommand { - constructor(optionModel, handle) { - super(optionModel); - this.handle = handle; - } - - name() { - return 'foo'; - } - - description() { - return 'foo description'; - } - - requiredOptions() { - return ['foo-option']; - } - - optionalOptions() { - return ['bar-option', 'another-bar-option', 'baz-option']; - } - } - - const mockCommand = new MockCommand(mockOptionModel, (options, cb) => { - expect(options._name).eq('foo'); - expect(options._description).eq('foo description'); - expect(options.fooOption).eq('foo'); - expect(options.barOption).eq('bar'); - expect(options.anotherBarOption).eq(true); - expect(options.bazOption).eq(true); - cb(); - }); - - mockCommand.createCommand()(commander); - await commander.parseAsync(['node', 'mock', 'foo', '-f', 'foo', '-b', 'bar', '-a', '-z']); - }); - - it('| should be able to register command without any option', async () => { - class NoOptionCommand extends AbstractCommand { - constructor(optionModel, handle) { - super(optionModel); - this.handle = handle; - } - - name() { - return 'empty-option'; - } - - description() { - return 'empty-option description'; - } - } - - const mockCommand = new NoOptionCommand(mockOptionModel, (options, cb) => { - expect(options._name).eq('empty-option'); - expect(options._description).eq('empty-option description'); - expect(options.options).deep.eq([]); - cb(); - }); - - mockCommand.createCommand()(commander); - await commander.parseAsync(['node', 'mock', 'empty-option']); - }); - - it('| should throw an error if the command did not override any abstract function', async () => { - class CommandWithoutName extends AbstractCommand { - description() { - return 'foo description'; - } - - handle() {} - } - - class CommandWithoutDescription extends AbstractCommand { - name() { - return 'badCommand'; - } - - handle() {} - } - - let counter = 0; - mockProcessExit.callsFake(() => { - counter++; - if (counter < 2) { - return; - } - - expect(mockConsoleError.args[0][0]).include('[Fatal]: Unimplemented abstract function: name()!'); - expect(mockConsoleError.args[1][0]).include('[Fatal]: Unimplemented abstract function: description()!'); - }); - - new CommandWithoutName({}).createCommand()(commander); - await commander.parseAsync(['node', 'mock', 'badCommand']); - new CommandWithoutDescription({}).createCommand()(commander); - await commander.parseAsync(['node', 'mock', 'badCommand']); - }); - - it('| should throw an error when no option model is found given option name', async (done) => { - class MockCommand extends AbstractCommand { - constructor(handle) { - super(null); - this.handle = handle; - } - - name() { - return 'mockCommandWithNoOptionModel'; - } - - description() { - return 'foo description'; - } - - requiredOptions() { - return ['foo-option']; - } - - optionalOptions() { - return ['bar-option', 'another-bar-option', 'baz-option']; - } - } - - mockProcessExit.callsFake(() => { - expect(mockConsoleError.args[0][0]).include('[Fatal]: Unrecognized option ID: foo-option'); - done(); - }); - - new MockCommand(() => {}).createCommand()(commander); - await commander.parseAsync(['node', 'mock', 'mockCommandWithNoOptionModel']); - }); - - it('| should throw an error when option validation fails', async (done) => { - class MockCommand extends AbstractCommand { - constructor(optionModel, handle) { - super(optionModel); - this.handle = handle; - } - - name() { - return 'mockCommand'; - } - - description() { - return 'foo description'; - } - - requiredOptions() { - return ['foo-option']; - } - - optionalOptions() { - return ['bar-option', 'another-bar-option', 'baz-option']; - } - } - - mockProcessExit.callsFake(() => { - expect(mockConsoleError.args[0][0]) - .include('[Error]: Please provide valid input for option: foo-option. Field is required and must be set.'); - done(); - }); - - new MockCommand(mockOptionModel, () => {}).createCommand()(commander); - await commander.parseAsync(['node', 'mock', 'mockCommand']); - }); - - afterEach(() => { - sinon.restore(); - AppConfig.dispose(); - }); - }); - - describe('# Static method - buildOptionString', () => { - it('| should be able to build option string from option model', () => { - const mockModel = { - name: 'mock-option', - alias: 'm', - description: 'mock option', - stringInput: 'REQUIRED', - }; - - const optionString = AbstractCommand.buildOptionString(mockModel); - - expect(optionString).eq('-m, --mock-option '); - - const mockModelWithOptionalStringInput = { - name: 'mock-option', - alias: 'm', - description: 'mock option', - stringInput: 'OPTIONAL', - }; - - const optionStringWithOptionalStringInput = AbstractCommand.buildOptionString(mockModelWithOptionalStringInput); - expect(optionStringWithOptionalStringInput).eq('-m, --mock-option [mock-option]'); - }); - - it('| should omit the option value when it does not required string input', () => { - const mockModel = { - name: 'mock-option', - alias: 'm', - description: 'mock option', - }; - - const optionString = AbstractCommand.buildOptionString(mockModel); - - expect(optionString).eq('-m, --mock-option'); - }); - - it('| should omit the alias when there is not one', () => { - const mockModel = { - name: 'mock-option', - description: 'mock option', - }; - - const optionString = AbstractCommand.buildOptionString(mockModel); - - expect(optionString).eq('--mock-option'); - }); - }); - - describe('# Static method - parseOptionKey', () => { - it('| should be able to parse option name', () => { - expect(AbstractCommand.parseOptionKey('skill-id')).eq('skillId'); - expect(AbstractCommand.parseOptionKey('skill')).eq('skill'); - }); - }); - - describe('# verify new version reminder method', () => { - const currentMajor = parseInt(packageJson.version.split('.')[0], 10); - const currentMinor = parseInt(packageJson.version.split('.')[1], 10); - let errorStub, warnStub, infoStub; - - beforeEach(() => { - errorStub = sinon.stub(); - warnStub = sinon.stub(); - infoStub = sinon.stub(); - sinon.stub(Messenger, 'getInstance').returns({ - info: infoStub, - warn: warnStub, - error: errorStub - }); - sinon.stub(httpClient, 'request'); - }); - - afterEach(() => { - sinon.restore(); - }); - - it('| skip is set, should skip version check', (done) => { - // setup - const skip = true; - // call - AbstractCommand.prototype._remindsIfNewVersion(TEST_DO_DEBUG_FALSE, skip, () => { - // verify - expect(httpClient.request.called).equal(false); - done(); - }); - }); - - it('| http client request error, should warn it out and pass the process', (done) => { - // setup - httpClient.request.callsArgWith(3, TEST_HTTP_ERROR); - // call - AbstractCommand.prototype._remindsIfNewVersion(TEST_DO_DEBUG_FALSE, undefined, (err) => { - // verify - expect(httpClient.request.args[0][0].url).equal( - `${CONSTANTS.NPM_REGISTRY_URL_BASE}/${CONSTANTS.APPLICATION_NAME}/latest` - ); - expect(httpClient.request.args[0][0].method).equal(CONSTANTS.HTTP_REQUEST.VERB.GET); - expect(errorStub.args[0][0]).equal( - `Failed to get the latest version for ${CONSTANTS.APPLICATION_NAME} from NPM registry.\n${TEST_HTTP_ERROR}\n` - ); - expect(err).equal(undefined); - done(); - }); - }); - - it('| http client request error status code , should warn it out and pass the process', (done) => { - // setup - httpClient.request.yields(undefined, { statusCode: 400 }); - // call - AbstractCommand.prototype._remindsIfNewVersion(TEST_DO_DEBUG_FALSE, undefined, (err) => { - // verify - expect(httpClient.request.args[0][0].url).equal( - `${CONSTANTS.NPM_REGISTRY_URL_BASE}/${CONSTANTS.APPLICATION_NAME}/latest` - ); - expect(httpClient.request.args[0][0].method).equal(CONSTANTS.HTTP_REQUEST.VERB.GET); - expect(errorStub.args[0][0]).equal( - `Failed to get the latest version for ${CONSTANTS.APPLICATION_NAME} from NPM registry.\nHttp Status Code: 400.\n` - ); - expect(err).equal(undefined); - done(); - }); - }); - - it('| new major version released, should error out and pass the process', (done) => { - // setup - const latestVersion = `${currentMajor + 1}.0.0`; - httpClient.request.callsArgWith(3, null, TEST_NPM_REGISTRY_DATA(latestVersion)); - // call - AbstractCommand.prototype._remindsIfNewVersion(TEST_DO_DEBUG_FALSE, undefined, (err) => { - // verify - expect(httpClient.request.args[0][0].url).equal( - `${CONSTANTS.NPM_REGISTRY_URL_BASE}/${CONSTANTS.APPLICATION_NAME}/latest` - ); - expect(httpClient.request.args[0][0].method).equal(CONSTANTS.HTTP_REQUEST.VERB.GET); - expect(warnStub.args[0][0]).equal(`\ -New MAJOR version (v${latestVersion}) of ${CONSTANTS.APPLICATION_NAME} is available now. Current version v${packageJson.version}. -It is recommended to use the latest version. Please update using "npm upgrade -g ${CONSTANTS.APPLICATION_NAME}". -\n`); - expect(err).equal(undefined); - done(); - }); - }); - - it('| new minor version released, should warn out and pass the process', (done) => { - // setup - const latestVersion = `${currentMajor}.${currentMinor + 1}.0`; - httpClient.request.callsArgWith(3, null, TEST_NPM_REGISTRY_DATA(latestVersion)); - // call - AbstractCommand.prototype._remindsIfNewVersion(TEST_DO_DEBUG_FALSE, undefined, (err) => { - // verify - expect(httpClient.request.args[0][0].url).equal( - `${CONSTANTS.NPM_REGISTRY_URL_BASE}/${CONSTANTS.APPLICATION_NAME}/latest` - ); - expect(httpClient.request.args[0][0].method).equal(CONSTANTS.HTTP_REQUEST.VERB.GET); - expect(warnStub.args[0][0]).equal(`\ -New MINOR version (v${latestVersion}) of ${CONSTANTS.APPLICATION_NAME} is available now. Current version v${packageJson.version}. -It is recommended to use the latest version. Please update using "npm upgrade -g ${CONSTANTS.APPLICATION_NAME}". -\n`); - expect(err).equal(undefined); - done(); - }); - }); - - it('| version is latest, should do nothing and pass the process', (done) => { - // setup - httpClient.request.callsArgWith(3, null, TEST_NPM_REGISTRY_DATA(`${currentMajor}.${currentMinor}.0`)); - // call - AbstractCommand.prototype._remindsIfNewVersion(TEST_DO_DEBUG_FALSE, undefined, (err) => { - // verify - expect(httpClient.request.args[0][0].url).equal( - `${CONSTANTS.NPM_REGISTRY_URL_BASE}/${CONSTANTS.APPLICATION_NAME}/latest` - ); - expect(httpClient.request.args[0][0].method).equal(CONSTANTS.HTTP_REQUEST.VERB.GET); - expect(infoStub.callCount).equal(0); - expect(warnStub.callCount).equal(0); - expect(errorStub.callCount).equal(0); - expect(err).equal(undefined); - done(); - }); - }); - }); - - describe('# check AppConfig object ', () => { - const mockOptionModel = { - 'foo-option': { - name: 'foo-option', - description: 'foo option', - alias: 'f', - stringInput: 'REQUIRED' - }, - 'bar-option': { - name: 'bar-option', - description: 'bar option', - alias: 'b', - stringInput: 'REQUIRED' - }, - 'another-bar-option': { - name: 'another-bar-option', - description: 'another bar option', - alias: 'a', - stringInput: 'OPTIONAL' - }, - 'baz-option': { - name: 'baz-option', - description: 'baz option', - alias: 'z', - stringInput: 'NONE' - }, - profile: { - name: 'profile', - description: 'profile option', - alias: 'p', - stringInput: 'REQUIRED' - } - }; - - let AppConfigReadStub; - beforeEach(() => { - AppConfigReadStub = sinon.stub(AppConfig.prototype, 'read'); - sinon.stub(process, 'exit'); - }); - - it('| should not be null for non-configure commands', async () => { - class NonConfigureCommand extends AbstractCommand { - constructor(optionModel, handle) { - super(optionModel); - this.handle = handle; - } - - name() { - return 'random'; - } - - optionalOptions() { - return ['profile']; - } - - description() { - return 'random description'; - } - } - - const mockCommand = new NonConfigureCommand(mockOptionModel, (options, cb) => { - expect(options._name).eq('random'); - expect(options._description).eq('random description'); - expect(AppConfigReadStub.called).eql(true); - cb(); - }); - - mockCommand.createCommand()(commander); - await commander.parseAsync(['node', 'mock', 'random', '--profile', TEST_PROFILE]); - }); - - it('| should be null for configure command', async () => { - class ConfigureCommand extends AbstractCommand { - constructor(optionModel, handle) { - super(optionModel); - this.handle = handle; - } - - name() { - return 'configure'; - } - - description() { - return 'configure description'; - } - } - - const mockCommand = new ConfigureCommand(mockOptionModel, (options, cb) => { - expect(options._name).eq('configure'); - expect(options._description).eq('configure description'); - expect(options.options).deep.eq([]); - expect(AppConfigReadStub.called).eql(false); - cb(); - }); - - mockCommand.createCommand()(commander); - await commander.parseAsync(['node', 'mock', 'configure']); - }); - - afterEach(() => { - sinon.restore(); - AppConfig.dispose(); - }); - }); -}); diff --git a/test/unit/commands/abstract-command-test.ts b/test/unit/commands/abstract-command-test.ts new file mode 100644 index 00000000..4815e066 --- /dev/null +++ b/test/unit/commands/abstract-command-test.ts @@ -0,0 +1,531 @@ +import {expect} from "chai"; +import sinon from "sinon"; +import path from "path"; +import httpClient from "../../../lib/clients/http-client"; +import {AbstractCommand} from "../../../lib/commands/abstract-command"; +import AppConfig from "../../../lib/model/app-config"; +import CONSTANTS from "../../../lib/utils/constants"; +import Messenger from "../../../lib/view/messenger"; +import packageJson from "../../../package.json"; +import {OptionModel} from "../../../lib/commands/option-validator"; +import { Command } from "commander"; + +const commander = new Command(); + +describe("Command test - AbstractCommand class", () => { + const TEST_DO_DEBUG_FALSE = false; + const TEST_HTTP_ERROR = "http error"; + const TEST_PROFILE = "profile"; + const TEST_NPM_REGISTRY_DATA = (inputVersion: string) => { + const result = { + body: JSON.stringify({version: inputVersion}), + }; + return result; + }; + const FIXTURE_PATH = path.join(process.cwd(), "test", "unit", "fixture", "model"); + const APP_CONFIG_NO_PROFILES_PATH = path.join(FIXTURE_PATH, "app-config-no-profiles.json"); + + describe("# Command class constructor", () => { + const mockOptionModel = { + "foo-option": { + name: "foo-option", + description: "foo option", + alias: "f", + stringInput: "REQUIRED", + }, + "bar-option": { + name: "bar-option", + description: "bar option", + alias: "b", + stringInput: "REQUIRED", + }, + "another-bar-option": { + name: "another-bar-option", + description: "another bar option", + alias: "a", + stringInput: "OPTIONAL", + }, + "baz-option": { + name: "baz-option", + description: "baz option", + alias: "z", + stringInput: "NONE", + }, + }; + + let mockProcessExit: sinon.SinonStub; + let mockConsoleError: sinon.SinonStub; + + beforeEach(() => { + sinon.stub(AppConfig.prototype, "read"); + sinon.stub(path, "join").returns(APP_CONFIG_NO_PROFILES_PATH); + mockProcessExit = sinon.stub(process, "exit"); + mockConsoleError = sinon.stub(console, "error"); + sinon.stub(AbstractCommand.prototype, "_remindsIfNewVersion").resolves(); + }); + + it("| should be able to register command", async () => { + const handleStub = sinon.stub().resolves(); + class MockCommand extends AbstractCommand { + constructor(optionModel: OptionModel) { + super(optionModel); + } + + name() { + return "foo"; + } + + description() { + return "foo description"; + } + + requiredOptions() { + return ["foo-option"]; + } + + optionalOptions() { + return ["bar-option", "another-bar-option", "baz-option"]; + } + + handle(options: Record) { + return handleStub(options); + } + } + + const mockCommand = new MockCommand(mockOptionModel); + + mockCommand.createCommand()(commander); + await commander.parseAsync(["blah", "mock", "foo", "-f", "foo", "-b", "bar", "-a", "-z"]); + + expect(handleStub).calledOnce; + const options = handleStub.getCall(0).args[0]; + expect(options._name).eq("foo"); + expect(options._description).eq("foo description"); + expect(options.fooOption).eq("foo"); + expect(options.barOption).eq("bar"); + expect(options.anotherBarOption).eq(true); + expect(options.bazOption).eq(true); + }); + + it("| should be able to register command without any option", async () => { + const handleStub = sinon.stub().resolves(); + + class NoOptionCommand extends AbstractCommand { + constructor(optionModel: OptionModel) { + super(optionModel); + } + + name() { + return "empty-option"; + } + + description() { + return "empty-option description"; + } + + handle(options: Record) { + return handleStub(options); + } + + requiredOptions(): string[] { + return []; + } + optionalOptions(): string[] { + return []; + } + } + + const mockCommand = new NoOptionCommand(mockOptionModel); + + mockCommand.createCommand()(commander); + await commander.parseAsync(["blah", "mock", "empty-option"]); + + expect(handleStub).calledWithMatch( + sinon.match({ + _name: "empty-option", + _description: "empty-option description", + options: [], + }), + ); + }); + + it("| should throw an error when no option model is found given option name", (done) => { + class MockCommand extends AbstractCommand { + constructor() { + super(null as any); + } + + name() { + return "mockCommandWithNoOptionModel"; + } + + description() { + return "foo description"; + } + + requiredOptions() { + return ["foo-option"]; + } + + optionalOptions() { + return ["bar-option", "another-bar-option", "baz-option"]; + } + + handle() { + return Promise.resolve(); + } + } + + mockProcessExit.callsFake(() => { + expect(mockConsoleError.args[0][0]).include("[Fatal]: Unrecognized option ID: foo-option"); + done(); + }); + + new MockCommand().createCommand()(commander); + commander.parseAsync(["node", "mock", "mockCommandWithNoOptionModel"]); + }); + + it("| should throw an error when option validation fails", (done) => { + class MockCommand extends AbstractCommand { + constructor(optionModel: OptionModel) { + super(optionModel); + } + + name() { + return "mockCommand"; + } + + description() { + return "foo description"; + } + + requiredOptions() { + return ["foo-option"]; + } + + optionalOptions() { + return ["bar-option", "another-bar-option", "baz-option"]; + } + + handle() { + return Promise.resolve(); + } + } + + mockProcessExit.callsFake(() => { + expect(mockConsoleError.args[0][0]).include( + "[Error]: Please provide valid input for option: foo-option. Field is required and must be set.", + ); + done(); + }); + + new MockCommand(mockOptionModel).createCommand()(commander); + commander.parseAsync(["node", "mock", "mockCommand"]); + }); + + afterEach(() => { + sinon.restore(); + AppConfig.dispose(); + }); + }); + + describe("# Static method - buildOptionString", () => { + it("| should be able to build option string from option model", () => { + const mockModel = { + name: "mock-option", + alias: "m", + description: "mock option", + stringInput: "REQUIRED", + }; + + const optionString = AbstractCommand.buildOptionString(mockModel); + + expect(optionString).eq("-m, --mock-option "); + + const mockModelWithOptionalStringInput = { + name: "mock-option", + alias: "m", + description: "mock option", + stringInput: "OPTIONAL", + }; + + const optionStringWithOptionalStringInput = AbstractCommand.buildOptionString(mockModelWithOptionalStringInput); + expect(optionStringWithOptionalStringInput).eq("-m, --mock-option [mock-option]"); + }); + + it("| should omit the option value when it does not required string input", () => { + const mockModel = { + name: "mock-option", + alias: "m", + description: "mock option", + }; + + const optionString = AbstractCommand.buildOptionString(mockModel as any); + + expect(optionString).eq("-m, --mock-option"); + }); + + it("| should omit the alias when there is not one", () => { + const mockModel = { + name: "mock-option", + description: "mock option", + }; + + const optionString = AbstractCommand.buildOptionString(mockModel as any); + + expect(optionString).eq("--mock-option"); + }); + }); + + describe("# Static method - parseOptionKey", () => { + it("| should be able to parse option name", () => { + expect(AbstractCommand.parseOptionKey("skill-id")).eq("skillId"); + expect(AbstractCommand.parseOptionKey("skill")).eq("skill"); + }); + }); + + describe("# verify new version reminder method", () => { + const currentMajor = parseInt(packageJson.version.split(".")[0], 10); + const currentMinor = parseInt(packageJson.version.split(".")[1], 10); + let errorStub: sinon.SinonStub, warnStub: sinon.SinonStub, infoStub: sinon.SinonStub, httpClientStub: sinon.SinonStub; + + beforeEach(() => { + errorStub = sinon.stub(); + warnStub = sinon.stub(); + infoStub = sinon.stub(); + sinon.stub(Messenger, "getInstance").returns({ + info: infoStub, + warn: warnStub, + error: errorStub, + }); + httpClientStub = sinon.stub(httpClient, "request"); + }); + + afterEach(() => { + sinon.restore(); + }); + + it("| skip is set, should skip version check", async () => { + // setup + const skip = true; + // call + await AbstractCommand.prototype._remindsIfNewVersion(TEST_DO_DEBUG_FALSE, skip); + + // verify + expect(httpClientStub).not.called; + }); + + it("| http client request error, should warn it out and pass the process", async () => { + // setup + httpClientStub.callsArgWith(3, TEST_HTTP_ERROR); + // call + await AbstractCommand.prototype._remindsIfNewVersion(TEST_DO_DEBUG_FALSE, undefined); + + // verify + expect(httpClientStub.args[0][0].url).equal(`${CONSTANTS.NPM_REGISTRY_URL_BASE}/${CONSTANTS.APPLICATION_NAME}/latest`); + expect(httpClientStub.args[0][0].method).equal(CONSTANTS.HTTP_REQUEST.VERB.GET); + expect(errorStub.args[0][0]).equal( + `Failed to get the latest version for ${CONSTANTS.APPLICATION_NAME} from NPM registry.\n${TEST_HTTP_ERROR}\n`, + ); + }); + + it("| http client request error status code , should warn it out and pass the process", async () => { + // setup + httpClientStub.yields(undefined, {statusCode: 400}); + // call + await AbstractCommand.prototype._remindsIfNewVersion(TEST_DO_DEBUG_FALSE, undefined); + // verify + expect(httpClientStub.args[0][0].url).equal(`${CONSTANTS.NPM_REGISTRY_URL_BASE}/${CONSTANTS.APPLICATION_NAME}/latest`); + expect(httpClientStub.args[0][0].method).equal(CONSTANTS.HTTP_REQUEST.VERB.GET); + expect(errorStub.args[0][0]).equal( + `Failed to get the latest version for ${CONSTANTS.APPLICATION_NAME} from NPM registry.\nHttp Status Code: 400.\n`, + ); + }); + + it("| new major version released, should error out and pass the process", async () => { + // setup + const latestVersion = `${currentMajor + 1}.0.0`; + httpClientStub.callsArgWith(3, null, TEST_NPM_REGISTRY_DATA(latestVersion)); + // call + await AbstractCommand.prototype._remindsIfNewVersion(TEST_DO_DEBUG_FALSE, undefined); + // verify + expect(httpClientStub.args[0][0].url).equal(`${CONSTANTS.NPM_REGISTRY_URL_BASE}/${CONSTANTS.APPLICATION_NAME}/latest`); + expect(httpClientStub.args[0][0].method).equal(CONSTANTS.HTTP_REQUEST.VERB.GET); + expect(warnStub.args[0][0]).equal(`\ +New MAJOR version (v${latestVersion}) of ${CONSTANTS.APPLICATION_NAME} is available now. Current version v${packageJson.version}. +It is recommended to use the latest version. Please update using "npm upgrade -g ${CONSTANTS.APPLICATION_NAME}". +\n`); + }); + + it("| new minor version released, should warn out and pass the process", async () => { + // setup + const latestVersion = `${currentMajor}.${currentMinor + 1}.0`; + httpClientStub.callsArgWith(3, null, TEST_NPM_REGISTRY_DATA(latestVersion)); + // call + await AbstractCommand.prototype._remindsIfNewVersion(TEST_DO_DEBUG_FALSE, undefined); + // verify + expect(httpClientStub.args[0][0].url).equal(`${CONSTANTS.NPM_REGISTRY_URL_BASE}/${CONSTANTS.APPLICATION_NAME}/latest`); + expect(httpClientStub.args[0][0].method).equal(CONSTANTS.HTTP_REQUEST.VERB.GET); + expect(warnStub.args[0][0]).equal(`\ +New MINOR version (v${latestVersion}) of ${CONSTANTS.APPLICATION_NAME} is available now. Current version v${packageJson.version}. +It is recommended to use the latest version. Please update using "npm upgrade -g ${CONSTANTS.APPLICATION_NAME}". +\n`); + }); + + it("| version is latest, should do nothing and pass the process", async () => { + // setup + httpClientStub.callsArgWith(3, null, TEST_NPM_REGISTRY_DATA(`${currentMajor}.${currentMinor}.0`)); + // call + await AbstractCommand.prototype._remindsIfNewVersion(TEST_DO_DEBUG_FALSE, undefined); + // verify + expect(httpClientStub.args[0][0].url).equal(`${CONSTANTS.NPM_REGISTRY_URL_BASE}/${CONSTANTS.APPLICATION_NAME}/latest`); + expect(httpClientStub.args[0][0].method).equal(CONSTANTS.HTTP_REQUEST.VERB.GET); + expect(infoStub.callCount).equal(0); + expect(warnStub.callCount).equal(0); + expect(errorStub.callCount).equal(0); + }); + }); + + describe("# check AppConfig object ", () => { + const mockOptionModel = { + "foo-option": { + name: "foo-option", + description: "foo option", + alias: "f", + stringInput: "REQUIRED", + }, + "bar-option": { + name: "bar-option", + description: "bar option", + alias: "b", + stringInput: "REQUIRED", + }, + "another-bar-option": { + name: "another-bar-option", + description: "another bar option", + alias: "a", + stringInput: "OPTIONAL", + }, + "baz-option": { + name: "baz-option", + description: "baz option", + alias: "z", + stringInput: "NONE", + }, + profile: { + name: "profile", + description: "profile option", + alias: "p", + stringInput: "REQUIRED", + }, + }; + + let AppConfigReadStub: sinon.SinonStub; + let errorStub: sinon.SinonStub, warnStub: sinon.SinonStub, infoStub: sinon.SinonStub; + + beforeEach(() => { + AppConfigReadStub = sinon.stub(AppConfig.prototype, "read"); + sinon.stub(process, "exit"); + errorStub = sinon.stub(); + warnStub = sinon.stub(); + infoStub = sinon.stub(); + sinon.stub(Messenger, "getInstance").returns({ + info: infoStub, + warn: warnStub, + error: errorStub, + }); + sinon.stub(httpClient, "request").yields({statusCode: 200}); + }); + + it("| should not be null for non-configure commands", async () => { + const handleStub = sinon.stub().resolves(); + + class NonConfigureCommand extends AbstractCommand { + constructor(optionModel: OptionModel) { + super(optionModel); + } + + name() { + return "random"; + } + + optionalOptions() { + return ["profile"]; + } + + description() { + return "random description"; + } + + handle(options: Record) { + return handleStub(options); + } + + requiredOptions(): string[] { + return []; + } + } + + const mockCommand = new NonConfigureCommand(mockOptionModel); + + mockCommand.createCommand()(commander); + await commander.parseAsync(["node", "mock", "random", "--profile", TEST_PROFILE]); + + expect(handleStub).calledWithMatch( + sinon.match({ + _name: "random", + _description: "random description", + }), + ); + + expect(AppConfigReadStub).called; + }); + + it("| should be null for configure command", async () => { + const handleStub = sinon.stub().resolves(); + + class ConfigureCommand extends AbstractCommand { + constructor(optionModel: OptionModel) { + super(optionModel); + } + + name() { + return "configure"; + } + + description() { + return "configure description"; + } + requiredOptions(): string[] { + return []; + } + optionalOptions(): string[] { + return []; + } + handle(cmd: any): Promise { + return handleStub(cmd); + } + } + + const mockCommand = new ConfigureCommand(mockOptionModel); + + mockCommand.createCommand()(commander); + await commander.parseAsync(["node", "mock", "configure"]); + + expect(handleStub).calledWithMatch( + sinon.match({ + _name: "configure", + _description: "configure description", + options: [], + }), + ); + + expect(AppConfigReadStub).not.called; + }); + + afterEach(() => { + sinon.restore(); + AppConfig.dispose(); + }); + }); +}); diff --git a/test/unit/commands/configure/ask-profile-setup-helper-test.js b/test/unit/commands/configure/ask-profile-setup-helper-test.js index 82ad44cb..2a54861c 100644 --- a/test/unit/commands/configure/ask-profile-setup-helper-test.js +++ b/test/unit/commands/configure/ask-profile-setup-helper-test.js @@ -1,283 +1,278 @@ -const { expect } = require('chai'); -const sinon = require('sinon'); - -const askProfileSetupHelper = require('@src/commands/configure/ask-profile-setup-helper'); -const messages = require('@src/commands/configure/messages'); -const ui = require('@src/commands/configure/ui'); -const AuthorizationController = require('@src/controllers/authorization-controller'); -const httpClient = require('@src/clients/http-client'); -const SmapiClient = require('@src/clients/smapi-client'); -const jsonView = require('@src/view/json-view'); -const Messenger = require('@src/view/messenger'); - -describe('Command: Configure - ASK profile setup helper test', () => { - const TEST_PROFILE = 'testProfile'; - const TEST_DO_DEBUG = false; - const TEST_NEED_BROWSER = false; - const TEST_VENDOR_ID_1 = 'testVendorId_1'; - const TEST_VENDOR_ID_2 = 'testVendorId_2'; - const TEST_ERROR_MESSAGE = 'error thrown'; - const TEST_CONFIG = { - askProfile: TEST_PROFILE, - needBrowser: TEST_NEED_BROWSER, - debug: TEST_DO_DEBUG - }; - const TEST_VENDOR_HTTP_RESPONSE_BODY = { - vendors: [ - { id: TEST_VENDOR_ID_1 } - ] - }; - - const TEST_MULTIPLE_VENDORS_HTTP_RESPONSE_BODY = { - vendors: [ - { id: TEST_VENDOR_ID_1 }, - { id: TEST_VENDOR_ID_2 } - ] - }; - - const TEST_EMPTY_VENDOR_HTTP_RESPONSE_BODY = { - vendors: [] - }; - - const TEST_ACCESS_TOKEN = { - access_token: 'access_token', - refresh_token: 'refresh_token', - expires_in: 3600, - expires_at: 'expires_at' - }; - - const TEST_AUTHORIZE_URL = 'authorizeUrl'; - const TEST_AUTH_CODE = 'authCode'; - - describe('# test setupAskToken', () => { - let infoStub; - beforeEach(() => { - sinon.stub(AuthorizationController.prototype, 'getTokensByListeningOnPort'); - sinon.stub(AuthorizationController.prototype, 'getAccessTokenUsingAuthCode'); - sinon.stub(AuthorizationController.prototype, 'getAuthorizeUrl'); - sinon.stub(ui, 'getAuthCode'); - infoStub = sinon.stub(); - sinon.stub(Messenger, 'getInstance').returns({ - info: infoStub - }); - }); +const {expect} = require("chai"); +const sinon = require("sinon"); + +const askProfileSetupHelper = require("../../../../lib/commands/configure/ask-profile-setup-helper"); +const messages = require("../../../../lib/commands/configure/messages"); +const ui = require("../../../../lib/commands/configure/ui"); +const AuthorizationController = require("../../../../lib/controllers/authorization-controller"); +const httpClient = require("../../../../lib/clients/http-client"); +const SmapiClient = require("../../../../lib/clients/smapi-client").default; +const jsonView = require("../../../../lib/view/json-view"); +const Messenger = require("../../../../lib/view/messenger"); + +describe("Command: Configure - ASK profile setup helper test", () => { + const TEST_PROFILE = "testProfile"; + const TEST_DO_DEBUG = false; + const TEST_NEED_BROWSER = false; + const TEST_VENDOR_ID_1 = "testVendorId_1"; + const TEST_VENDOR_ID_2 = "testVendorId_2"; + const TEST_ERROR_MESSAGE = "error thrown"; + const TEST_CONFIG = { + askProfile: TEST_PROFILE, + needBrowser: TEST_NEED_BROWSER, + debug: TEST_DO_DEBUG, + }; + const TEST_VENDOR_HTTP_RESPONSE_BODY = { + vendors: [{id: TEST_VENDOR_ID_1}], + }; + + const TEST_MULTIPLE_VENDORS_HTTP_RESPONSE_BODY = { + vendors: [{id: TEST_VENDOR_ID_1}, {id: TEST_VENDOR_ID_2}], + }; + + const TEST_EMPTY_VENDOR_HTTP_RESPONSE_BODY = { + vendors: [], + }; + + const TEST_ACCESS_TOKEN = { + access_token: "access_token", + refresh_token: "refresh_token", + expires_in: 3600, + expires_at: "expires_at", + }; + + const TEST_AUTHORIZE_URL = "authorizeUrl"; + const TEST_AUTH_CODE = "authCode"; + + describe("# test setupAskToken", () => { + let infoStub; + beforeEach(() => { + sinon.stub(AuthorizationController.prototype, "getTokensByListeningOnPort"); + sinon.stub(AuthorizationController.prototype, "getAccessTokenUsingAuthCode"); + sinon.stub(AuthorizationController.prototype, "getAuthorizeUrl"); + sinon.stub(ui, "getAuthCode"); + infoStub = sinon.stub(); + sinon.stub(Messenger, "getInstance").returns({ + info: infoStub, + }); + }); - it('| test valid access token retrieval, getTokensByListeningOnPort returns valid token', (done) => { - // setup - AuthorizationController.prototype.getTokensByListeningOnPort.callsArgWith(0, null, TEST_ACCESS_TOKEN); - - // call - askProfileSetupHelper.setupAskToken({ needBrowser: true, askProfile: TEST_PROFILE }, (error, accessToken) => { - // verify - expect(error).eq(null); - expect(accessToken).to.deep.eq(TEST_ACCESS_TOKEN); - done(); - }); - }); + it("| test valid access token retrieval, getTokensByListeningOnPort returns valid token", (done) => { + // setup + AuthorizationController.prototype.getTokensByListeningOnPort.callsArgWith(0, null, TEST_ACCESS_TOKEN); + + // call + askProfileSetupHelper.setupAskToken({needBrowser: true, askProfile: TEST_PROFILE}, (error, accessToken) => { + // verify + expect(error).eq(null); + expect(accessToken).to.deep.eq(TEST_ACCESS_TOKEN); + done(); + }); + }); - it('| test valid access token retrieval, getTokensByListeningOnPort returns error', (done) => { - // setup - AuthorizationController.prototype.getTokensByListeningOnPort.callsArgWith(0, TEST_ERROR_MESSAGE); - - // call - askProfileSetupHelper.setupAskToken({ needBrowser: true, askProfile: TEST_PROFILE }, (error, accessToken) => { - // verify - expect(error).eq(TEST_ERROR_MESSAGE); - expect(accessToken).eq(undefined); - done(); - }); - }); + it("| test valid access token retrieval, getTokensByListeningOnPort returns error", (done) => { + // setup + AuthorizationController.prototype.getTokensByListeningOnPort.callsArgWith(0, TEST_ERROR_MESSAGE); + + // call + askProfileSetupHelper.setupAskToken({needBrowser: true, askProfile: TEST_PROFILE}, (error, accessToken) => { + // verify + expect(error).eq(TEST_ERROR_MESSAGE); + expect(accessToken).eq(undefined); + done(); + }); + }); - it('| test valid access token retrieval, authcode retrieval returns error', (done) => { - // setup - AuthorizationController.prototype.getAuthorizeUrl.returns(TEST_AUTHORIZE_URL); - ui.getAuthCode.callsArgWith(0, TEST_ERROR_MESSAGE); - - // call - askProfileSetupHelper.setupAskToken(TEST_CONFIG, (error, accessToken) => { - // verify - expect(infoStub.args[0][0]).eq(`Paste the following url to your browser:\n ${TEST_AUTHORIZE_URL}`); - expect(error).eq(TEST_ERROR_MESSAGE); - expect(accessToken).eq(undefined); - done(); - }); - }); + it("| test valid access token retrieval, authcode retrieval returns error", (done) => { + // setup + AuthorizationController.prototype.getAuthorizeUrl.returns(TEST_AUTHORIZE_URL); + ui.getAuthCode.callsArgWith(0, TEST_ERROR_MESSAGE); + + // call + askProfileSetupHelper.setupAskToken(TEST_CONFIG, (error, accessToken) => { + // verify + expect(infoStub.args[0][0]).eq(`Paste the following url to your browser:\n ${TEST_AUTHORIZE_URL}`); + expect(error).eq(TEST_ERROR_MESSAGE); + expect(accessToken).eq(undefined); + done(); + }); + }); - it('| test valid access token retrieval, getAccessTokenUsingAuthCode returns valid token', (done) => { - // setup - AuthorizationController.prototype.getAccessTokenUsingAuthCode.callsArgWith(1, null, TEST_ACCESS_TOKEN); - AuthorizationController.prototype.getAuthorizeUrl.returns('authorizeUrl'); - ui.getAuthCode.callsArgWith(0, null, TEST_AUTH_CODE); - - // call - askProfileSetupHelper.setupAskToken(TEST_CONFIG, (error, accessToken) => { - // verify - expect(error).eq(null); - expect(accessToken).to.deep.eq(TEST_ACCESS_TOKEN); - expect(infoStub.args[0][0]).eq(`Paste the following url to your browser:\n ${TEST_AUTHORIZE_URL}`); - done(); - }); - }); + it("| test valid access token retrieval, getAccessTokenUsingAuthCode returns valid token", (done) => { + // setup + AuthorizationController.prototype.getAccessTokenUsingAuthCode.callsArgWith(1, null, TEST_ACCESS_TOKEN); + AuthorizationController.prototype.getAuthorizeUrl.returns("authorizeUrl"); + ui.getAuthCode.callsArgWith(0, null, TEST_AUTH_CODE); + + // call + askProfileSetupHelper.setupAskToken(TEST_CONFIG, (error, accessToken) => { + // verify + expect(error).eq(null); + expect(accessToken).to.deep.eq(TEST_ACCESS_TOKEN); + expect(infoStub.args[0][0]).eq(`Paste the following url to your browser:\n ${TEST_AUTHORIZE_URL}`); + done(); + }); + }); - it('| test valid access token retrieval, getAccessTokenUsingAuthCode throws error', (done) => { - // setup - AuthorizationController.prototype.getAccessTokenUsingAuthCode.callsArgWith(1, TEST_ERROR_MESSAGE); - AuthorizationController.prototype.getAuthorizeUrl.returns('authorizeUrl'); - ui.getAuthCode.callsArgWith(0, null, TEST_AUTH_CODE); - - // call - askProfileSetupHelper.setupAskToken(TEST_CONFIG, (error, accessToken) => { - // verify - expect(error).eq(TEST_ERROR_MESSAGE); - expect(accessToken).eq(undefined); - expect(infoStub.args[0][0]).eq(`Paste the following url to your browser:\n ${TEST_AUTHORIZE_URL}`); - done(); - }); - }); + it("| test valid access token retrieval, getAccessTokenUsingAuthCode throws error", (done) => { + // setup + AuthorizationController.prototype.getAccessTokenUsingAuthCode.callsArgWith(1, TEST_ERROR_MESSAGE); + AuthorizationController.prototype.getAuthorizeUrl.returns("authorizeUrl"); + ui.getAuthCode.callsArgWith(0, null, TEST_AUTH_CODE); + + // call + askProfileSetupHelper.setupAskToken(TEST_CONFIG, (error, accessToken) => { + // verify + expect(error).eq(TEST_ERROR_MESSAGE); + expect(accessToken).eq(undefined); + expect(infoStub.args[0][0]).eq(`Paste the following url to your browser:\n ${TEST_AUTHORIZE_URL}`); + done(); + }); + }); - afterEach(() => { - sinon.restore(); - }); + afterEach(() => { + sinon.restore(); }); + }); - describe('# test setupVendorId', () => { - const smapiClient = new SmapiClient({ - profile: TEST_PROFILE, - doDebug: TEST_DO_DEBUG + describe("# test setupVendorId", () => { + const smapiClient = new SmapiClient({ + profile: TEST_PROFILE, + doDebug: TEST_DO_DEBUG, + }); + const EMPTY_RESPONSE_BODY = "{}"; + + smapiClient.testFunc = () => {}; + let stubTestFunc; + + describe("# test _getVendorInfo", () => { + beforeEach(() => { + sinon.stub(httpClient, "request"); + sinon.stub(AuthorizationController.prototype, "tokenRefreshAndRead"); + stubTestFunc = sinon.stub(smapiClient, "testFunc"); + AuthorizationController.prototype.tokenRefreshAndRead.callsArgWith(1, null, "refresh_token"); + }); + + it("| returns valid vendorID, one vendorID present", (done) => { + // setup + httpClient.request.callsArgWith(3, null, {statusCode: 200, body: TEST_VENDOR_HTTP_RESPONSE_BODY}); + stubTestFunc.callsArgWith(0, null, {statusCode: 200, body: TEST_VENDOR_HTTP_RESPONSE_BODY}); + + // call + askProfileSetupHelper.setupVendorId(TEST_CONFIG, (err, vendorId) => { + // verify + expect(err).eq(null); + expect(vendorId).eq(TEST_VENDOR_ID_1); + done(); }); - const EMPTY_RESPONSE_BODY = '{}'; - - smapiClient.testFunc = () => {}; - let stubTestFunc; - - describe('# test _getVendorInfo', () => { - beforeEach(() => { - sinon.stub(httpClient, 'request'); - sinon.stub(AuthorizationController.prototype, 'tokenRefreshAndRead'); - stubTestFunc = sinon.stub(smapiClient, 'testFunc'); - AuthorizationController.prototype.tokenRefreshAndRead.callsArgWith(1, null, 'refresh_token'); - }); - - it('| returns valid vendorID, one vendorID present', (done) => { - // setup - httpClient.request.callsArgWith(3, null, { statusCode: 200, body: TEST_VENDOR_HTTP_RESPONSE_BODY }); - stubTestFunc.callsArgWith(0, null, { statusCode: 200, body: TEST_VENDOR_HTTP_RESPONSE_BODY }); - - // call - askProfileSetupHelper.setupVendorId(TEST_CONFIG, (err, vendorId) => { - // verify - expect(err).eq(null); - expect(vendorId).eq(TEST_VENDOR_ID_1); - done(); - }); - }); - - it('| throws error: smapi client returns error', (done) => { - // setup - httpClient.request.callsArgWith(3, TEST_ERROR_MESSAGE, {}); - stubTestFunc.callsArgWith(0, TEST_ERROR_MESSAGE, {}); - - // call - askProfileSetupHelper.setupVendorId(TEST_CONFIG, (err, vendorId) => { - // verify - expect(err).eq(TEST_ERROR_MESSAGE); - expect(vendorId).eq(undefined); - done(); - }); - }); - - it('| throws error: status code greater than or equal to 300', (done) => { - // setup - sinon.stub(jsonView, 'toString'); - jsonView.toString.withArgs(sinon.match.any).returns(TEST_ERROR_MESSAGE); - httpClient.request.callsArgWith(3, null, { statusCode: 300, body: EMPTY_RESPONSE_BODY }); - stubTestFunc.callsArgWith(0, null, { statusCode: 300, body: EMPTY_RESPONSE_BODY }); - - // call - askProfileSetupHelper.setupVendorId(TEST_CONFIG, (err, vendorId) => { - // verify - expect(err).eq(TEST_ERROR_MESSAGE); - expect(vendorId).eq(undefined); - done(); - }); - }); - - afterEach(() => { - sinon.restore(); - }); + }); + + it("| throws error: smapi client returns error", (done) => { + // setup + httpClient.request.callsArgWith(3, TEST_ERROR_MESSAGE, {}); + stubTestFunc.callsArgWith(0, TEST_ERROR_MESSAGE, {}); + + // call + askProfileSetupHelper.setupVendorId(TEST_CONFIG, (err, vendorId) => { + // verify + expect(err).eq(TEST_ERROR_MESSAGE); + expect(vendorId).eq(undefined); + done(); }); + }); + + it("| throws error: status code greater than or equal to 300", (done) => { + // setup + sinon.stub(jsonView, "toString"); + jsonView.toString.withArgs(sinon.match.any).returns(TEST_ERROR_MESSAGE); + httpClient.request.callsArgWith(3, null, {statusCode: 300, body: EMPTY_RESPONSE_BODY}); + stubTestFunc.callsArgWith(0, null, {statusCode: 300, body: EMPTY_RESPONSE_BODY}); + + // call + askProfileSetupHelper.setupVendorId(TEST_CONFIG, (err, vendorId) => { + // verify + expect(err).eq(TEST_ERROR_MESSAGE); + expect(vendorId).eq(undefined); + done(); + }); + }); + + afterEach(() => { + sinon.restore(); + }); + }); - describe('# test _selectVendorId', () => { - beforeEach(() => { - sinon.stub(httpClient, 'request'); - sinon.stub(AuthorizationController.prototype, 'tokenRefreshAndRead'); - stubTestFunc = sinon.stub(smapiClient, 'testFunc'); - AuthorizationController.prototype.tokenRefreshAndRead.callsArgWith(1, null, 'refresh_token'); - }); - - it('| throws error: no vendorInfo present', (done) => { - // setup - httpClient.request.callsArgWith(3, null, { body: {} }); - stubTestFunc.callsArgWith(0, TEST_ERROR_MESSAGE, { body: {} }); - - // call - askProfileSetupHelper.setupVendorId(TEST_CONFIG, (err, vendorId) => { - // verify - expect(err).eq(messages.VENDOR_INFO_FETCH_ERROR); - expect(vendorId).eq(undefined); - done(); - }); - }); - - it('| throws error: no vendorIDs present', (done) => { - // setup - httpClient.request.callsArgWith(3, null, { body: TEST_EMPTY_VENDOR_HTTP_RESPONSE_BODY }); - stubTestFunc.callsArgWith(0, TEST_ERROR_MESSAGE, { body: TEST_EMPTY_VENDOR_HTTP_RESPONSE_BODY }); - - // call - askProfileSetupHelper.setupVendorId(TEST_CONFIG, (err, vendorId) => { - // verify - expect(err).eq(messages.VENDOR_ID_CREATE_INSTRUCTIONS); - expect(vendorId).eq(undefined); - done(); - }); - }); - - it('| returns valid vendorID: multiple vendorIDs present', (done) => { - // setup - sinon.stub(ui, 'chooseVendorId'); - ui.chooseVendorId.callsArgWith(2, null, TEST_VENDOR_ID_2); - httpClient.request.callsArgWith(3, null, { body: TEST_MULTIPLE_VENDORS_HTTP_RESPONSE_BODY }); - stubTestFunc.callsArgWith(0, TEST_ERROR_MESSAGE, { body: TEST_MULTIPLE_VENDORS_HTTP_RESPONSE_BODY }); - - // call - askProfileSetupHelper.setupVendorId(TEST_CONFIG, (err, vendorId) => { - // verify - expect(err).eq(null); - expect(vendorId).eq(TEST_VENDOR_ID_2); - done(); - }); - }); - - it('| throws error: vendorId selection component throws error', (done) => { - // setup - sinon.stub(ui, 'chooseVendorId'); - ui.chooseVendorId.callsArgWith(2, TEST_ERROR_MESSAGE, null); - httpClient.request.callsArgWith(3, null, { body: TEST_MULTIPLE_VENDORS_HTTP_RESPONSE_BODY }); - stubTestFunc.callsArgWith(0, TEST_ERROR_MESSAGE, { body: TEST_MULTIPLE_VENDORS_HTTP_RESPONSE_BODY }); - - // call - askProfileSetupHelper.setupVendorId(TEST_CONFIG, (err, vendorId) => { - // verify - expect(err).eq(TEST_ERROR_MESSAGE); - expect(vendorId).eq(undefined); - done(); - }); - }); - - afterEach(() => { - sinon.restore(); - }); + describe("# test _selectVendorId", () => { + beforeEach(() => { + sinon.stub(httpClient, "request"); + sinon.stub(AuthorizationController.prototype, "tokenRefreshAndRead"); + stubTestFunc = sinon.stub(smapiClient, "testFunc"); + AuthorizationController.prototype.tokenRefreshAndRead.callsArgWith(1, null, "refresh_token"); + }); + + it("| throws error: no vendorInfo present", (done) => { + // setup + httpClient.request.callsArgWith(3, null, {body: {}}); + stubTestFunc.callsArgWith(0, TEST_ERROR_MESSAGE, {body: {}}); + + // call + askProfileSetupHelper.setupVendorId(TEST_CONFIG, (err, vendorId) => { + // verify + expect(err).eq(messages.VENDOR_INFO_FETCH_ERROR); + expect(vendorId).eq(undefined); + done(); + }); + }); + + it("| throws error: no vendorIDs present", (done) => { + // setup + httpClient.request.callsArgWith(3, null, {body: TEST_EMPTY_VENDOR_HTTP_RESPONSE_BODY}); + stubTestFunc.callsArgWith(0, TEST_ERROR_MESSAGE, {body: TEST_EMPTY_VENDOR_HTTP_RESPONSE_BODY}); + + // call + askProfileSetupHelper.setupVendorId(TEST_CONFIG, (err, vendorId) => { + // verify + expect(err).eq(messages.VENDOR_ID_CREATE_INSTRUCTIONS); + expect(vendorId).eq(undefined); + done(); + }); + }); + + it("| returns valid vendorID: multiple vendorIDs present", (done) => { + // setup + sinon.stub(ui, "chooseVendorId"); + ui.chooseVendorId.callsArgWith(2, null, TEST_VENDOR_ID_2); + httpClient.request.callsArgWith(3, null, {body: TEST_MULTIPLE_VENDORS_HTTP_RESPONSE_BODY}); + stubTestFunc.callsArgWith(0, TEST_ERROR_MESSAGE, {body: TEST_MULTIPLE_VENDORS_HTTP_RESPONSE_BODY}); + + // call + askProfileSetupHelper.setupVendorId(TEST_CONFIG, (err, vendorId) => { + // verify + expect(err).eq(null); + expect(vendorId).eq(TEST_VENDOR_ID_2); + done(); }); + }); + + it("| throws error: vendorId selection component throws error", (done) => { + // setup + sinon.stub(ui, "chooseVendorId"); + ui.chooseVendorId.callsArgWith(2, TEST_ERROR_MESSAGE, null); + httpClient.request.callsArgWith(3, null, {body: TEST_MULTIPLE_VENDORS_HTTP_RESPONSE_BODY}); + stubTestFunc.callsArgWith(0, TEST_ERROR_MESSAGE, {body: TEST_MULTIPLE_VENDORS_HTTP_RESPONSE_BODY}); + + // call + askProfileSetupHelper.setupVendorId(TEST_CONFIG, (err, vendorId) => { + // verify + expect(err).eq(TEST_ERROR_MESSAGE); + expect(vendorId).eq(undefined); + done(); + }); + }); + + afterEach(() => { + sinon.restore(); + }); }); + }); }); diff --git a/test/unit/commands/configure/aws-profile-setup-helper-test.js b/test/unit/commands/configure/aws-profile-setup-helper-test.js index bf8d8c77..cd0a4ad7 100644 --- a/test/unit/commands/configure/aws-profile-setup-helper-test.js +++ b/test/unit/commands/configure/aws-profile-setup-helper-test.js @@ -1,319 +1,323 @@ -const { expect } = require('chai'); -const sinon = require('sinon'); -const awsProfileHandler = require('aws-profile-handler'); -const fs = require('fs-extra'); -const path = require('path'); -const querystring = require('querystring'); -const proxyquire = require('proxyquire'); +const {expect} = require("chai"); +const sinon = require("sinon"); +const awsProfileHandler = require("aws-profile-handler"); +const fs = require("fs-extra"); +const path = require("path"); +const querystring = require("querystring"); +const proxyquire = require("proxyquire"); -const awsProfileSetupHelper = require('@src/commands/configure/aws-profile-setup-helper'); -const messages = require('@src/commands/configure/messages'); -const ui = require('@src/commands/configure/ui'); -const CONSTANTS = require('@src/utils/constants'); -const profileHelper = require('@src/utils/profile-helper'); -const stringUtils = require('@src/utils/string-utils'); -const Messenger = require('@src/view/messenger'); +const awsProfileSetupHelper = require("../../../../lib/commands/configure/aws-profile-setup-helper"); +const messages = require("../../../../lib/commands/configure/messages"); +const ui = require("../../../../lib/commands/configure/ui"); +const CONSTANTS = require("../../../../lib/utils/constants"); +const profileHelper = require("../../../../lib/utils/profile-helper"); +const stringUtils = require("../../../../lib/utils/string-utils"); +const Messenger = require("../../../../lib/view/messenger"); -describe('Command: Configure - AWS profile setup helper test', () => { - const TEST_PROFILE = 'testAwsProfile'; - const TEST_DO_DEBUG = false; - const TEST_NEED_BROWSER = false; - const TEST_CONFIG_PATH = '~/.aws/credentials'; - const TEST_CONFIG = { - askProfile: TEST_PROFILE, - needBrowser: TEST_NEED_BROWSER, - debug: TEST_DO_DEBUG - }; - const TEST_ERROR_MESSAGE = 'errorThrown'; - const TEST_NEW_AWS_PROFILE_NAME = 'newProfileName'; - const TEST_PARAMS = { - accessKey: true, - step: 'review', - userNames: `ask-cli-${TEST_NEW_AWS_PROFILE_NAME}`, - permissionType: 'policies', - policies: [ - CONSTANTS.AWS.IAM.USER.POLICY_ARN.IAM_FULL, - CONSTANTS.AWS.IAM.USER.POLICY_ARN.CFN_FULL, - CONSTANTS.AWS.IAM.USER.POLICY_ARN.S3_FULL, - CONSTANTS.AWS.IAM.USER.POLICY_ARN.LAMBDA_FULL, - CONSTANTS.AWS.IAM.USER.POLICY_ARN.CLOUD_WATCH_FULL - ] - }; - const TEST_CREDENTIALS = { aws_access_key_id: 'accessKeyId', aws_secret_access_key: 'secretAccessKey' }; +describe("Command: Configure - AWS profile setup helper test", () => { + const TEST_PROFILE = "testAwsProfile"; + const TEST_DO_DEBUG = false; + const TEST_NEED_BROWSER = false; + const TEST_CONFIG_PATH = "~/.aws/credentials"; + const TEST_CONFIG = { + askProfile: TEST_PROFILE, + needBrowser: TEST_NEED_BROWSER, + debug: TEST_DO_DEBUG, + }; + const TEST_ERROR_MESSAGE = "errorThrown"; + const TEST_NEW_AWS_PROFILE_NAME = "newProfileName"; + const TEST_PARAMS = { + accessKey: true, + step: "review", + userNames: `ask-cli-${TEST_NEW_AWS_PROFILE_NAME}`, + permissionType: "policies", + policies: [ + CONSTANTS.AWS.IAM.USER.POLICY_ARN.IAM_FULL, + CONSTANTS.AWS.IAM.USER.POLICY_ARN.CFN_FULL, + CONSTANTS.AWS.IAM.USER.POLICY_ARN.S3_FULL, + CONSTANTS.AWS.IAM.USER.POLICY_ARN.LAMBDA_FULL, + CONSTANTS.AWS.IAM.USER.POLICY_ARN.CLOUD_WATCH_FULL, + ], + }; + const TEST_CREDENTIALS = {aws_access_key_id: "accessKeyId", aws_secret_access_key: "secretAccessKey"}; - describe('# test setupAwsProfile', () => { - beforeEach(() => { - sinon.stub(fs, 'existsSync').returns(true); - sinon.stub(path, 'join').returns(TEST_CONFIG_PATH); - }); + describe("# test setupAwsProfile", () => { + beforeEach(() => { + sinon.stub(fs, "existsSync").returns(true); + sinon.stub(path, "join").returns(TEST_CONFIG_PATH); + }); - afterEach(() => { - sinon.restore(); - }); + afterEach(() => { + sinon.restore(); + }); - it('| returns error, awsProfileHandler listProfiles function throws error, expect error called back ', (done) => { - // setup - sinon.stub(awsProfileHandler, 'listProfiles').throws(new Error(TEST_ERROR_MESSAGE)); - // call - awsProfileSetupHelper.setupAwsProfile(TEST_CONFIG, (err, awsProfile) => { - // verify - expect(err.message).eq(TEST_ERROR_MESSAGE); - expect(awsProfile).eq(undefined); - done(); - }); - }); + it("| returns error, awsProfileHandler listProfiles function throws error, expect error called back ", (done) => { + // setup + sinon.stub(awsProfileHandler, "listProfiles").throws(new Error(TEST_ERROR_MESSAGE)); + // call + awsProfileSetupHelper.setupAwsProfile(TEST_CONFIG, (err, awsProfile) => { + // verify + expect(err.message).eq(TEST_ERROR_MESSAGE); + expect(awsProfile).eq(undefined); + done(); + }); + }); - describe('# test _initiateAwsProfileSetup', () => { - it('| returns error, ui confirmSettingAws fails', (done) => { - // setup - sinon.stub(ui, 'confirmSettingAws').callsArgWith(0, TEST_ERROR_MESSAGE); - sinon.stub(awsProfileHandler, 'listProfiles').returns([TEST_PROFILE]); + describe("# test _initiateAwsProfileSetup", () => { + it("| returns error, ui confirmSettingAws fails", (done) => { + // setup + sinon.stub(ui, "confirmSettingAws").callsArgWith(0, TEST_ERROR_MESSAGE); + sinon.stub(awsProfileHandler, "listProfiles").returns([TEST_PROFILE]); - // call - awsProfileSetupHelper.setupAwsProfile(TEST_CONFIG, (err, awsProfile) => { - // verify - expect(err).eq(TEST_ERROR_MESSAGE); - expect(awsProfile).eq(TEST_ERROR_MESSAGE); - done(); - }); - }); + // call + awsProfileSetupHelper.setupAwsProfile(TEST_CONFIG, (err, awsProfile) => { + // verify + expect(err).eq(TEST_ERROR_MESSAGE); + expect(awsProfile).eq(TEST_ERROR_MESSAGE); + done(); + }); + }); - it('| returns error due to invalid setup choice', (done) => { - // setup - const infoStub = sinon.stub(); - sinon.stub(Messenger, 'getInstance').returns({ - info: infoStub - }); - sinon.stub(ui, 'confirmSettingAws').callsArgWith(0, null, null); - sinon.stub(awsProfileHandler, 'listProfiles').returns([TEST_PROFILE]); + it("| returns error due to invalid setup choice", (done) => { + // setup + const infoStub = sinon.stub(); + sinon.stub(Messenger, "getInstance").returns({ + info: infoStub, + }); + sinon.stub(ui, "confirmSettingAws").callsArgWith(0, null, null); + sinon.stub(awsProfileHandler, "listProfiles").returns([TEST_PROFILE]); - // call - awsProfileSetupHelper.setupAwsProfile(TEST_CONFIG, (err, awsProfile) => { - // verify - expect(infoStub.args[0][0]).eq(messages.SKIP_AWS_CONFIGURATION); - expect(err).eq(undefined); - expect(awsProfile).eq(undefined); - done(); - }); - }); + // call + awsProfileSetupHelper.setupAwsProfile(TEST_CONFIG, (err, awsProfile) => { + // verify + expect(infoStub.args[0][0]).eq(messages.SKIP_AWS_CONFIGURATION); + expect(err).eq(undefined); + expect(awsProfile).eq(undefined); + done(); + }); + }); - describe('# test _handleEnvironmentVariableAwsSetup', () => { - it('| returns error, ui selectEnvironmentVariables fails', (done) => { - // setup - sinon.stub(stringUtils, 'isNonBlankString').returns(true); - sinon.stub(ui, 'confirmSettingAws').callsArgWith(0, null, true); - sinon.stub(ui, 'selectEnvironmentVariables').callsArgWith(0, TEST_ERROR_MESSAGE); - sinon.stub(awsProfileHandler, 'listProfiles').returns([TEST_PROFILE]); + describe("# test _handleEnvironmentVariableAwsSetup", () => { + it("| returns error, ui selectEnvironmentVariables fails", (done) => { + // setup + sinon.stub(stringUtils, "isNonBlankString").returns(true); + sinon.stub(ui, "confirmSettingAws").callsArgWith(0, null, true); + sinon.stub(ui, "selectEnvironmentVariables").callsArgWith(0, TEST_ERROR_MESSAGE); + sinon.stub(awsProfileHandler, "listProfiles").returns([TEST_PROFILE]); - // call - awsProfileSetupHelper.setupAwsProfile(TEST_CONFIG, (err, awsProfile) => { - // verify - expect(err).eq(TEST_ERROR_MESSAGE); - expect(awsProfile).eq(TEST_ERROR_MESSAGE); - done(); - }); - }); + // call + awsProfileSetupHelper.setupAwsProfile(TEST_CONFIG, (err, awsProfile) => { + // verify + expect(err).eq(TEST_ERROR_MESSAGE); + expect(awsProfile).eq(TEST_ERROR_MESSAGE); + done(); + }); + }); - it('| returns error, setup choice is Yes', (done) => { - // setup - sinon.stub(stringUtils, 'isNonBlankString').returns(true); - sinon.stub(ui, 'confirmSettingAws').callsArgWith(0, null, true); - sinon.stub(ui, 'selectEnvironmentVariables').callsArgWith(0, null, 'Yes'); - sinon.stub(awsProfileHandler, 'listProfiles').returns([TEST_PROFILE]); - sinon.stub(profileHelper, 'setupProfile'); + it("| returns error, setup choice is Yes", (done) => { + // setup + sinon.stub(stringUtils, "isNonBlankString").returns(true); + sinon.stub(ui, "confirmSettingAws").callsArgWith(0, null, true); + sinon.stub(ui, "selectEnvironmentVariables").callsArgWith(0, null, "Yes"); + sinon.stub(awsProfileHandler, "listProfiles").returns([TEST_PROFILE]); + sinon.stub(profileHelper, "setupProfile"); - // call - awsProfileSetupHelper.setupAwsProfile(TEST_CONFIG, (err, awsProfile) => { - // verify - expect(profileHelper.setupProfile.args[0][0]).eq(CONSTANTS.PLACEHOLDER.ENVIRONMENT_VAR.AWS_CREDENTIALS); - expect(profileHelper.setupProfile.args[0][1]).eq(TEST_PROFILE); - expect(err).eq(null); - expect(awsProfile).eq(CONSTANTS.PLACEHOLDER.ENVIRONMENT_VAR.AWS_CREDENTIALS); - done(); - }); - }); + // call + awsProfileSetupHelper.setupAwsProfile(TEST_CONFIG, (err, awsProfile) => { + // verify + expect(profileHelper.setupProfile.args[0][0]).eq(CONSTANTS.PLACEHOLDER.ENVIRONMENT_VAR.AWS_CREDENTIALS); + expect(profileHelper.setupProfile.args[0][1]).eq(TEST_PROFILE); + expect(err).eq(null); + expect(awsProfile).eq(CONSTANTS.PLACEHOLDER.ENVIRONMENT_VAR.AWS_CREDENTIALS); + done(); + }); + }); - it('| returns error, ui createNewOrSelectAWSProfile fails ', (done) => { - // setup - sinon.stub(stringUtils, 'isNonBlankString').returns(false); - sinon.stub(ui, 'confirmSettingAws').callsArgWith(0, null, true); - sinon.stub(ui, 'selectEnvironmentVariables').callsArgWith(0, TEST_ERROR_MESSAGE); - sinon.stub(ui, 'createNewOrSelectAWSProfile').callsArgWith(1, TEST_ERROR_MESSAGE); - sinon.stub(awsProfileHandler, 'listProfiles').returns([TEST_PROFILE]); + it("| returns error, ui createNewOrSelectAWSProfile fails ", (done) => { + // setup + sinon.stub(stringUtils, "isNonBlankString").returns(false); + sinon.stub(ui, "confirmSettingAws").callsArgWith(0, null, true); + sinon.stub(ui, "selectEnvironmentVariables").callsArgWith(0, TEST_ERROR_MESSAGE); + sinon.stub(ui, "createNewOrSelectAWSProfile").callsArgWith(1, TEST_ERROR_MESSAGE); + sinon.stub(awsProfileHandler, "listProfiles").returns([TEST_PROFILE]); - // call - awsProfileSetupHelper.setupAwsProfile(TEST_CONFIG, (err, awsProfile) => { - // verify - expect(err).eq(TEST_ERROR_MESSAGE); - expect(awsProfile).eq(TEST_ERROR_MESSAGE); - done(); - }); - }); + // call + awsProfileSetupHelper.setupAwsProfile(TEST_CONFIG, (err, awsProfile) => { + // verify + expect(err).eq(TEST_ERROR_MESSAGE); + expect(awsProfile).eq(TEST_ERROR_MESSAGE); + done(); + }); + }); - it('| returns awsProfile, user chooses existing profile ', (done) => { - // setup - sinon.stub(stringUtils, 'isNonBlankString').returns(false); - sinon.stub(ui, 'confirmSettingAws').callsArgWith(0, null, true); - sinon.stub(ui, 'selectEnvironmentVariables').callsArgWith(0, TEST_ERROR_MESSAGE); - sinon.stub(ui, 'createNewOrSelectAWSProfile').callsArgWith(1, null, 'existing_profile'); - sinon.stub(awsProfileHandler, 'listProfiles').returns([TEST_PROFILE]); - sinon.stub(profileHelper, 'setupProfile'); + it("| returns awsProfile, user chooses existing profile ", (done) => { + // setup + sinon.stub(stringUtils, "isNonBlankString").returns(false); + sinon.stub(ui, "confirmSettingAws").callsArgWith(0, null, true); + sinon.stub(ui, "selectEnvironmentVariables").callsArgWith(0, TEST_ERROR_MESSAGE); + sinon.stub(ui, "createNewOrSelectAWSProfile").callsArgWith(1, null, "existing_profile"); + sinon.stub(awsProfileHandler, "listProfiles").returns([TEST_PROFILE]); + sinon.stub(profileHelper, "setupProfile"); - // call - awsProfileSetupHelper.setupAwsProfile(TEST_CONFIG, (err, awsProfile) => { - // verify - expect(profileHelper.setupProfile.args[0][0]).eq('existing_profile'); - expect(profileHelper.setupProfile.args[0][1]).eq(TEST_PROFILE); - expect(err).eq(null); - expect(awsProfile).eq('existing_profile'); - done(); - }); - }); - }); + // call + awsProfileSetupHelper.setupAwsProfile(TEST_CONFIG, (err, awsProfile) => { + // verify + expect(profileHelper.setupProfile.args[0][0]).eq("existing_profile"); + expect(profileHelper.setupProfile.args[0][1]).eq(TEST_PROFILE); + expect(err).eq(null); + expect(awsProfile).eq("existing_profile"); + done(); + }); }); + }); }); + }); - describe('# test _createAwsProfileFlow', () => { - afterEach(() => { - sinon.restore(); - }); + describe("# test _createAwsProfileFlow", () => { + afterEach(() => { + sinon.restore(); + }); - it('| fs ensureFileSync throws error', (done) => { - // setup - sinon.stub(path, 'join').returns(TEST_CONFIG_PATH); - sinon.stub(fs, 'existsSync').returns(false); - sinon.stub(fs, 'ensureFileSync').throws(new Error(TEST_ERROR_MESSAGE)); - sinon.stub(stringUtils, 'isNonBlankString').returns(false); - sinon.stub(ui, 'confirmSettingAws').callsArgWith(0, null, true); + it("| fs ensureFileSync throws error", (done) => { + // setup + sinon.stub(path, "join").returns(TEST_CONFIG_PATH); + sinon.stub(fs, "existsSync").returns(false); + sinon.stub(fs, "ensureFileSync").throws(new Error(TEST_ERROR_MESSAGE)); + sinon.stub(stringUtils, "isNonBlankString").returns(false); + sinon.stub(ui, "confirmSettingAws").callsArgWith(0, null, true); - // call - awsProfileSetupHelper.setupAwsProfile(TEST_CONFIG, (err) => { - // verify - expect(err.message).eq(TEST_ERROR_MESSAGE); - done(); - }); - }); + // call + awsProfileSetupHelper.setupAwsProfile(TEST_CONFIG, (err) => { + // verify + expect(err.message).eq(TEST_ERROR_MESSAGE); + done(); + }); + }); - it('| returns valid awsProfile ', (done) => { - // setup - const DEFAULT_AWS_PROFILE = 'ask_cli_default'; - const openStub = sinon.stub(); - const proxyHelper = proxyquire('@src/commands/configure/aws-profile-setup-helper', { - open: openStub - }); - const infoStub = sinon.stub(); - sinon.stub(Messenger, 'getInstance').returns({ - info: infoStub - }); - sinon.stub(fs, 'existsSync').returns(false); - sinon.stub(fs, 'ensureFileSync'); - sinon.stub(fs, 'chmodSync'); - sinon.stub(stringUtils, 'isNonBlankString').returns(false); - sinon.stub(ui, 'confirmSettingAws').callsArgWith(0, null, true); - sinon.stub(ui, 'addNewCredentials').callsArgWith(0, null, TEST_CREDENTIALS); - sinon.stub(awsProfileHandler, 'addProfile'); - sinon.stub(profileHelper, 'setupProfile'); + it("| returns valid awsProfile ", (done) => { + // setup + const DEFAULT_AWS_PROFILE = "ask_cli_default"; + const openStub = sinon.stub(); + const proxyHelper = proxyquire("../../../../lib/commands/configure/aws-profile-setup-helper", { + open: openStub, + }); + const infoStub = sinon.stub(); + sinon.stub(Messenger, "getInstance").returns({ + info: infoStub, + }); + sinon.stub(fs, "existsSync").returns(false); + sinon.stub(fs, "ensureFileSync"); + sinon.stub(fs, "chmodSync"); + sinon.stub(stringUtils, "isNonBlankString").returns(false); + sinon.stub(ui, "confirmSettingAws").callsArgWith(0, null, true); + sinon.stub(ui, "addNewCredentials").callsArgWith(0, null, TEST_CREDENTIALS); + sinon.stub(awsProfileHandler, "addProfile"); + sinon.stub(profileHelper, "setupProfile"); - // call - proxyHelper.setupAwsProfile({ askProfile: TEST_PROFILE, needBrowser: true }, (err, awsProfile) => { - // verify - expect(awsProfileHandler.addProfile.args[0][0]).eq(DEFAULT_AWS_PROFILE); - expect(awsProfileHandler.addProfile.args[0][1]).to.deep.eq(TEST_CREDENTIALS); - expect(profileHelper.setupProfile.args[0][0]).eq(DEFAULT_AWS_PROFILE); - expect(profileHelper.setupProfile.args[0][1]).eq(TEST_PROFILE); - expect(infoStub.args[0][0]).eq(messages.AWS_CREATE_PROFILE_TITLE); - expect(infoStub.args[1][0]).eq(`\nAWS profile "${DEFAULT_AWS_PROFILE}" was successfully created. The details are recorded in aws credentials file (.aws/credentials) located at your **HOME** folder.`); - expect(err).eq(null); - expect(awsProfile).eq(DEFAULT_AWS_PROFILE); - done(); - }); - }); + // call + proxyHelper.setupAwsProfile({askProfile: TEST_PROFILE, needBrowser: true}, (err, awsProfile) => { + // verify + expect(awsProfileHandler.addProfile.args[0][0]).eq(DEFAULT_AWS_PROFILE); + expect(awsProfileHandler.addProfile.args[0][1]).to.deep.eq(TEST_CREDENTIALS); + expect(profileHelper.setupProfile.args[0][0]).eq(DEFAULT_AWS_PROFILE); + expect(profileHelper.setupProfile.args[0][1]).eq(TEST_PROFILE); + expect(infoStub.args[0][0]).eq(messages.AWS_CREATE_PROFILE_TITLE); + expect(infoStub.args[1][0]).eq( + `\nAWS profile "${DEFAULT_AWS_PROFILE}" was successfully created. The details are recorded in aws credentials file (.aws/credentials) located at your **HOME** folder.`, + ); + expect(err).eq(null); + expect(awsProfile).eq(DEFAULT_AWS_PROFILE); + done(); + }); + }); - it('| returns error, ui requestAwsProfileName fails ', (done) => { - // setup - sinon.stub(path, 'join').returns(TEST_CONFIG_PATH); - sinon.stub(stringUtils, 'isNonBlankString').returns(true); - sinon.stub(ui, 'confirmSettingAws').callsArgWith(0, null, true); - sinon.stub(ui, 'selectEnvironmentVariables').callsArgWith(0, null, 'No'); - sinon.stub(ui, 'createNewOrSelectAWSProfile').callsArgWith(1, null, 'Create new profile'); - sinon.stub(ui, 'requestAwsProfileName').callsArgWith(1, TEST_ERROR_MESSAGE); - sinon.stub(awsProfileHandler, 'listProfiles').returns([TEST_PROFILE]); - sinon.stub(fs, 'ensureFileSync'); - sinon.stub(fs, 'chmodSync'); - sinon.stub(fs, 'existsSync').returns(true); + it("| returns error, ui requestAwsProfileName fails ", (done) => { + // setup + sinon.stub(path, "join").returns(TEST_CONFIG_PATH); + sinon.stub(stringUtils, "isNonBlankString").returns(true); + sinon.stub(ui, "confirmSettingAws").callsArgWith(0, null, true); + sinon.stub(ui, "selectEnvironmentVariables").callsArgWith(0, null, "No"); + sinon.stub(ui, "createNewOrSelectAWSProfile").callsArgWith(1, null, "Create new profile"); + sinon.stub(ui, "requestAwsProfileName").callsArgWith(1, TEST_ERROR_MESSAGE); + sinon.stub(awsProfileHandler, "listProfiles").returns([TEST_PROFILE]); + sinon.stub(fs, "ensureFileSync"); + sinon.stub(fs, "chmodSync"); + sinon.stub(fs, "existsSync").returns(true); - // call - awsProfileSetupHelper.setupAwsProfile(TEST_CONFIG, (err) => { - // verify - expect(err).eq(TEST_ERROR_MESSAGE); - done(); - }); - }); + // call + awsProfileSetupHelper.setupAwsProfile(TEST_CONFIG, (err) => { + // verify + expect(err).eq(TEST_ERROR_MESSAGE); + done(); + }); + }); - it('| returns error, ui addNewCredentials fails ', (done) => { - // setup - sinon.stub(path, 'join').returns(TEST_CONFIG_PATH); - const infoStub = sinon.stub(); - sinon.stub(Messenger, 'getInstance').returns({ - info: infoStub - }); - sinon.stub(stringUtils, 'isNonBlankString').returns(true); - sinon.stub(ui, 'confirmSettingAws').callsArgWith(0, null, true); - sinon.stub(ui, 'selectEnvironmentVariables').callsArgWith(0, null, 'No'); - sinon.stub(ui, 'createNewOrSelectAWSProfile').callsArgWith(1, null, 'Create new profile'); - sinon.stub(ui, 'requestAwsProfileName').callsArgWith(1, null, TEST_NEW_AWS_PROFILE_NAME); - sinon.stub(ui, 'addNewCredentials').callsArgWith(0, TEST_ERROR_MESSAGE); - sinon.stub(awsProfileHandler, 'listProfiles').returns([TEST_PROFILE]); - sinon.stub(fs, 'ensureFileSync'); - sinon.stub(fs, 'chmodSync'); - sinon.stub(fs, 'existsSync').returns(true); + it("| returns error, ui addNewCredentials fails ", (done) => { + // setup + sinon.stub(path, "join").returns(TEST_CONFIG_PATH); + const infoStub = sinon.stub(); + sinon.stub(Messenger, "getInstance").returns({ + info: infoStub, + }); + sinon.stub(stringUtils, "isNonBlankString").returns(true); + sinon.stub(ui, "confirmSettingAws").callsArgWith(0, null, true); + sinon.stub(ui, "selectEnvironmentVariables").callsArgWith(0, null, "No"); + sinon.stub(ui, "createNewOrSelectAWSProfile").callsArgWith(1, null, "Create new profile"); + sinon.stub(ui, "requestAwsProfileName").callsArgWith(1, null, TEST_NEW_AWS_PROFILE_NAME); + sinon.stub(ui, "addNewCredentials").callsArgWith(0, TEST_ERROR_MESSAGE); + sinon.stub(awsProfileHandler, "listProfiles").returns([TEST_PROFILE]); + sinon.stub(fs, "ensureFileSync"); + sinon.stub(fs, "chmodSync"); + sinon.stub(fs, "existsSync").returns(true); - // call - awsProfileSetupHelper.setupAwsProfile(TEST_CONFIG, (err) => { - // verify - expect(infoStub.args[0][0]).eq(messages.AWS_CREATE_PROFILE_TITLE); - expect(infoStub.args[1][0]).eq(messages.AWS_CREATE_PROFILE_NO_BROWSER_OPEN_BROWSER); - expect(infoStub.args[2][0]).eq(` ${CONSTANTS.AWS.IAM.USER.NEW_USER_BASE_URL}${querystring.stringify(TEST_PARAMS)}`); - done(); - }); - }); + // call + awsProfileSetupHelper.setupAwsProfile(TEST_CONFIG, (err) => { + // verify + expect(infoStub.args[0][0]).eq(messages.AWS_CREATE_PROFILE_TITLE); + expect(infoStub.args[1][0]).eq(messages.AWS_CREATE_PROFILE_NO_BROWSER_OPEN_BROWSER); + expect(infoStub.args[2][0]).eq(` ${CONSTANTS.AWS.IAM.USER.NEW_USER_BASE_URL}${querystring.stringify(TEST_PARAMS)}`); + done(); + }); + }); - it('| successfully added awsProfile and credentials ', (done) => { - // setup - sinon.stub(path, 'join').returns(TEST_CONFIG_PATH); - const infoStub = sinon.stub(); - sinon.stub(Messenger, 'getInstance').returns({ - info: infoStub - }); - sinon.stub(stringUtils, 'isNonBlankString').returns(true); - sinon.stub(ui, 'confirmSettingAws').callsArgWith(0, null, true); - sinon.stub(ui, 'selectEnvironmentVariables').callsArgWith(0, null, 'No'); - sinon.stub(ui, 'createNewOrSelectAWSProfile').callsArgWith(1, null, 'Create new profile'); - sinon.stub(ui, 'requestAwsProfileName').callsArgWith(1, null, TEST_NEW_AWS_PROFILE_NAME); - sinon.stub(ui, 'addNewCredentials').callsArgWith(0, null, TEST_CREDENTIALS); - sinon.stub(awsProfileHandler, 'listProfiles').returns([TEST_PROFILE]); - sinon.stub(fs, 'ensureFileSync'); - sinon.stub(fs, 'chmodSync'); - sinon.stub(fs, 'existsSync').returns(true); - sinon.stub(awsProfileHandler, 'addProfile'); - sinon.stub(profileHelper, 'setupProfile'); + it("| successfully added awsProfile and credentials ", (done) => { + // setup + sinon.stub(path, "join").returns(TEST_CONFIG_PATH); + const infoStub = sinon.stub(); + sinon.stub(Messenger, "getInstance").returns({ + info: infoStub, + }); + sinon.stub(stringUtils, "isNonBlankString").returns(true); + sinon.stub(ui, "confirmSettingAws").callsArgWith(0, null, true); + sinon.stub(ui, "selectEnvironmentVariables").callsArgWith(0, null, "No"); + sinon.stub(ui, "createNewOrSelectAWSProfile").callsArgWith(1, null, "Create new profile"); + sinon.stub(ui, "requestAwsProfileName").callsArgWith(1, null, TEST_NEW_AWS_PROFILE_NAME); + sinon.stub(ui, "addNewCredentials").callsArgWith(0, null, TEST_CREDENTIALS); + sinon.stub(awsProfileHandler, "listProfiles").returns([TEST_PROFILE]); + sinon.stub(fs, "ensureFileSync"); + sinon.stub(fs, "chmodSync"); + sinon.stub(fs, "existsSync").returns(true); + sinon.stub(awsProfileHandler, "addProfile"); + sinon.stub(profileHelper, "setupProfile"); - // call - awsProfileSetupHelper.setupAwsProfile(TEST_CONFIG, (err, awsProfile) => { - // verify - expect(awsProfileHandler.addProfile.args[0][0]).eq(TEST_NEW_AWS_PROFILE_NAME); - expect(awsProfileHandler.addProfile.args[0][1]).to.deep.eq(TEST_CREDENTIALS); - expect(profileHelper.setupProfile.args[0][0]).eq(TEST_NEW_AWS_PROFILE_NAME); - expect(profileHelper.setupProfile.args[0][1]).eq(TEST_PROFILE); - expect(infoStub.args[0][0]).eq(messages.AWS_CREATE_PROFILE_TITLE); - expect(infoStub.args[1][0]).eq(messages.AWS_CREATE_PROFILE_NO_BROWSER_OPEN_BROWSER); - expect(infoStub.args[2][0]).eq(` ${CONSTANTS.AWS.IAM.USER.NEW_USER_BASE_URL}${querystring.stringify(TEST_PARAMS)}`); - expect(infoStub.args[3][0]).eq(`\nAWS profile "${TEST_NEW_AWS_PROFILE_NAME}" was successfully created. The details are recorded in aws credentials file (.aws/credentials) located at your **HOME** folder.`); - expect(err).eq(null); - expect(awsProfile).eq(TEST_NEW_AWS_PROFILE_NAME); + // call + awsProfileSetupHelper.setupAwsProfile(TEST_CONFIG, (err, awsProfile) => { + // verify + expect(awsProfileHandler.addProfile.args[0][0]).eq(TEST_NEW_AWS_PROFILE_NAME); + expect(awsProfileHandler.addProfile.args[0][1]).to.deep.eq(TEST_CREDENTIALS); + expect(profileHelper.setupProfile.args[0][0]).eq(TEST_NEW_AWS_PROFILE_NAME); + expect(profileHelper.setupProfile.args[0][1]).eq(TEST_PROFILE); + expect(infoStub.args[0][0]).eq(messages.AWS_CREATE_PROFILE_TITLE); + expect(infoStub.args[1][0]).eq(messages.AWS_CREATE_PROFILE_NO_BROWSER_OPEN_BROWSER); + expect(infoStub.args[2][0]).eq(` ${CONSTANTS.AWS.IAM.USER.NEW_USER_BASE_URL}${querystring.stringify(TEST_PARAMS)}`); + expect(infoStub.args[3][0]).eq( + `\nAWS profile "${TEST_NEW_AWS_PROFILE_NAME}" was successfully created. The details are recorded in aws credentials file (.aws/credentials) located at your **HOME** folder.`, + ); + expect(err).eq(null); + expect(awsProfile).eq(TEST_NEW_AWS_PROFILE_NAME); - done(); - }); - }); + done(); + }); }); + }); }); diff --git a/test/unit/commands/configure/helper-test.js b/test/unit/commands/configure/helper-test.js index 26ed1120..8340a546 100644 --- a/test/unit/commands/configure/helper-test.js +++ b/test/unit/commands/configure/helper-test.js @@ -1,163 +1,173 @@ -const { expect } = require('chai'); -const sinon = require('sinon'); +const {expect} = require("chai"); +const sinon = require("sinon"); -const askProfileSetupHelper = require('@src/commands/configure/ask-profile-setup-helper'); -const awsProfileSetupHelper = require('@src/commands/configure/aws-profile-setup-helper'); -const messages = require('@src/commands/configure/messages'); -const helper = require('@src/commands/configure/helper'); -const AppConfig = require('@src/model/app-config'); -const Messenger = require('@src/view/messenger'); +const askProfileSetupHelper = require("../../../../lib/commands/configure/ask-profile-setup-helper"); +const awsProfileSetupHelper = require("../../../../lib/commands/configure/aws-profile-setup-helper"); +const messages = require("../../../../lib/commands/configure/messages"); +const helper = require("../../../../lib/commands/configure/helper"); +const AppConfig = require("../../../../lib/model/app-config"); +const Messenger = require("../../../../lib/view/messenger"); -describe('Command: Configure - helper test', () => { - const TEST_PROFILE = 'testProfile'; - const TEST_AWS_PROFILE = 'testAwsProfile'; - const TEST_DO_DEBUG = false; - const TEST_NEED_BROWSER = false; - const TEST_VENDOR_ID = 'testVendorId'; - const TEST_ERROR_MESSAGE = 'errorMessage'; - const TEST_ACCESS_TOKEN = { - access_token: 'access_token', - refresh_token: 'refresh_token', - expires_in: 3600, - expires_at: 'expires_at' - }; - const TEST_CONFIG = { - askProfile: TEST_PROFILE, - needBrowser: TEST_NEED_BROWSER, - debug: TEST_DO_DEBUG - }; - let setTokenStub; - let infoStub; - let warnStub; - let setAwsProfileStub; - let writeStub; - let setVendorIdStub; - describe('# test initiateAskProfileSetup', () => { - beforeEach(() => { - infoStub = sinon.stub(); - warnStub = sinon.stub(); - setAwsProfileStub = sinon.stub(); - setVendorIdStub = sinon.stub(); - writeStub = sinon.stub(); - setTokenStub = sinon.stub(); - sinon.stub(Messenger, 'getInstance').returns({ - info: infoStub, - warn: warnStub - }); - sinon.stub(AppConfig, 'getInstance').returns({ - write: writeStub, - setAwsProfile: setAwsProfileStub, - setToken: setTokenStub, - setVendorId: setVendorIdStub - }); - sinon.stub(askProfileSetupHelper, 'setupAskToken'); - sinon.stub(askProfileSetupHelper, 'setupVendorId'); - sinon.stub(awsProfileSetupHelper, 'setupAwsProfile'); - }); +describe("Command: Configure - helper test", () => { + const TEST_PROFILE = "testProfile"; + const TEST_AWS_PROFILE = "testAwsProfile"; + const TEST_DO_DEBUG = false; + const TEST_NEED_BROWSER = false; + const TEST_VENDOR_ID = "testVendorId"; + const TEST_ERROR_MESSAGE = "errorMessage"; + const TEST_ACCESS_TOKEN = { + access_token: "access_token", + refresh_token: "refresh_token", + expires_in: 3600, + expires_at: "expires_at", + }; + const TEST_CONFIG = { + askProfile: TEST_PROFILE, + needBrowser: TEST_NEED_BROWSER, + debug: TEST_DO_DEBUG, + }; + let setTokenStub; + let infoStub; + let warnStub; + let setAwsProfileStub; + let writeStub; + let setVendorIdStub; + describe("# test initiateAskProfileSetup", () => { + beforeEach(() => { + infoStub = sinon.stub(); + warnStub = sinon.stub(); + setAwsProfileStub = sinon.stub(); + setVendorIdStub = sinon.stub(); + writeStub = sinon.stub(); + setTokenStub = sinon.stub(); + sinon.stub(Messenger, "getInstance").returns({ + info: infoStub, + warn: warnStub, + }); + sinon.stub(AppConfig, "getInstance").returns({ + write: writeStub, + setAwsProfile: setAwsProfileStub, + setToken: setTokenStub, + setVendorId: setVendorIdStub, + }); + sinon.stub(askProfileSetupHelper, "setupAskToken"); + sinon.stub(askProfileSetupHelper, "setupVendorId"); + sinon.stub(awsProfileSetupHelper, "setupAwsProfile"); + }); - it('| setupAskToken returns error', (done) => { - // setup - askProfileSetupHelper.setupAskToken.callsArgWith(1, TEST_ERROR_MESSAGE); + it("| setupAskToken returns error", (done) => { + // setup + askProfileSetupHelper.setupAskToken.callsArgWith(1, TEST_ERROR_MESSAGE); - // call - helper.initiateAskProfileSetup(TEST_CONFIG, (error, askProfile) => { - // verify - expect(warnStub.args[0][0]).eq(messages.LWA_TOKEN_SHARE_WARN_MESSAGE); - expect(error).eq(TEST_ERROR_MESSAGE); - expect(askProfile).eq(undefined); - done(); - }); - }); + // call + helper.initiateAskProfileSetup(TEST_CONFIG, (error, askProfile) => { + // verify + expect(warnStub.args[0][0]).eq(messages.LWA_TOKEN_SHARE_WARN_MESSAGE); + expect(error).eq(TEST_ERROR_MESSAGE); + expect(askProfile).eq(undefined); + done(); + }); + }); - it('| setupAskToken returns valid token and setupVendorId throws error ', (done) => { - // setup - askProfileSetupHelper.setupAskToken.callsArgWith(1, null, TEST_ACCESS_TOKEN); - askProfileSetupHelper.setupVendorId.callsArgWith(1, TEST_ERROR_MESSAGE); + it("| setupAskToken returns valid token and setupVendorId throws error ", (done) => { + // setup + askProfileSetupHelper.setupAskToken.callsArgWith(1, null, TEST_ACCESS_TOKEN); + askProfileSetupHelper.setupVendorId.callsArgWith(1, TEST_ERROR_MESSAGE); - // call - helper.initiateAskProfileSetup(TEST_CONFIG, (error, askProfile) => { - // verify - expect(warnStub.args[0][0]).eq(messages.LWA_TOKEN_SHARE_WARN_MESSAGE); - expect(setTokenStub.args[0][0]).eq(TEST_PROFILE); - expect(setTokenStub.args[0][1]).to.deep.eq(TEST_ACCESS_TOKEN); - expect(infoStub.args[0][0]).eq(`ASK Profile "${TEST_PROFILE}" was successfully created. The details are recorded in ask-cli config file (.ask/cli_config) located at your **HOME** folder.`); - expect(error).eq(TEST_ERROR_MESSAGE); - expect(askProfile).eq(undefined); - done(); - }); - }); + // call + helper.initiateAskProfileSetup(TEST_CONFIG, (error, askProfile) => { + // verify + expect(warnStub.args[0][0]).eq(messages.LWA_TOKEN_SHARE_WARN_MESSAGE); + expect(setTokenStub.args[0][0]).eq(TEST_PROFILE); + expect(setTokenStub.args[0][1]).to.deep.eq(TEST_ACCESS_TOKEN); + expect(infoStub.args[0][0]).eq( + `ASK Profile "${TEST_PROFILE}" was successfully created. The details are recorded in ask-cli config file (.ask/cli_config) located at your **HOME** folder.`, + ); + expect(error).eq(TEST_ERROR_MESSAGE); + expect(askProfile).eq(undefined); + done(); + }); + }); - it('| setupVendorId returns valid vendorId and setupAwsProfile throws error', (done) => { - // setup - askProfileSetupHelper.setupAskToken.callsArgWith(1, null, TEST_ACCESS_TOKEN); - askProfileSetupHelper.setupVendorId.callsArgWith(1, null, TEST_VENDOR_ID); - awsProfileSetupHelper.setupAwsProfile.callsArgWith(1, TEST_ERROR_MESSAGE); + it("| setupVendorId returns valid vendorId and setupAwsProfile throws error", (done) => { + // setup + askProfileSetupHelper.setupAskToken.callsArgWith(1, null, TEST_ACCESS_TOKEN); + askProfileSetupHelper.setupVendorId.callsArgWith(1, null, TEST_VENDOR_ID); + awsProfileSetupHelper.setupAwsProfile.callsArgWith(1, TEST_ERROR_MESSAGE); - // call - helper.initiateAskProfileSetup(TEST_CONFIG, (error, askProfile) => { - // verify - expect(warnStub.args[0][0]).eq(messages.LWA_TOKEN_SHARE_WARN_MESSAGE); - expect(setVendorIdStub.args[0][0]).eq(TEST_PROFILE); - expect(setVendorIdStub.args[0][1]).to.deep.eq(TEST_VENDOR_ID); - expect(infoStub.args[0][0]).eq(`ASK Profile "${TEST_PROFILE}" was successfully created. The details are recorded in ask-cli config file (.ask/cli_config) located at your **HOME** folder.`); - expect(infoStub.args[1][0]).eq(`Vendor ID set as ${TEST_VENDOR_ID}.\n`); - expect(error).eq(TEST_ERROR_MESSAGE); - expect(askProfile).eq(undefined); - done(); - }); - }); + // call + helper.initiateAskProfileSetup(TEST_CONFIG, (error, askProfile) => { + // verify + expect(warnStub.args[0][0]).eq(messages.LWA_TOKEN_SHARE_WARN_MESSAGE); + expect(setVendorIdStub.args[0][0]).eq(TEST_PROFILE); + expect(setVendorIdStub.args[0][1]).to.deep.eq(TEST_VENDOR_ID); + expect(infoStub.args[0][0]).eq( + `ASK Profile "${TEST_PROFILE}" was successfully created. The details are recorded in ask-cli config file (.ask/cli_config) located at your **HOME** folder.`, + ); + expect(infoStub.args[1][0]).eq(`Vendor ID set as ${TEST_VENDOR_ID}.\n`); + expect(error).eq(TEST_ERROR_MESSAGE); + expect(askProfile).eq(undefined); + done(); + }); + }); - it('| successfully initiated askProfile but awsProfile is not set', (done) => { - // setup - askProfileSetupHelper.setupAskToken.callsArgWith(1, null, TEST_ACCESS_TOKEN); - askProfileSetupHelper.setupVendorId.callsArgWith(1, null, TEST_VENDOR_ID); - awsProfileSetupHelper.setupAwsProfile.callsArgWith(1, null); + it("| successfully initiated askProfile but awsProfile is not set", (done) => { + // setup + askProfileSetupHelper.setupAskToken.callsArgWith(1, null, TEST_ACCESS_TOKEN); + askProfileSetupHelper.setupVendorId.callsArgWith(1, null, TEST_VENDOR_ID); + awsProfileSetupHelper.setupAwsProfile.callsArgWith(1, null); - // call - helper.initiateAskProfileSetup(TEST_CONFIG, (error, askProfile) => { - // verify - expect(warnStub.args[0][0]).eq(messages.LWA_TOKEN_SHARE_WARN_MESSAGE); - expect(setVendorIdStub.args[0][0]).eq(TEST_PROFILE); - expect(setVendorIdStub.args[0][1]).to.deep.eq(TEST_VENDOR_ID); - expect(infoStub.args[0][0]).eq(`ASK Profile "${TEST_PROFILE}" was successfully created. The details are recorded in ask-cli config file (.ask/cli_config) located at your **HOME** folder.`); - expect(infoStub.args[1][0]).eq(`Vendor ID set as ${TEST_VENDOR_ID}.\n`); - expect(infoStub.args[2][0]).eq(messages.AWS_CONFIGURATION_MESSAGE); - expect(warnStub.args[1][0]).eq(messages.AWS_SECRET_ACCESS_KEY_AND_ID_SHARE_WARN_MESSAGE); - expect(setAwsProfileStub.args[0][0]).eq(TEST_PROFILE); - expect(setAwsProfileStub.args[0][1]).to.deep.eq(undefined); - expect(error).eq(null); - expect(askProfile).eq(TEST_PROFILE); - done(); - }); - }); + // call + helper.initiateAskProfileSetup(TEST_CONFIG, (error, askProfile) => { + // verify + expect(warnStub.args[0][0]).eq(messages.LWA_TOKEN_SHARE_WARN_MESSAGE); + expect(setVendorIdStub.args[0][0]).eq(TEST_PROFILE); + expect(setVendorIdStub.args[0][1]).to.deep.eq(TEST_VENDOR_ID); + expect(infoStub.args[0][0]).eq( + `ASK Profile "${TEST_PROFILE}" was successfully created. The details are recorded in ask-cli config file (.ask/cli_config) located at your **HOME** folder.`, + ); + expect(infoStub.args[1][0]).eq(`Vendor ID set as ${TEST_VENDOR_ID}.\n`); + expect(infoStub.args[2][0]).eq(messages.AWS_CONFIGURATION_MESSAGE); + expect(warnStub.args[1][0]).eq(messages.AWS_SECRET_ACCESS_KEY_AND_ID_SHARE_WARN_MESSAGE); + expect(setAwsProfileStub.args[0][0]).eq(TEST_PROFILE); + expect(setAwsProfileStub.args[0][1]).to.deep.eq(undefined); + expect(error).eq(null); + expect(askProfile).eq(TEST_PROFILE); + done(); + }); + }); - it('| successfully initiated askProfile and awsProfile', (done) => { - // setup - askProfileSetupHelper.setupAskToken.callsArgWith(1, null, TEST_ACCESS_TOKEN); - askProfileSetupHelper.setupVendorId.callsArgWith(1, null, TEST_VENDOR_ID); - awsProfileSetupHelper.setupAwsProfile.callsArgWith(1, null, TEST_AWS_PROFILE); + it("| successfully initiated askProfile and awsProfile", (done) => { + // setup + askProfileSetupHelper.setupAskToken.callsArgWith(1, null, TEST_ACCESS_TOKEN); + askProfileSetupHelper.setupVendorId.callsArgWith(1, null, TEST_VENDOR_ID); + awsProfileSetupHelper.setupAwsProfile.callsArgWith(1, null, TEST_AWS_PROFILE); - // call - helper.initiateAskProfileSetup(TEST_CONFIG, (error, askProfile) => { - // verify - expect(warnStub.args[0][0]).eq(messages.LWA_TOKEN_SHARE_WARN_MESSAGE); - expect(setVendorIdStub.args[0][0]).eq(TEST_PROFILE); - expect(setVendorIdStub.args[0][1]).to.deep.eq(TEST_VENDOR_ID); - expect(infoStub.args[0][0]).eq(`ASK Profile "${TEST_PROFILE}" was successfully created. The details are recorded in ask-cli config file (.ask/cli_config) located at your **HOME** folder.`); - expect(infoStub.args[1][0]).eq(`Vendor ID set as ${TEST_VENDOR_ID}.\n`); - expect(infoStub.args[2][0]).eq(messages.AWS_CONFIGURATION_MESSAGE); - expect(warnStub.args[1][0]).eq(messages.AWS_SECRET_ACCESS_KEY_AND_ID_SHARE_WARN_MESSAGE); - expect(infoStub.args[3][0]).eq(`AWS profile "${TEST_AWS_PROFILE}" was successfully associated with your ASK profile "${TEST_PROFILE}".\n`); - expect(setAwsProfileStub.args[0][0]).eq(TEST_PROFILE); - expect(setAwsProfileStub.args[0][1]).to.deep.eq(TEST_AWS_PROFILE); - expect(error).eq(null); - expect(askProfile).eq(TEST_PROFILE); - done(); - }); - }); + // call + helper.initiateAskProfileSetup(TEST_CONFIG, (error, askProfile) => { + // verify + expect(warnStub.args[0][0]).eq(messages.LWA_TOKEN_SHARE_WARN_MESSAGE); + expect(setVendorIdStub.args[0][0]).eq(TEST_PROFILE); + expect(setVendorIdStub.args[0][1]).to.deep.eq(TEST_VENDOR_ID); + expect(infoStub.args[0][0]).eq( + `ASK Profile "${TEST_PROFILE}" was successfully created. The details are recorded in ask-cli config file (.ask/cli_config) located at your **HOME** folder.`, + ); + expect(infoStub.args[1][0]).eq(`Vendor ID set as ${TEST_VENDOR_ID}.\n`); + expect(infoStub.args[2][0]).eq(messages.AWS_CONFIGURATION_MESSAGE); + expect(warnStub.args[1][0]).eq(messages.AWS_SECRET_ACCESS_KEY_AND_ID_SHARE_WARN_MESSAGE); + expect(infoStub.args[3][0]).eq( + `AWS profile "${TEST_AWS_PROFILE}" was successfully associated with your ASK profile "${TEST_PROFILE}".\n`, + ); + expect(setAwsProfileStub.args[0][0]).eq(TEST_PROFILE); + expect(setAwsProfileStub.args[0][1]).to.deep.eq(TEST_AWS_PROFILE); + expect(error).eq(null); + expect(askProfile).eq(TEST_PROFILE); + done(); + }); + }); - afterEach(() => { - sinon.restore(); - }); + afterEach(() => { + sinon.restore(); }); + }); }); diff --git a/test/unit/commands/configure/index-test.js b/test/unit/commands/configure/index-test.js deleted file mode 100644 index 0cf26e20..00000000 --- a/test/unit/commands/configure/index-test.js +++ /dev/null @@ -1,217 +0,0 @@ -const { expect } = require('chai'); -const sinon = require('sinon'); -const path = require('path'); -const fs = require('fs-extra'); -const jsonfile = require('jsonfile'); - -const ConfigureCommand = require('@src/commands/configure'); -const helper = require('@src/commands/configure/helper'); -const messages = require('@src/commands/configure/messages'); -const ui = require('@src/commands/configure/ui'); -const optionModel = require('@src/commands/option-model'); -const AppConfig = require('@src/model/app-config'); -const stringUtils = require('@src/utils/string-utils'); -const Messenger = require('@src/view/messenger'); - - -describe('Commands Configure test - command class test', () => { - const TEST_APP_CONFIG_FILE_PATH = path.join(process.cwd(), 'test', 'unit', 'fixture', 'model', 'cli_config'); - const TEST_PROFILE = 'default'; - const TEST_CMD = { - profile: TEST_PROFILE - }; - const TEST_INVALID_PROFILE = '&@%$&%@$^'; - const TEST_ERROR_MESSAGE = 'error'; - const TEST_AWS_PROFILE = 'awsProfile'; - const TEST_VENDOR_ID = 'vendorId'; - let infoStub; - let errorStub; - let warnStub; - - beforeEach(() => { - infoStub = sinon.stub(); - errorStub = sinon.stub(); - warnStub = sinon.stub(); - sinon.stub(Messenger, 'getInstance').returns({ - info: infoStub, - error: errorStub, - warn: warnStub - }); - }); - - afterEach(() => { - sinon.restore(); - }); - - it('| validate command information is set correctly', () => { - const instance = new ConfigureCommand(optionModel); - expect(instance.name()).eq('configure'); - expect(instance.description()).eq('helps to configure the credentials that ask-cli uses to authenticate the user to Amazon developer services'); - expect(instance.requiredOptions()).deep.eq([]); - expect(instance.optionalOptions()).deep.eq(['no-browser', 'profile', 'debug']); - }); - - describe('validate command handle - ensure AppConfig initiated', () => { - let instance; - const INVALID_FILE_PATH = '/invalid/path'; - - beforeEach(() => { - instance = new ConfigureCommand(optionModel); - }); - - afterEach(() => { - sinon.restore(); - AppConfig.dispose(); - }); - - it('| AppConfig creation, expect throw error', (done) => { - // setup - sinon.stub(path, 'join').returns(INVALID_FILE_PATH); - sinon.stub(fs, 'existsSync').returns(true); - - // call - instance.handle(TEST_CMD, (err, askProfile) => { - // verify - expect(infoStub.args[0][0]).eq(messages.ASK_CLI_CONFIGURATION_MESSAGE); - expect(err.message).eq(`No access to read/write file ${INVALID_FILE_PATH}.`); - expect(askProfile).eq(undefined); - done(); - }); - }); - - it('| returns error, invalid profile entered by user', (done) => { - // setup - sinon.stub(path, 'join').returns(TEST_APP_CONFIG_FILE_PATH); - const existsSyncStub = sinon.stub(fs, 'existsSync'); - existsSyncStub.onCall(0).returns(false); - existsSyncStub.onCall(1).returns(true); - sinon.stub(fs, 'ensureDirSync'); - sinon.stub(jsonfile, 'writeFileSync'); - sinon.stub(stringUtils, 'validateSyntax').returns(false); - getProfileListStub = sinon.stub().returns([]); - sinon.stub(AppConfig, 'getInstance').returns({ - getProfilesList: getProfileListStub, - }); - - // call - instance.handle({}, (err, askProfile) => { - // verify - expect(infoStub.args[0][0]).eq(messages.ASK_CLI_CONFIGURATION_MESSAGE); - expect(fs.ensureDirSync.callCount).eq(1); - expect(jsonfile.writeFileSync.callCount).eq(1); - expect(err).eq(messages.PROFILE_NAME_VALIDATION_ERROR); - expect(askProfile).eq(undefined); - done(); - }); - }); - - describe(('# existing profiles'), () => { - beforeEach(() => { - instance = new ConfigureCommand(optionModel); - sinon.stub(path, 'join').returns(TEST_APP_CONFIG_FILE_PATH); - const existsSyncStub = sinon.stub(fs, 'existsSync'); - existsSyncStub.onCall(0).returns(false); - existsSyncStub.onCall(1).returns(true); - sinon.stub(fs, 'ensureDirSync'); - sinon.stub(jsonfile, 'writeFileSync'); - getProfileListStub = sinon.stub().returns([TEST_INVALID_PROFILE]); - const getAwsProfileStub = sinon.stub().returns(TEST_AWS_PROFILE); - const getVendorIdStub = sinon.stub().returns(TEST_VENDOR_ID); - sinon.stub(AppConfig, 'getInstance').returns({ - getProfilesList: getProfileListStub, - getAwsProfile: getAwsProfileStub, - getVendorId: getVendorIdStub - }); - }); - - it('| returns error, existing profiles but user enters invalid profile name', (done) => { - // setup - sinon.stub(stringUtils, 'validateSyntax').returns(false); - - // call - instance.handle({ profile: TEST_INVALID_PROFILE }, (err, askProfile) => { - // verify - expect(infoStub.args[0][0]).eq(messages.ASK_CLI_CONFIGURATION_MESSAGE); - expect(fs.ensureDirSync.callCount).eq(1); - expect(jsonfile.writeFileSync.callCount).eq(1); - expect(err).eq(messages.PROFILE_NAME_VALIDATION_ERROR); - expect(askProfile).eq(undefined); - done(); - }); - }); - - it('| returns error, existing profiles and valid profile name, setup fails', (done) => { - // setup - sinon.stub(stringUtils, 'validateSyntax').returns(true); - sinon.stub(helper, 'initiateAskProfileSetup').callsArgWith(1, TEST_ERROR_MESSAGE); - - // call - instance.handle(TEST_CMD, (err, askProfile) => { - // verify - expect(infoStub.args[0][0]).eq(messages.ASK_CLI_CONFIGURATION_MESSAGE); - expect(fs.ensureDirSync.callCount).eq(1); - expect(jsonfile.writeFileSync.callCount).eq(1); - expect(err).eq(TEST_ERROR_MESSAGE); - expect(askProfile).eq(undefined); - done(); - }); - }); - - it('| returns error, existing profiles and invalid profile name, ask for creation of new profile fails', (done) => { - // setup - sinon.stub(stringUtils, 'validateSyntax').returns(true); - sinon.stub(ui, 'createOrUpdateProfile').callsArgWith(1, TEST_ERROR_MESSAGE); - - // call - instance.handle({}, (err, askProfile) => { - // verify - expect(infoStub.args[0][0]).eq(messages.ASK_CLI_CONFIGURATION_MESSAGE); - expect(fs.ensureDirSync.callCount).eq(1); - expect(jsonfile.writeFileSync.callCount).eq(1); - expect(err).eq(TEST_ERROR_MESSAGE); - expect(askProfile).eq(undefined); - done(); - }); - }); - - it('| returns error, existing profiles and invalid profile name, setup fails', (done) => { - // setup - sinon.stub(stringUtils, 'validateSyntax').returns(true); - sinon.stub(ui, 'createOrUpdateProfile').callsArgWith(1, null, TEST_PROFILE); - sinon.stub(helper, 'initiateAskProfileSetup').callsArgWith(1, TEST_ERROR_MESSAGE); - - // call - instance.handle({}, (err, askProfile) => { - // verify - expect(infoStub.args[0][0]).eq(messages.ASK_CLI_CONFIGURATION_MESSAGE); - expect(fs.ensureDirSync.callCount).eq(1); - expect(jsonfile.writeFileSync.callCount).eq(1); - expect(err).eq(TEST_ERROR_MESSAGE); - expect(askProfile).eq(undefined); - done(); - }); - }); - - it('| successfully configured profiles', (done) => { - // setup - sinon.stub(stringUtils, 'validateSyntax').returns(true); - sinon.stub(ui, 'createOrUpdateProfile').callsArgWith(1, null, TEST_PROFILE); - sinon.stub(helper, 'initiateAskProfileSetup').callsArgWith(1, null, TEST_PROFILE); - - // call - instance.handle(TEST_CMD, (err) => { - // verify - expect(infoStub.args[0][0]).eq(messages.ASK_CLI_CONFIGURATION_MESSAGE); - expect(infoStub.args[1][0]).eq(messages.CONFIGURE_SETUP_SUCCESS_MESSAGE); - expect(infoStub.args[2][0]).eq(`ASK Profile: ${TEST_PROFILE}`); - expect(infoStub.args[3][0]).eq(`AWS Profile: ${TEST_AWS_PROFILE}`); - expect(infoStub.args[4][0]).eq(`Vendor ID: ${TEST_VENDOR_ID}`); - expect(fs.ensureDirSync.callCount).eq(1); - expect(jsonfile.writeFileSync.callCount).eq(1); - expect(err).eq(undefined); - done(); - }); - }); - }); - }); -}); diff --git a/test/unit/commands/configure/index-test.ts b/test/unit/commands/configure/index-test.ts new file mode 100644 index 00000000..175ab4f3 --- /dev/null +++ b/test/unit/commands/configure/index-test.ts @@ -0,0 +1,198 @@ +import {expect} from "chai"; +import sinon from "sinon"; +import path from "path"; +import fs from "fs-extra"; +import jsonfile from "jsonfile"; +import ConfigureCommand from "../../../../lib/commands/configure"; +import helper from "../../../../lib/commands/configure/helper"; +import messages from "../../../../lib/commands/configure/messages"; +import ui from "../../../../lib/commands/configure/ui"; +import optionModel from "../../../../lib/commands/option-model.json"; +import AppConfig from "../../../../lib/model/app-config"; +import stringUtils from "../../../../lib/utils/string-utils"; +import Messenger from "../../../../lib/view/messenger"; +import {OptionModel} from "../../../../lib/commands/option-validator"; + +describe("Commands Configure test - command class test", () => { + const TEST_APP_CONFIG_FILE_PATH = path.join(process.cwd(), "test", "unit", "fixture", "model", "cli_config"); + const TEST_PROFILE = "default"; + const TEST_CMD = { + profile: TEST_PROFILE, + }; + const TEST_INVALID_PROFILE = "&@%$&%@$^"; + const TEST_ERROR_MESSAGE = "error"; + const TEST_AWS_PROFILE = "awsProfile"; + const TEST_VENDOR_ID = "vendorId"; + let infoStub: sinon.SinonStub; + let errorStub: sinon.SinonStub; + let warnStub: sinon.SinonStub; + + beforeEach(() => { + infoStub = sinon.stub(); + errorStub = sinon.stub(); + warnStub = sinon.stub(); + sinon.stub(Messenger, "getInstance").returns({ + info: infoStub, + error: errorStub, + warn: warnStub, + }); + }); + + afterEach(() => { + sinon.restore(); + }); + + it("| validate command information is set correctly", () => { + const instance = new ConfigureCommand(optionModel as OptionModel); + expect(instance.name()).eq("configure"); + expect(instance.description()).eq( + "helps to configure the credentials that ask-cli uses to authenticate the user to Amazon developer services", + ); + expect(instance.requiredOptions()).deep.eq([]); + expect(instance.optionalOptions()).deep.eq(["no-browser", "profile", "debug"]); + }); + + describe("validate command handle - ensure AppConfig initiated", () => { + let instance: ConfigureCommand; + const INVALID_FILE_PATH = "/invalid/path"; + + beforeEach(() => { + instance = new ConfigureCommand(optionModel as OptionModel); + }); + + afterEach(() => { + sinon.restore(); + AppConfig.dispose(); + }); + + it("| AppConfig creation, expect throw error", async () => { + // setup + sinon.stub(path, "join").returns(INVALID_FILE_PATH); + sinon.stub(fs, "existsSync").returns(true); + + // call + await expect(instance.handle(TEST_CMD)).rejectedWith(`No access to read/write file ${INVALID_FILE_PATH}.`); + + // verify + expect(infoStub).calledOnceWith(messages.ASK_CLI_CONFIGURATION_MESSAGE); + }); + + it("| returns error, invalid profile entered by user", async () => { + // setup + sinon.stub(path, "join").returns(TEST_APP_CONFIG_FILE_PATH); + const existsSyncStub = sinon.stub(fs, "existsSync"); + existsSyncStub.onCall(0).returns(false); + existsSyncStub.onCall(1).returns(true); + sinon.stub(fs, "ensureDirSync"); + sinon.stub(jsonfile, "writeFileSync"); + sinon.stub(stringUtils, "validateSyntax").returns(false); + const getProfileListStub = sinon.stub().returns([]); + sinon.stub(AppConfig, "getInstance").returns({ + getProfilesList: getProfileListStub, + }); + + // call + await expect(instance.handle(TEST_CMD)).rejectedWith(messages.PROFILE_NAME_VALIDATION_ERROR); + + // verify + expect(infoStub).calledOnceWith(messages.ASK_CLI_CONFIGURATION_MESSAGE); + expect(fs.ensureDirSync).calledOnce; + expect(jsonfile.writeFileSync).calledOnce; + }); + + describe("# existing profiles", () => { + beforeEach(() => { + instance = new ConfigureCommand(optionModel as OptionModel); + sinon.stub(path, "join").returns(TEST_APP_CONFIG_FILE_PATH); + const existsSyncStub = sinon.stub(fs, "existsSync"); + existsSyncStub.onCall(0).returns(false); + existsSyncStub.onCall(1).returns(true); + sinon.stub(fs, "ensureDirSync"); + sinon.stub(jsonfile, "writeFileSync"); + const getProfileListStub = sinon.stub().returns([TEST_INVALID_PROFILE]); + const getAwsProfileStub = sinon.stub().returns(TEST_AWS_PROFILE); + const getVendorIdStub = sinon.stub().returns(TEST_VENDOR_ID); + sinon.stub(AppConfig, "getInstance").returns({ + getProfilesList: getProfileListStub, + getAwsProfile: getAwsProfileStub, + getVendorId: getVendorIdStub, + }); + }); + + it("| returns error, existing profiles but user enters invalid profile name", async () => { + // setup + sinon.stub(stringUtils, "validateSyntax").returns(false); + + // call + await expect(instance.handle({profile: TEST_INVALID_PROFILE})).rejectedWith(messages.PROFILE_NAME_VALIDATION_ERROR); + + // verify + expect(infoStub).calledOnceWith(messages.ASK_CLI_CONFIGURATION_MESSAGE); + expect(fs.ensureDirSync).calledOnce; + expect(jsonfile.writeFileSync).calledOnce; + }); + + it("| returns error, existing profiles and valid profile name, setup fails", async () => { + // setup + sinon.stub(stringUtils, "validateSyntax").returns(true); + sinon.stub(helper, "initiateAskProfileSetup").callsArgWith(1, TEST_ERROR_MESSAGE); + + // call + await expect(instance.handle({profile: TEST_INVALID_PROFILE})).rejectedWith(TEST_ERROR_MESSAGE); + + // verify + expect(infoStub).calledOnceWith(messages.ASK_CLI_CONFIGURATION_MESSAGE); + expect(fs.ensureDirSync).calledOnce; + expect(jsonfile.writeFileSync).calledOnce; + }); + + it("| returns error, existing profiles and invalid profile name, ask for creation of new profile fails", async () => { + // setup + sinon.stub(stringUtils, "validateSyntax").returns(true); + sinon.stub(ui, "createOrUpdateProfile").callsArgWith(1, TEST_ERROR_MESSAGE); + + // call + await expect(instance.handle({})).rejectedWith(TEST_ERROR_MESSAGE); + + // verify + expect(infoStub).calledOnceWith(messages.ASK_CLI_CONFIGURATION_MESSAGE); + expect(fs.ensureDirSync).calledOnce; + expect(jsonfile.writeFileSync).calledOnce; + }); + + it("| returns error, existing profiles and invalid profile name, setup fails", async () => { + // setup + sinon.stub(stringUtils, "validateSyntax").returns(true); + sinon.stub(ui, "createOrUpdateProfile").callsArgWith(1, null, TEST_PROFILE); + sinon.stub(helper, "initiateAskProfileSetup").callsArgWith(1, TEST_ERROR_MESSAGE); + + // call + await expect(instance.handle({profile: TEST_INVALID_PROFILE})).rejectedWith(TEST_ERROR_MESSAGE); + + // verify + expect(infoStub).calledOnceWith(messages.ASK_CLI_CONFIGURATION_MESSAGE); + expect(fs.ensureDirSync).calledOnce; + expect(jsonfile.writeFileSync).calledOnce; + }); + + it("| successfully configured profiles", async () => { + // setup + sinon.stub(stringUtils, "validateSyntax").returns(true); + sinon.stub(ui, "createOrUpdateProfile").callsArgWith(1, null, TEST_PROFILE); + sinon.stub(helper, "initiateAskProfileSetup").callsArgWith(1, null, TEST_PROFILE); + + // call + await instance.handle({profile: TEST_INVALID_PROFILE}); + + // verify + expect(infoStub.getCall(0).args[0]).equal(messages.ASK_CLI_CONFIGURATION_MESSAGE); + expect(infoStub.getCall(1).args[0]).equal(messages.CONFIGURE_SETUP_SUCCESS_MESSAGE); + expect(infoStub.getCall(2).args[0]).equal(`ASK Profile: ${TEST_PROFILE}`); + expect(infoStub.getCall(3).args[0]).equal(`AWS Profile: ${TEST_AWS_PROFILE}`); + expect(infoStub.getCall(4).args[0]).equal(`Vendor ID: ${TEST_VENDOR_ID}`); + expect(fs.ensureDirSync).calledOnce; + expect(jsonfile.writeFileSync).calledOnce; + }); + }); + }); +}); diff --git a/test/unit/commands/configure/questions-test.js b/test/unit/commands/configure/questions-test.js index 5b28d6e9..faa1c979 100644 --- a/test/unit/commands/configure/questions-test.js +++ b/test/unit/commands/configure/questions-test.js @@ -1,59 +1,59 @@ -const { expect } = require('chai'); -const questions = require('@src/commands/configure/questions'); -const CONSTANTS = require('@src/utils/constants'); - -describe('Command: Configure - questions validate test', () => { - describe('# test request AWS profile name validators', () => { - const TEST_LIST = ['1', '2']; - - it('| input is blank string', () => { - expect(questions.REQUEST_AWS_PROFILE_NAME(TEST_LIST)[0].validate(' ')).equal('Profile name can not be blank string.'); - }); - - it('| input is not existed in profiles list', () => { - const result = questions.REQUEST_AWS_PROFILE_NAME(TEST_LIST); - expect(result[0].validate('1')).equal('[1] already exists in existing AWS profiles. Please try again with another name.'); - }); - - it('| input is valid based on profiles list', () => { - TEST_LIST.push(CONSTANTS.AWS_DEFAULT_PROFILE_NAME); - const result = questions.REQUEST_AWS_PROFILE_NAME(TEST_LIST); - expect(result[0].validate('3')).equal(true); - expect(result[0].default).equal(null); - }); - }); - - describe('# test accessKeyID and accessSecretKey validators', () => { - it('| invalid accessKeyID', () => { - // call and verify - expect(questions.REQUEST_ACCESS_SECRET_KEY_AND_ID[0].validate('')).equal('"AWS Access Key ID" cannot be empty.'); - }); - - it('| valid accessKeyID', () => { - // call and verify - expect(questions.REQUEST_ACCESS_SECRET_KEY_AND_ID[0].validate('accessKeyID')).equal(true); - }); - - it('| invalid secretAccessKey', () => { - // call and verify - expect(questions.REQUEST_ACCESS_SECRET_KEY_AND_ID[1].validate('')).equal('"AWS Secret Access Key" cannot be empty.'); - }); - - it('| valid secretAccessKey', () => { - // call and verify - expect(questions.REQUEST_ACCESS_SECRET_KEY_AND_ID[1].validate('secretAccessKey')).equal(true); - }); - }); - - describe('# test authCode validators', () => { - it('| invalid authCode', () => { - // call and verify - expect(questions.REQUEST_AUTH_CODE[0].validate('')).equal('Please enter a valid Authorization Code.'); - }); - - it('| valid authCode', () => { - // call and verify - expect(questions.REQUEST_AUTH_CODE[0].validate('authorizationCode')).equal(true); - }); +const {expect} = require("chai"); +const questions = require("../../../../lib/commands/configure/questions"); +const CONSTANTS = require("../../../../lib/utils/constants"); + +describe("Command: Configure - questions validate test", () => { + describe("# test request AWS profile name validators", () => { + const TEST_LIST = ["1", "2"]; + + it("| input is blank string", () => { + expect(questions.REQUEST_AWS_PROFILE_NAME(TEST_LIST)[0].validate(" ")).equal("Profile name can not be blank string."); + }); + + it("| input is not existed in profiles list", () => { + const result = questions.REQUEST_AWS_PROFILE_NAME(TEST_LIST); + expect(result[0].validate("1")).equal("[1] already exists in existing AWS profiles. Please try again with another name."); + }); + + it("| input is valid based on profiles list", () => { + TEST_LIST.push(CONSTANTS.AWS_DEFAULT_PROFILE_NAME); + const result = questions.REQUEST_AWS_PROFILE_NAME(TEST_LIST); + expect(result[0].validate("3")).equal(true); + expect(result[0].default).equal(null); + }); + }); + + describe("# test accessKeyID and accessSecretKey validators", () => { + it("| invalid accessKeyID", () => { + // call and verify + expect(questions.REQUEST_ACCESS_SECRET_KEY_AND_ID[0].validate("")).equal('"AWS Access Key ID" cannot be empty.'); + }); + + it("| valid accessKeyID", () => { + // call and verify + expect(questions.REQUEST_ACCESS_SECRET_KEY_AND_ID[0].validate("accessKeyID")).equal(true); + }); + + it("| invalid secretAccessKey", () => { + // call and verify + expect(questions.REQUEST_ACCESS_SECRET_KEY_AND_ID[1].validate("")).equal('"AWS Secret Access Key" cannot be empty.'); + }); + + it("| valid secretAccessKey", () => { + // call and verify + expect(questions.REQUEST_ACCESS_SECRET_KEY_AND_ID[1].validate("secretAccessKey")).equal(true); + }); + }); + + describe("# test authCode validators", () => { + it("| invalid authCode", () => { + // call and verify + expect(questions.REQUEST_AUTH_CODE[0].validate("")).equal("Please enter a valid Authorization Code."); + }); + + it("| valid authCode", () => { + // call and verify + expect(questions.REQUEST_AUTH_CODE[0].validate("authorizationCode")).equal(true); }); + }); }); diff --git a/test/unit/commands/configure/ui-test.js b/test/unit/commands/configure/ui-test.js index 97b4dc5f..5e27403d 100644 --- a/test/unit/commands/configure/ui-test.js +++ b/test/unit/commands/configure/ui-test.js @@ -1,522 +1,508 @@ -const { expect } = require('chai'); -const sinon = require('sinon'); -const inquirer = require('inquirer'); -const CONSTANTS = require('@src/utils/constants'); -const ui = require('@src/commands/configure/ui'); -const messages = require('@src/commands/configure/messages'); -const profileHelper = require('@src/utils/profile-helper'); -const stringUtils = require('@src/utils/string-utils'); +const {expect} = require("chai"); +const sinon = require("sinon"); +const inquirer = require("inquirer"); +const CONSTANTS = require("../../../../lib/utils/constants"); +const ui = require("../../../../lib/commands/configure/ui"); +const messages = require("../../../../lib/commands/configure/messages"); +const profileHelper = require("../../../../lib/utils/profile-helper"); +const stringUtils = require("../../../../lib/utils/string-utils"); function validateInquirerConfig(stub, expectedConfig) { - const { message, type, defaultValue, choices } = expectedConfig; - expect(stub.message).equal(message); - expect(stub.type).equal(type); - if (defaultValue) { - expect(stub.default).equal(defaultValue); - } - if (choices) { - expect(stub.choices).deep.equal(choices); - } + const {message, type, defaultValue, choices} = expectedConfig; + expect(stub.message).equal(message); + expect(stub.type).equal(type); + if (defaultValue) { + expect(stub.default).equal(defaultValue); + } + if (choices) { + expect(stub.choices).deep.equal(choices); + } } -describe('Command: Configure - UI test', () => { - const TEST_ERROR = 'error'; - describe('# confirmSettingAws check', () => { - beforeEach(() => { - sinon.stub(inquirer, 'prompt'); - }); +describe("Command: Configure - UI test", () => { + const TEST_ERROR = "error"; + describe("# confirmSettingAws check", () => { + beforeEach(() => { + sinon.stub(inquirer, "prompt"); + }); - it('| AWS setup confirmation by user', (done) => { - // setup - inquirer.prompt.resolves({ choice: 'true' }); - - // call - ui.confirmSettingAws((err, response) => { - // verify - validateInquirerConfig(inquirer.prompt.args[0][0][0], { - message: 'Do you want to link your AWS account in order to host your Alexa skills?', - type: 'confirm', - default: true - }); - - expect(err).equal(null); - expect(response).equal('true'); - done(); - }); - }); + it("| AWS setup confirmation by user", (done) => { + // setup + inquirer.prompt.resolves({choice: "true"}); - it('| AWS setup confirmation by user and inquirer throws exception', (done) => { - // setup - inquirer.prompt.rejects(new Error(TEST_ERROR)); - // call - ui.confirmSettingAws((err, response) => { - // verify - validateInquirerConfig(inquirer.prompt.args[0][0][0], { - message: 'Do you want to link your AWS account in order to host your Alexa skills?', - type: 'confirm', - default: true - }); - expect(err.message).equal(TEST_ERROR); - expect(response).equal(undefined); - done(); - }); + // call + ui.confirmSettingAws((err, response) => { + // verify + validateInquirerConfig(inquirer.prompt.args[0][0][0], { + message: "Do you want to link your AWS account in order to host your Alexa skills?", + type: "confirm", + default: true, }); - afterEach(() => { - sinon.restore(); - }); + expect(err).equal(null); + expect(response).equal("true"); + done(); + }); }); - describe('# selectEnvironmentVariables check', () => { - beforeEach(() => { - sinon.stub(inquirer, 'prompt'); - }); + it("| AWS setup confirmation by user and inquirer throws exception", (done) => { + // setup + inquirer.prompt.rejects(new Error(TEST_ERROR)); + // call + ui.confirmSettingAws((err, response) => { + // verify + validateInquirerConfig(inquirer.prompt.args[0][0][0], { + message: "Do you want to link your AWS account in order to host your Alexa skills?", + type: "confirm", + default: true, + }); + expect(err.message).equal(TEST_ERROR); + expect(response).equal(undefined); + done(); + }); + }); - it('| Use environment variables confirmation by user', (done) => { - // setup - inquirer.prompt.resolves({ choice: 'yes' }); - - // call - ui.selectEnvironmentVariables((err, response) => { - // verify - validateInquirerConfig(inquirer.prompt.args[0][0][0], { - message: 'We have detected you have AWS environment variables. Would you like to setup your profile using those?', - type: 'list', - choices: ['Yes', 'No'] - }); - expect(err).equal(null); - expect(response).equal('yes'); - done(); - }); - }); + afterEach(() => { + sinon.restore(); + }); + }); - it('| Use environment variables confirmation by user and inquirer throws exception', (done) => { - // setup - inquirer.prompt.rejects(new Error(TEST_ERROR)); - // call - ui.selectEnvironmentVariables((err, response) => { - // verify - validateInquirerConfig(inquirer.prompt.args[0][0][0], { - message: 'We have detected you have AWS environment variables. Would you like to setup your profile using those?', - type: 'list', - choices: ['Yes', 'No'] - }); - expect(err.message).equal(TEST_ERROR); - expect(response).equal(undefined); - done(); - }); - }); + describe("# selectEnvironmentVariables check", () => { + beforeEach(() => { + sinon.stub(inquirer, "prompt"); + }); - afterEach(() => { - sinon.restore(); - }); + it("| Use environment variables confirmation by user", (done) => { + // setup + inquirer.prompt.resolves({choice: "yes"}); + + // call + ui.selectEnvironmentVariables((err, response) => { + // verify + validateInquirerConfig(inquirer.prompt.args[0][0][0], { + message: "We have detected you have AWS environment variables. Would you like to setup your profile using those?", + type: "list", + choices: ["Yes", "No"], + }); + expect(err).equal(null); + expect(response).equal("yes"); + done(); + }); }); - describe('# addNewCredentials check', () => { - beforeEach(() => { - sinon.stub(inquirer, 'prompt'); - }); + it("| Use environment variables confirmation by user and inquirer throws exception", (done) => { + // setup + inquirer.prompt.rejects(new Error(TEST_ERROR)); + // call + ui.selectEnvironmentVariables((err, response) => { + // verify + validateInquirerConfig(inquirer.prompt.args[0][0][0], { + message: "We have detected you have AWS environment variables. Would you like to setup your profile using those?", + type: "list", + choices: ["Yes", "No"], + }); + expect(err.message).equal(TEST_ERROR); + expect(response).equal(undefined); + done(); + }); + }); - it('| Aws access_key_id and secret_access_key entered by user', (done) => { - // setup - const accessKeyId = 'accessKeyId'; - const secretAccessKey = 'secretAccessKey'; - inquirer.prompt.resolves({ - accessKeyId, - secretAccessKey - }); - - // call - ui.addNewCredentials((err, response) => { - // verify - expect(err).equal(null); - expect(response.aws_access_key_id).equal(accessKeyId); - expect(response.aws_secret_access_key).equal(secretAccessKey); - done(); - }); - }); + afterEach(() => { + sinon.restore(); + }); + }); - it('| Aws access_key_id and secret_access_key entered by user and inquirer throws exception', (done) => { - // setup - inquirer.prompt.rejects(new Error(TEST_ERROR)); - // call - ui.addNewCredentials((err, response) => { - // verify - expect(err.message).equal(TEST_ERROR); - expect(response).equal(undefined); - done(); - }); - }); + describe("# addNewCredentials check", () => { + beforeEach(() => { + sinon.stub(inquirer, "prompt"); + }); - afterEach(() => { - sinon.restore(); - }); + it("| Aws access_key_id and secret_access_key entered by user", (done) => { + // setup + const accessKeyId = "accessKeyId"; + const secretAccessKey = "secretAccessKey"; + inquirer.prompt.resolves({ + accessKeyId, + secretAccessKey, + }); + + // call + ui.addNewCredentials((err, response) => { + // verify + expect(err).equal(null); + expect(response.aws_access_key_id).equal(accessKeyId); + expect(response.aws_secret_access_key).equal(secretAccessKey); + done(); + }); }); - describe('# createNewOrSelectAWSProfile check', () => { - const listOfProfiles = ['ask', 'aws', 'lambda']; + it("| Aws access_key_id and secret_access_key entered by user and inquirer throws exception", (done) => { + // setup + inquirer.prompt.rejects(new Error(TEST_ERROR)); + // call + ui.addNewCredentials((err, response) => { + // verify + expect(err.message).equal(TEST_ERROR); + expect(response).equal(undefined); + done(); + }); + }); - beforeEach(() => { - sinon.stub(inquirer, 'prompt'); - }); + afterEach(() => { + sinon.restore(); + }); + }); - it('| create profile or use existing profile decision by user', (done) => { - // setup - inquirer.prompt.resolves({ chosenProfile: 'lambda' }); - - // call - ui.createNewOrSelectAWSProfile(listOfProfiles, (err, response) => { - // verify - validateInquirerConfig(inquirer.prompt.args[0][0][0], { - type: 'list', - message: 'Please choose from the following existing AWS profiles or create a new one.' - }); - expect(err).equal(null); - expect(response).equal('lambda'); - done(); - }); - }); + describe("# createNewOrSelectAWSProfile check", () => { + const listOfProfiles = ["ask", "aws", "lambda"]; - it('| create profile or use existing profile decision by user and inquirer throws exception', (done) => { - // setup - inquirer.prompt.rejects(new Error(TEST_ERROR)); - // call - ui.createNewOrSelectAWSProfile(listOfProfiles, (err, response) => { - // verify - validateInquirerConfig(inquirer.prompt.args[0][0][0], { - type: 'list', - message: 'Please choose from the following existing AWS profiles or create a new one.' - }); - expect(err.message).equal(TEST_ERROR); - expect(response).equal(undefined); - done(); - }); - }); + beforeEach(() => { + sinon.stub(inquirer, "prompt"); + }); - afterEach(() => { - sinon.restore(); - }); + it("| create profile or use existing profile decision by user", (done) => { + // setup + inquirer.prompt.resolves({chosenProfile: "lambda"}); + + // call + ui.createNewOrSelectAWSProfile(listOfProfiles, (err, response) => { + // verify + validateInquirerConfig(inquirer.prompt.args[0][0][0], { + type: "list", + message: "Please choose from the following existing AWS profiles or create a new one.", + }); + expect(err).equal(null); + expect(response).equal("lambda"); + done(); + }); }); - describe('# createNewProfile check', () => { - beforeEach(() => { - sinon.stub(inquirer, 'prompt'); - }); + it("| create profile or use existing profile decision by user and inquirer throws exception", (done) => { + // setup + inquirer.prompt.rejects(new Error(TEST_ERROR)); + // call + ui.createNewOrSelectAWSProfile(listOfProfiles, (err, response) => { + // verify + validateInquirerConfig(inquirer.prompt.args[0][0][0], { + type: "list", + message: "Please choose from the following existing AWS profiles or create a new one.", + }); + expect(err.message).equal(TEST_ERROR); + expect(response).equal(undefined); + done(); + }); + }); - it('| valid profile name entered by user', (done) => { - // setup - inquirer.prompt.resolves({ profile: 'lambda' }); - - // call - ui.createNewProfile((error, response) => { - // verify - validateInquirerConfig(inquirer.prompt.args[0][0][0], { - message: `Please provide a profile name or press enter to use ${CONSTANTS.ASK_DEFAULT_PROFILE_NAME} as the profile name: `, - type: 'input', - default: CONSTANTS.ASK_DEFAULT_PROFILE_NAME - }); - expect(error).equal(null); - expect(response).equal('lambda'); - done(); - }); - }); + afterEach(() => { + sinon.restore(); + }); + }); - it('| invalid profile name entered by user', (done) => { - // setup - inquirer.prompt.resolves({ profile: ' %*^@&!' }); - - // call - ui.createNewProfile((error, response) => { - // verify - expect(error).equal(messages.PROFILE_NAME_VALIDATION_ERROR); - expect(response).equal(undefined); - done(); - }); - }); + describe("# createNewProfile check", () => { + beforeEach(() => { + sinon.stub(inquirer, "prompt"); + }); - it('| profile name entered by user and inquirer throws exception', (done) => { - // setup - inquirer.prompt.rejects(new Error(TEST_ERROR)); - // call - ui.createNewProfile((err, response) => { - // verify - validateInquirerConfig(inquirer.prompt.args[0][0][0], { - message: `Please provide a profile name or press enter to use ${CONSTANTS.ASK_DEFAULT_PROFILE_NAME} as the profile name: `, - type: 'input', - default: CONSTANTS.ASK_DEFAULT_PROFILE_NAME - }); - expect(err.message).equal(TEST_ERROR); - expect(response).equal(undefined); - done(); - }); - }); + it("| valid profile name entered by user", (done) => { + // setup + inquirer.prompt.resolves({profile: "lambda"}); + + // call + ui.createNewProfile((error, response) => { + // verify + validateInquirerConfig(inquirer.prompt.args[0][0][0], { + message: `Please provide a profile name or press enter to use ${CONSTANTS.ASK_DEFAULT_PROFILE_NAME} as the profile name: `, + type: "input", + default: CONSTANTS.ASK_DEFAULT_PROFILE_NAME, + }); + expect(error).equal(null); + expect(response).equal("lambda"); + done(); + }); + }); + it("| invalid profile name entered by user", (done) => { + // setup + inquirer.prompt.resolves({profile: " %*^@&!"}); + + // call + ui.createNewProfile((error, response) => { + // verify + expect(error).equal(messages.PROFILE_NAME_VALIDATION_ERROR); + expect(response).equal(undefined); + done(); + }); + }); - afterEach(() => { - sinon.restore(); - }); + it("| profile name entered by user and inquirer throws exception", (done) => { + // setup + inquirer.prompt.rejects(new Error(TEST_ERROR)); + // call + ui.createNewProfile((err, response) => { + // verify + validateInquirerConfig(inquirer.prompt.args[0][0][0], { + message: `Please provide a profile name or press enter to use ${CONSTANTS.ASK_DEFAULT_PROFILE_NAME} as the profile name: `, + type: "input", + default: CONSTANTS.ASK_DEFAULT_PROFILE_NAME, + }); + expect(err.message).equal(TEST_ERROR); + expect(response).equal(undefined); + done(); + }); }); - describe('# chooseVendorId check', () => { - const VENDOR_PAGE_SIZE = 50; - const vendorInfo = [ - { - vendorName: 'vendor_name1', - vendorId: ' vendor_id1' - }, - { - vendorName: 'vendor_name2', - vendorId: ' vendor_id2' - } - ]; - - beforeEach(() => { - sinon.stub(inquirer, 'prompt'); - }); + afterEach(() => { + sinon.restore(); + }); + }); + + describe("# chooseVendorId check", () => { + const VENDOR_PAGE_SIZE = 50; + const vendorInfo = [ + { + vendorName: "vendor_name1", + vendorId: " vendor_id1", + }, + { + vendorName: "vendor_name2", + vendorId: " vendor_id2", + }, + ]; + + beforeEach(() => { + sinon.stub(inquirer, "prompt"); + }); - it('| vendor selection by user', (done) => { - // setup - inquirer.prompt.resolves({ selectedVendor: vendorInfo[0].vendorId }); - - // call - ui.chooseVendorId(VENDOR_PAGE_SIZE, vendorInfo, (error, response) => { - // verify - validateInquirerConfig(inquirer.prompt.args[0][0][0], { - type: 'rawlist', - message: 'Your Amazon developer account has multiple Vendor IDs. Please choose the Vendor ID for the skills you want to manage.', - }); - expect(error).equal(null); - expect(response).equal('vendor_id1'); - done(); - }); - }); + it("| vendor selection by user", (done) => { + // setup + inquirer.prompt.resolves({selectedVendor: vendorInfo[0].vendorId}); + + // call + ui.chooseVendorId(VENDOR_PAGE_SIZE, vendorInfo, (error, response) => { + // verify + validateInquirerConfig(inquirer.prompt.args[0][0][0], { + type: "rawlist", + message: "Your Amazon developer account has multiple Vendor IDs. Please choose the Vendor ID for the skills you want to manage.", + }); + expect(error).equal(null); + expect(response).equal("vendor_id1"); + done(); + }); + }); - it('| vendor selection by user and inquirer throws exception', (done) => { - // setup - inquirer.prompt.rejects(new Error(TEST_ERROR)); - // call - ui.chooseVendorId(VENDOR_PAGE_SIZE, vendorInfo, (err, response) => { - // verify - validateInquirerConfig(inquirer.prompt.args[0][0][0], { - type: 'rawlist', - message: 'Your Amazon developer account has multiple Vendor IDs. Please choose the Vendor ID for the skills you want to manage.', - }); - expect(err.message).equal(TEST_ERROR); - expect(response).equal(undefined); - done(); - }); - }); + it("| vendor selection by user and inquirer throws exception", (done) => { + // setup + inquirer.prompt.rejects(new Error(TEST_ERROR)); + // call + ui.chooseVendorId(VENDOR_PAGE_SIZE, vendorInfo, (err, response) => { + // verify + validateInquirerConfig(inquirer.prompt.args[0][0][0], { + type: "rawlist", + message: "Your Amazon developer account has multiple Vendor IDs. Please choose the Vendor ID for the skills you want to manage.", + }); + expect(err.message).equal(TEST_ERROR); + expect(response).equal(undefined); + done(); + }); + }); - afterEach(() => { - sinon.restore(); - }); + afterEach(() => { + sinon.restore(); }); + }); - describe('# createOrUpdateProfile check', () => { - beforeEach(() => { - sinon.stub(inquirer, 'prompt'); - }); + describe("# createOrUpdateProfile check", () => { + beforeEach(() => { + sinon.stub(inquirer, "prompt"); + }); - it('| returns error | invalid profile name entered', (done) => { - // setup - const listOfProfiles = [ - 'askProfile1', - 'askProfile2' - ]; - const createNewProfile = 'Create new profile'; - inquirer.prompt.resolves({ profile: createNewProfile }); - sinon.stub(ui, 'createNewProfile').callsArgWith(0, null, 'askProfile2'); - - - // call - ui.createOrUpdateProfile(listOfProfiles, (error, askProfile) => { - // verify - expect(error).to.equal(messages.PROFILE_NAME_VALIDATION_ERROR); - expect(askProfile).equals(undefined); - done(); - }); - }); + it("| returns error | invalid profile name entered", (done) => { + // setup + const listOfProfiles = ["askProfile1", "askProfile2"]; + const createNewProfile = "Create new profile"; + inquirer.prompt.resolves({profile: createNewProfile}); + sinon.stub(ui, "createNewProfile").callsArgWith(0, null, "askProfile2"); + + // call + ui.createOrUpdateProfile(listOfProfiles, (error, askProfile) => { + // verify + expect(error).to.equal(messages.PROFILE_NAME_VALIDATION_ERROR); + expect(askProfile).equals(undefined); + done(); + }); + }); - it('| returns valid profile | createNewProfile returns valid profile', (done) => { - // setup - const listOfProfiles = [ - 'askProfile1', - 'askProfile2' - ]; - const createNewProfile = 'Create new profile'; - inquirer.prompt.resolves({ profile: createNewProfile }); - sinon.stub(stringUtils, 'validateSyntax').returns(true); - sinon.stub(ui, 'createNewProfile').callsArgWith(0, null, 'askProfile2'); - - // call - ui.createOrUpdateProfile(listOfProfiles, (error, askProfile) => { - // verify - expect(error).to.equal(null); - expect(askProfile).equals(createNewProfile); - done(); - }); - }); + it("| returns valid profile | createNewProfile returns valid profile", (done) => { + // setup + const listOfProfiles = ["askProfile1", "askProfile2"]; + const createNewProfile = "Create new profile"; + inquirer.prompt.resolves({profile: createNewProfile}); + sinon.stub(stringUtils, "validateSyntax").returns(true); + sinon.stub(ui, "createNewProfile").callsArgWith(0, null, "askProfile2"); + + // call + ui.createOrUpdateProfile(listOfProfiles, (error, askProfile) => { + // verify + expect(error).to.equal(null); + expect(askProfile).equals(createNewProfile); + done(); + }); + }); - it('| update an existing ASK profile by user', (done) => { - // setup - const listOfProfiles = [ - 'askProfile1', - 'askProfile2', - '#$*%#$(%$43' - ]; - inquirer.prompt.resolves({ profile: listOfProfiles[1] }); - - // call - ui.createOrUpdateProfile(listOfProfiles, (error, response) => { - // verify - expect(error).to.equal(null); - expect(response).equal('askProfile2'); - done(); - }); - }); + it("| update an existing ASK profile by user", (done) => { + // setup + const listOfProfiles = ["askProfile1", "askProfile2", "#$*%#$(%$43"]; + inquirer.prompt.resolves({profile: listOfProfiles[1]}); + + // call + ui.createOrUpdateProfile(listOfProfiles, (error, response) => { + // verify + expect(error).to.equal(null); + expect(response).equal("askProfile2"); + done(); + }); + }); - it('| invalid profile name read from config file', (done) => { - // setup - const listOfProfiles = [ - 'askProfile1', - '#$*%#$(%$43' - ]; - inquirer.prompt.resolves({ profile: listOfProfiles[1] }); - - // call - ui.createOrUpdateProfile(listOfProfiles, (error, response) => { - // verify - expect(error).equal(messages.PROFILE_NAME_VALIDATION_ERROR); - expect(response).to.equal(undefined); - done(); - }); - }); + it("| invalid profile name read from config file", (done) => { + // setup + const listOfProfiles = ["askProfile1", "#$*%#$(%$43"]; + inquirer.prompt.resolves({profile: listOfProfiles[1]}); + + // call + ui.createOrUpdateProfile(listOfProfiles, (error, response) => { + // verify + expect(error).equal(messages.PROFILE_NAME_VALIDATION_ERROR); + expect(response).to.equal(undefined); + done(); + }); + }); - it('| createOrUpdateProfile and inquirer throws exception', (done) => { - // setup - const listOfProfiles = [ - 'askProfile1', - '#$*%#$(%$43' - ]; - inquirer.prompt.rejects(new Error(TEST_ERROR)); - // call - ui.createOrUpdateProfile(listOfProfiles, (err, response) => { - // verify - expect(err.message).equal(TEST_ERROR); - expect(response).equal(undefined); - done(); - }); - }); + it("| createOrUpdateProfile and inquirer throws exception", (done) => { + // setup + const listOfProfiles = ["askProfile1", "#$*%#$(%$43"]; + inquirer.prompt.rejects(new Error(TEST_ERROR)); + // call + ui.createOrUpdateProfile(listOfProfiles, (err, response) => { + // verify + expect(err.message).equal(TEST_ERROR); + expect(response).equal(undefined); + done(); + }); + }); - afterEach(() => { - sinon.restore(); - }); + afterEach(() => { + sinon.restore(); }); + }); - describe('# requestAwsProfileName check', () => { - beforeEach(() => { - sinon.stub(inquirer, 'prompt'); - }); + describe("# requestAwsProfileName check", () => { + beforeEach(() => { + sinon.stub(inquirer, "prompt"); + }); - it('| Aws profile name entered by user', (done) => { - // setup - inquirer.prompt.resolves({ awsProfileName: 'awsProfile' }); - - // call - ui.requestAwsProfileName([], (error, response) => { - // verify - expect(error).to.equal(null); - expect(response).equal('awsProfile'); - done(); - }); - }); + it("| Aws profile name entered by user", (done) => { + // setup + inquirer.prompt.resolves({awsProfileName: "awsProfile"}); + + // call + ui.requestAwsProfileName([], (error, response) => { + // verify + expect(error).to.equal(null); + expect(response).equal("awsProfile"); + done(); + }); + }); - it('| Aws profile name entered by user and inquirer throws exception', (done) => { - // setup - inquirer.prompt.rejects(new Error(TEST_ERROR)); - // call - ui.requestAwsProfileName([], (err, response) => { - // verify - expect(err.message).equal(TEST_ERROR); - expect(response).equal(undefined); - done(); - }); - }); + it("| Aws profile name entered by user and inquirer throws exception", (done) => { + // setup + inquirer.prompt.rejects(new Error(TEST_ERROR)); + // call + ui.requestAwsProfileName([], (err, response) => { + // verify + expect(err.message).equal(TEST_ERROR); + expect(response).equal(undefined); + done(); + }); + }); - afterEach(() => { - sinon.restore(); - }); + afterEach(() => { + sinon.restore(); }); + }); - describe('# stringFormatter', () => { - it('| return null if not profile list', () => { - expect(ui.profileFormatter()).to.be.a('null'); - }); + describe("# stringFormatter", () => { + it("| return null if not profile list", () => { + expect(ui.profileFormatter()).to.be.a("null"); + }); - it('| return null if profile list is empty', () => { - expect(ui.profileFormatter([])).to.be.a('null'); - }); + it("| return null if profile list is empty", () => { + expect(ui.profileFormatter([])).to.be.a("null"); + }); - it('| return formatted profile list with no aws profile', () => { - const input = [{ - askProfile: 'ask_test', - awsProfile: null - }]; - const expectResult = ['[ask_test] ** NULL **']; - expect(ui.profileFormatter(input)).to.eql(expectResult); - }); + it("| return formatted profile list with no aws profile", () => { + const input = [ + { + askProfile: "ask_test", + awsProfile: null, + }, + ]; + const expectResult = ["[ask_test] ** NULL **"]; + expect(ui.profileFormatter(input)).to.eql(expectResult); + }); - it('| return formatted profile list with aws profile', () => { - const input = [{ - askProfile: 'ask_test', - awsProfile: 'aws_test' - }]; - const expectResult = ['[ask_test] "aws_test"']; - expect(ui.profileFormatter(input)).to.eql(expectResult); - }); + it("| return formatted profile list with aws profile", () => { + const input = [ + { + askProfile: "ask_test", + awsProfile: "aws_test", + }, + ]; + const expectResult = ['[ask_test] "aws_test"']; + expect(ui.profileFormatter(input)).to.eql(expectResult); }); + }); - describe('# getAuthCode check', () => { - beforeEach(() => { - sinon.stub(inquirer, 'prompt'); - }); + describe("# getAuthCode check", () => { + beforeEach(() => { + sinon.stub(inquirer, "prompt"); + }); - it('| Authorization code entered by user', (done) => { - // setup - inquirer.prompt.resolves({ authCode: 'authorizationCode' }); - - // call - ui.getAuthCode((err, response) => { - // verify - validateInquirerConfig(inquirer.prompt.args[0][0][0], { - type: 'input', - message: 'Please enter the Authorization Code: ' - }); - - expect(err).equal(null); - expect(response).equal('authorizationCode'); - done(); - }); - }); + it("| Authorization code entered by user", (done) => { + // setup + inquirer.prompt.resolves({authCode: "authorizationCode"}); - it('| Authorization code entered by user and inquirer throws exception', (done) => { - // setup - inquirer.prompt.rejects(new Error(TEST_ERROR)); - // call - ui.getAuthCode((err, response) => { - // verify - validateInquirerConfig(inquirer.prompt.args[0][0][0], { - type: 'input', - message: 'Please enter the Authorization Code: ' - }); - expect(err.message).equal(TEST_ERROR); - expect(response).equal(undefined); - done(); - }); + // call + ui.getAuthCode((err, response) => { + // verify + validateInquirerConfig(inquirer.prompt.args[0][0][0], { + type: "input", + message: "Please enter the Authorization Code: ", }); - afterEach(() => { - sinon.restore(); - }); + expect(err).equal(null); + expect(response).equal("authorizationCode"); + done(); + }); + }); + + it("| Authorization code entered by user and inquirer throws exception", (done) => { + // setup + inquirer.prompt.rejects(new Error(TEST_ERROR)); + // call + ui.getAuthCode((err, response) => { + // verify + validateInquirerConfig(inquirer.prompt.args[0][0][0], { + type: "input", + message: "Please enter the Authorization Code: ", + }); + expect(err.message).equal(TEST_ERROR); + expect(response).equal(undefined); + done(); + }); + }); + + afterEach(() => { + sinon.restore(); }); + }); }); diff --git a/test/unit/commands/deploy/helper-test.js b/test/unit/commands/deploy/helper-test.js index 562241ea..25b3f0fb 100644 --- a/test/unit/commands/deploy/helper-test.js +++ b/test/unit/commands/deploy/helper-test.js @@ -1,199 +1,204 @@ -const { expect } = require('chai'); -const sinon = require('sinon'); - -const helper = require('@src/commands/deploy/helper'); -const SkillMetadataController = require('@src/controllers/skill-metadata-controller'); -const SkillCodeController = require('@src/controllers/skill-code-controller'); -const SkillInfrastructureController = require('@src/controllers/skill-infrastructure-controller'); -const CliError = require('@src/exceptions/cli-error'); -const ResourcesConfig = require('@src/model/resources-config'); -const CONSTANTS = require('@src/utils/constants'); -const profileHelper = require('@src/utils/profile-helper'); -const Messenger = require('@src/view/messenger'); - -describe('Commands deploy test - helper test', () => { - const TEST_PROFILE = 'default'; - const TEST_IGNORE_HASH = false; - const TEST_VENDOR_ID = 'vendor'; - const TEST_DO_DEBUG = false; - const TEST_OPTIONS = { profile: TEST_PROFILE, doDebug: TEST_DO_DEBUG, ignoreHash: TEST_IGNORE_HASH }; - - describe('# test helper method - confirmProfile', () => { - afterEach(() => { - sinon.restore(); - }); - - it('| profile does not exist, expect throw error', () => { - // setup - sinon.stub(ResourcesConfig.prototype, 'getProfile').returns(undefined); - // call & verify - expect(() => helper.confirmProfile(TEST_PROFILE)).throw(CliError, - `Profile [${TEST_PROFILE}] does not exist. Please configure it in your ${CONSTANTS.FILE_PATH.ASK_RESOURCES_JSON_CONFIG} file.`); - }); - - it('| profile does exist, expect messenger info', () => { - // setup - const infoStub = sinon.stub(); - sinon.stub(Messenger, 'getInstance').returns({ - info: infoStub - }); - sinon.stub(ResourcesConfig.prototype, 'getProfile').returns({ test: 'result' }); - // call & verify - expect(() => helper.confirmProfile(TEST_PROFILE)).to.not.throw(); - expect(infoStub.args[0][0]).equal(`Deploy project for profile [${TEST_PROFILE}]\n`); - }); - }); - - describe('# test helper method - deploySkillMetadata', () => { - afterEach(() => { - sinon.restore(); - }); - - it('| profile resolve vendorId fails, expect callback error', (done) => { - // setup - sinon.stub(profileHelper, 'resolveVendorId').throws(new Error('error')); - // call - helper.deploySkillMetadata(TEST_OPTIONS, (err, res) => { - // verify - expect(err.message).equal('error'); - expect(res).equal(undefined); - done(); - }); - }); - - it('| skillMetaController deploySkillPackage fails, expect callback error', (done) => { - // setup - sinon.stub(profileHelper, 'resolveVendorId').returns(TEST_VENDOR_ID); - sinon.stub(SkillMetadataController.prototype, 'deploySkillPackage').callsArgWith(2, 'error'); - // call - helper.deploySkillMetadata(TEST_OPTIONS, (err, res) => { - // verify - expect(err).equal('error'); - expect(res).equal(undefined); - done(); - }); - }); - - it('| skillMetaController deploySkillPackage passes, expect no error callback', (done) => { - // setup - sinon.stub(profileHelper, 'resolveVendorId').returns(TEST_VENDOR_ID); - sinon.stub(SkillMetadataController.prototype, 'deploySkillPackage').callsArgWith(2); - // call - helper.deploySkillMetadata(TEST_OPTIONS, (err, res) => { - // verify - expect(err).equal(undefined); - expect(res).equal(undefined); - done(); - }); - }); - }); - - describe('# test helper method - buildSkillCode', () => { - afterEach(() => { - sinon.restore(); - }); - - it('| skillCodeController buildSkillCode fails, expect callback error', (done) => { - // setup - sinon.stub(SkillCodeController.prototype, 'buildCode').callsArgWith(0, 'error'); - // call - helper.buildSkillCode(TEST_PROFILE, TEST_DO_DEBUG, (err, res) => { - // verify - expect(err).equal('error'); - expect(res).equal(undefined); - done(); - }); - }); - - it('| skillCodeController buildSkillCode passes, expect no error callback', (done) => { - // setup - sinon.stub(SkillCodeController.prototype, 'buildCode').callsArgWith(0); - // call - helper.buildSkillCode(TEST_PROFILE, TEST_DO_DEBUG, (err, res) => { - // verify - expect(err).equal(null); - expect(res).equal(undefined); - done(); - }); - }); - }); - - describe('# test helper method - deploySkillInfrastructure', () => { - afterEach(() => { - sinon.restore(); - }); - - it('| skillInfraController deploySkillInfrastructure fails, expect callback error', (done) => { - // setup - sinon.stub(SkillInfrastructureController.prototype, 'deployInfrastructure').callsArgWith(0, 'error'); - // call - helper.deploySkillInfrastructure(TEST_PROFILE, TEST_DO_DEBUG, TEST_IGNORE_HASH, (err, res) => { - // verify - expect(err).equal('error'); - expect(res).equal(undefined); - done(); - }); - }); - - it('| skillInfraController deploySkillInfrastructure passes, expect no error callback', (done) => { - // setup - sinon.stub(SkillInfrastructureController.prototype, 'deployInfrastructure').callsArgWith(0); - // call - helper.deploySkillInfrastructure(TEST_PROFILE, TEST_DO_DEBUG, TEST_IGNORE_HASH, (err, res) => { - // verify - expect(err).equal(undefined); - expect(res).equal(undefined); - done(); - }); - }); - }); - - describe('# test helper method - enableSkill', () => { - let infoStub; - beforeEach(() => { - infoStub = sinon.stub(); - sinon.stub(Messenger, 'getInstance').returns({ - info: infoStub, - }); - }); - - afterEach(() => { - sinon.restore(); - }); - - it('| skillMetaController enableSkill fails, expect callback error', (done) => { - // setup - sinon.stub(SkillMetadataController.prototype, 'enableSkill').callsArgWith(0, 'error'); - // call - helper.enableSkill(TEST_PROFILE, TEST_DO_DEBUG, (err) => { - expect(err).equal('error'); - expect(infoStub.args[0][0]).equal('\n==================== Enable Skill ===================='); - done(); - }); - }); - - it('| skillMetaController validateDomain fails, expect callback error', (done) => { - // setup - sinon.stub(SkillMetadataController.prototype, 'validateDomain').throws('test-error'); - // call - helper.enableSkill(TEST_PROFILE, TEST_DO_DEBUG, (err) => { - expect(err.name).equal('test-error'); - expect(infoStub.args[0][0]).equal('\n==================== Enable Skill ===================='); - done(); - }); - }); - - it('| skillMetaController enableSkill passes, expect no error callback', (done) => { - // setup - sinon.stub(SkillMetadataController.prototype, 'enableSkill').callsArgWith(0); - // call - helper.enableSkill(TEST_PROFILE, TEST_DO_DEBUG, (err, res) => { - // verify - expect(err).equal(undefined); - expect(res).equal(undefined); - expect(infoStub.args[0][0]).equal('\n==================== Enable Skill ===================='); - done(); - }); - }); +const {expect} = require("chai"); +const sinon = require("sinon"); + +const helper = require("../../../../lib/commands/deploy/helper"); +const SkillMetadataController = require("../../../../lib/controllers/skill-metadata-controller"); +const SkillCodeController = require("../../../../lib/controllers/skill-code-controller"); +const SkillInfrastructureController = require("../../../../lib/controllers/skill-infrastructure-controller"); +const CliError = require("../../../../lib/exceptions/cli-error"); +const ResourcesConfig = require("../../../../lib/model/resources-config"); +const CONSTANTS = require("../../../../lib/utils/constants"); +const profileHelper = require("../../../../lib/utils/profile-helper"); +const Messenger = require("../../../../lib/view/messenger"); +const SpinnerView = require("../../../../lib/view/spinner-view"); + +describe("Commands deploy test - helper test", () => { + const TEST_PROFILE = "default"; + const TEST_IGNORE_HASH = false; + const TEST_VENDOR_ID = "vendor"; + const TEST_DO_DEBUG = false; + const TEST_OPTIONS = {profile: TEST_PROFILE, doDebug: TEST_DO_DEBUG, ignoreHash: TEST_IGNORE_HASH}; + + describe("# test helper method - confirmProfile", () => { + afterEach(() => { + sinon.restore(); }); + + it("| profile does not exist, expect throw error", () => { + // setup + sinon.stub(ResourcesConfig.prototype, "getProfile").returns(undefined); + // call & verify + expect(() => helper.confirmProfile(TEST_PROFILE)).throw( + CliError, + `Profile [${TEST_PROFILE}] does not exist. Please configure it in your ${CONSTANTS.FILE_PATH.ASK_RESOURCES_JSON_CONFIG} file.`, + ); + }); + + it("| profile does exist, expect messenger info", () => { + // setup + const infoStub = sinon.stub(); + sinon.stub(Messenger, "getInstance").returns({ + info: infoStub, + }); + sinon.stub(ResourcesConfig.prototype, "getProfile").returns({test: "result"}); + // call & verify + expect(() => helper.confirmProfile(TEST_PROFILE)).to.not.throw(); + expect(infoStub.args[0][0]).equal(`Deploy project for profile [${TEST_PROFILE}]\n`); + }); + }); + + describe("# test helper method - deploySkillMetadata", () => { + afterEach(() => { + sinon.restore(); + }); + + it("| profile resolve vendorId fails, expect callback error", (done) => { + // setup + sinon.stub(profileHelper, "resolveVendorId").throws(new Error("error")); + // call + helper.deploySkillMetadata(TEST_OPTIONS, (err, res) => { + // verify + expect(err.message).equal("error"); + expect(res).equal(undefined); + done(); + }); + }); + + it("| skillMetaController deploySkillPackage fails, expect callback error", (done) => { + // setup + sinon.stub(profileHelper, "resolveVendorId").returns(TEST_VENDOR_ID); + sinon.stub(SkillMetadataController.prototype, "deploySkillPackage").callsArgWith(2, "error"); + // call + helper.deploySkillMetadata(TEST_OPTIONS, (err, res) => { + // verify + expect(err).equal("error"); + expect(res).equal(undefined); + done(); + }); + }); + + it("| skillMetaController deploySkillPackage passes, expect no error callback", (done) => { + // setup + sinon.stub(profileHelper, "resolveVendorId").returns(TEST_VENDOR_ID); + sinon.stub(SkillMetadataController.prototype, "deploySkillPackage").callsArgWith(2); + // call + helper.deploySkillMetadata(TEST_OPTIONS, (err, res) => { + // verify + expect(err).equal(undefined); + expect(res).equal(undefined); + done(); + }); + }); + }); + + describe("# test helper method - buildSkillCode", () => { + afterEach(() => { + sinon.restore(); + }); + + it("| skillCodeController buildSkillCode fails, expect callback error", (done) => { + // setup + sinon.stub(SkillCodeController.prototype, "buildCode").callsArgWith(0, "error"); + // call + helper.buildSkillCode(TEST_PROFILE, TEST_DO_DEBUG, (err, res) => { + // verify + expect(err).equal("error"); + expect(res).equal(undefined); + done(); + }); + }); + + it("| skillCodeController buildSkillCode passes, expect no error callback", (done) => { + // setup + sinon.stub(SkillCodeController.prototype, "buildCode").callsArgWith(0); + // call + helper.buildSkillCode(TEST_PROFILE, TEST_DO_DEBUG, (err, res) => { + // verify + expect(err).equal(null); + expect(res).equal(undefined); + done(); + }); + }); + }); + + describe("# test helper method - deploySkillInfrastructure", () => { + afterEach(() => { + sinon.restore(); + }); + + it("| skillInfraController deploySkillInfrastructure fails, expect callback error", (done) => { + // setup + sinon.stub(SkillInfrastructureController.prototype, "deployInfrastructure").callsArgWith(0, "error"); + // call + helper.deploySkillInfrastructure(TEST_PROFILE, TEST_DO_DEBUG, TEST_IGNORE_HASH, (err, res) => { + // verify + expect(err).equal("error"); + expect(res).equal(undefined); + done(); + }); + }); + + it("| skillInfraController deploySkillInfrastructure passes, expect no error callback", (done) => { + // setup + sinon.stub(SkillInfrastructureController.prototype, "deployInfrastructure").callsArgWith(0); + // call + helper.deploySkillInfrastructure(TEST_PROFILE, TEST_DO_DEBUG, TEST_IGNORE_HASH, (err, res) => { + // verify + expect(err).equal(undefined); + expect(res).equal(undefined); + done(); + }); + }); + }); + + describe("# test helper method - enableSkill", () => { + let infoStub; + beforeEach(() => { + infoStub = sinon.stub(); + sinon.stub(Messenger, "getInstance").returns({ + info: infoStub, + }); + }); + + afterEach(() => { + sinon.restore(); + }); + + it("| skillMetaController enableSkill fails, expect callback error", (done) => { + // setup + sinon.stub(SkillMetadataController.prototype, "validateDomain").returns(undefined); + sinon.stub(SkillMetadataController.prototype, "enableSkill").callsArgWith(0, "error"); + // call + helper.enableSkill(TEST_PROFILE, TEST_DO_DEBUG, (err) => { + expect(err).equal("error"); + expect(infoStub.args[0][0]).equal("\n==================== Enable Skill ===================="); + done(); + }); + }); + + it("| skillMetaController validateDomain fails, expect callback error", (done) => { + // setup + sinon.stub(SkillMetadataController.prototype, "validateDomain").throws("test-error"); + // call + helper.enableSkill(TEST_PROFILE, TEST_DO_DEBUG, (err) => { + expect(err.name).equal("test-error"); + expect(infoStub.args[0][0]).equal("\n==================== Enable Skill ===================="); + done(); + }); + }); + + it("| skillMetaController enableSkill passes, expect no error callback", (done) => { + // setup + sinon.stub(SkillMetadataController.prototype, "validateDomain").returns(undefined); + sinon.stub(SkillMetadataController.prototype, "enableSkill").callsArgWith(0); + // call + helper.enableSkill(TEST_PROFILE, TEST_DO_DEBUG, (err, res) => { + // verify + expect(err).equal(undefined); + expect(res).equal(undefined); + expect(infoStub.args[0][0]).equal("\n==================== Enable Skill ===================="); + done(); + }); + }); + }); }); diff --git a/test/unit/commands/deploy/index-test.js b/test/unit/commands/deploy/index-test.js deleted file mode 100644 index a8cd8704..00000000 --- a/test/unit/commands/deploy/index-test.js +++ /dev/null @@ -1,479 +0,0 @@ -const { expect } = require('chai'); -const sinon = require('sinon'); -const path = require('path'); -const fs = require('fs'); -const fse = require('fs-extra'); - -const DeployCommand = require('@src/commands/deploy'); -const helper = require('@src/commands/deploy/helper'); -const optionModel = require('@src/commands/option-model'); -const CliWarn = require('@src/exceptions/cli-warn'); -const ResourcesConfig = require('@src/model/resources-config'); -const Messenger = require('@src/view/messenger'); -const profileHelper = require('@src/utils/profile-helper'); -const stringUtils = require('@src/utils/string-utils'); -const CONSTANTS = require('@src/utils/constants'); - -describe('Commands deploy test - command class test', () => { - const FIXTURE_RESOURCES_CONFIG_FILE_PATH = path.join(process.cwd(), 'test', 'unit', 'fixture', 'model', 'regular-proj', 'ask-resources.json'); - const FIXTURE_MANIFEST_FILE = path.join(process.cwd(), 'test', 'unit', 'fixture', 'model', 'manifest.json'); - const TEST_PROFILE = 'default'; - const TEST_DEBUG = false; - const TEST_IGNORE_HASH = false; - - let infoStub; - let errorStub; - let warnStub; - - beforeEach(() => { - infoStub = sinon.stub(); - errorStub = sinon.stub(); - warnStub = sinon.stub(); - sinon.stub(Messenger, 'getInstance').returns({ - info: infoStub, - error: errorStub, - warn: warnStub - }); - }); - - afterEach(() => { - sinon.restore(); - }); - - it('| validate command information is set correctly', () => { - const instance = new DeployCommand(optionModel); - expect(instance.name()).equal('deploy'); - expect(instance.description()).equal('deploy the skill project'); - expect(instance.requiredOptions()).deep.equal([]); - expect(instance.optionalOptions()).deep.equal(['ignore-hash', 'target', 'profile', 'debug']); - }); - - describe('validate command handle', () => { - const TEST_CMD = { - profile: TEST_PROFILE, - debug: TEST_DEBUG, - ignoreHash: TEST_IGNORE_HASH - }; - const TEST_SKILL_METADATA_SRC = './skillPackage'; - let instance; - let pathStub; - - beforeEach(() => { - sinon.stub(profileHelper, 'runtimeProfile').returns(TEST_PROFILE); - pathStub = sinon.stub(path, 'join'); - pathStub.withArgs(process.cwd(), CONSTANTS.FILE_PATH.ASK_RESOURCES_JSON_CONFIG).returns(FIXTURE_RESOURCES_CONFIG_FILE_PATH); - pathStub.withArgs(TEST_SKILL_METADATA_SRC, CONSTANTS.FILE_PATH.SKILL_PACKAGE.MANIFEST).returns(FIXTURE_MANIFEST_FILE); - pathStub.callThrough(); - instance = new DeployCommand(optionModel); - }); - - afterEach(() => { - sinon.restore(); - }); - - describe('command handle - before deploy resources', () => { - it('| when profile is not correct, expect throw error', (done) => { - // setup - profileHelper.runtimeProfile.throws(new Error('error')); - // call - instance.handle(TEST_CMD, (err) => { - // verify - expect(err.message).equal('error'); - expect(errorStub.args[0][0].message).equal('error'); - expect(infoStub.callCount).equal(0); - expect(warnStub.callCount).equal(0); - done(); - }); - }); - - it('| when ResourcesConfig initiation fails, expect throw error', (done) => { - // setup - pathStub.withArgs(process.cwd(), CONSTANTS.FILE_PATH.ASK_RESOURCES_JSON_CONFIG).returns('invalidPath'); - // call - instance.handle(TEST_CMD, (err) => { - // verify - expect(err.message).includes('File invalidPath not exists.'); - expect(err.message).includes('please run \'ask util upgrade-project\''); - expect(errorStub.callCount).equal(0); - expect(infoStub.callCount).equal(0); - expect(warnStub.callCount).equal(1); - done(); - }); - }); - - it('| when deployer is alexa-hosted-deployer, expect throw warning', (done) => { - // setup - sinon.stub(ResourcesConfig.prototype, 'getSkillInfraType').returns(CONSTANTS.DEPLOYER_TYPE.HOSTED.NAME); - // call - instance.handle(TEST_CMD, (err) => { - // verify - expect(err).instanceOf(CliWarn); - expect(errorStub.callCount).equal(0); - expect(infoStub.callCount).equal(2); - expect(warnStub.callCount).equal(1); - done(); - }); - }); - - it('| when skillPackage src is not set, expect throw error', (done) => { - // setup - sinon.stub(stringUtils, 'isNonBlankString').returns(false); - // call - instance.handle(TEST_CMD, (err) => { - // verify - expect(err.message).equal('Skill package src is not found in ask-resources.json.'); - expect(errorStub.args[0][0]).equal('Skill package src is not found in ask-resources.json.'); - expect(infoStub.callCount).equal(2); - expect(warnStub.callCount).equal(0); - done(); - }); - }); - - it('| when skillPackage src does not exist, expect throw error', (done) => { - // setup - sinon.stub(fse, 'existsSync').withArgs('./skillPackage').returns(false); - // call - instance.handle(TEST_CMD, (err) => { - // verify - expect(err.message).equal('The skillMetadata src file ./skillPackage does not exist.'); - expect(errorStub.args[0][0]).equal('The skillMetadata src file ./skillPackage does not exist.'); - expect(infoStub.callCount).equal(2); - expect(warnStub.callCount).equal(0); - done(); - }); - }); - - it('| when Manifest initiation fails, expect throw error', (done) => { - // setup - sinon.stub(fse, 'existsSync').withArgs('./skillPackage').returns(true); - fse.existsSync.withArgs('invalidPath').returns(false); - sinon.stub(stringUtils, 'isNonBlankString').returns(true); - path.join.withArgs('./skillPackage', CONSTANTS.FILE_PATH.SKILL_PACKAGE.MANIFEST).returns('invalidPath'); - // call - instance.handle(TEST_CMD, (err) => { - // verify - expect(err.message).equal('File invalidPath not exists.'); - expect(errorStub.callCount).equal(0); - expect(infoStub.callCount).equal(2); - expect(warnStub.callCount).equal(1); - done(); - }); - }); - }); - - describe('command handle - deploy skill metadata', () => { - beforeEach(() => { - sinon.stub(fse, 'existsSync').returns(true); - }); - - it('| helper deploy skill metadata fails, expect throw error', (done) => { - // setup - sinon.stub(helper, 'deploySkillMetadata').callsArgWith(1, 'error'); - // call - instance.handle(TEST_CMD, (err) => { - // verify - expect(err).equal('error'); - expect(errorStub.args[0][0]).equal('error'); - expect(infoStub.args[0][0]).equal('Deploy configuration loaded from ask-resources.json'); - expect(infoStub.args[1][0]).equal(`Deploy project for profile [${TEST_PROFILE}]\n`); - expect(infoStub.args[2][0]).equal('==================== Deploy Skill Metadata ===================='); - expect(warnStub.callCount).equal(0); - done(); - }); - }); - - it('| helper deploy skill metadata with same hash skip result, expect display the message and continue', (done) => { - // setup - sinon.stub(helper, 'deploySkillMetadata').callsArgWith(1, - 'The hash of current skill package folder does not change compared to the last deploy hash result, ' - + 'CLI will skip the deploy of skill package.'); - sinon.stub(helper, 'buildSkillCode').callsArgWith(2, 'error'); - // call - instance.handle(TEST_CMD, (err) => { - // verify - expect(err).equal('error'); - expect(errorStub.args[0][0]).equal('error'); - expect(infoStub.args[2][0]).equal('==================== Deploy Skill Metadata ===================='); - expect(infoStub.args[3][0].startsWith('Skill ID:')).equal(true); - expect(warnStub.callCount).equal(1); - done(); - }); - }); - - it('| helper deploy skill metadata and no skillCode portion of work, expect quit with no error', (done) => { - // setup - sinon.stub(helper, 'deploySkillMetadata').callsArgWith(1, - 'The hash of current skill package folder does not change compared to the last deploy hash result, ' - + 'CLI will skip the deploy of skill package.'); - sinon.stub(ResourcesConfig.prototype, 'getCodeRegions').returns([]); - sinon.stub(helper, 'enableSkill').callsArgWith(2); - // call - instance.handle(TEST_CMD, (err) => { - // verify - expect(err).equal(undefined); - expect(infoStub.args[2][0]).equal('==================== Deploy Skill Metadata ===================='); - expect(infoStub.args[3][0].startsWith('Skill ID:')).equal(true); - expect(errorStub.callCount).equal(0); - expect(warnStub.callCount).equal(1); - done(); - }); - }); - - it('| helper deploy skill with skill metadata target, expect skip deploy metadata and skip build and infra deploy', (done) => { - // setup - sinon.stub(helper, 'deploySkillMetadata').callsArgWith(1); - sinon.stub(helper, 'enableSkill').callsArgWith(2); - const cmd = { ...TEST_CMD, target: CONSTANTS.DEPLOY_TARGET.SKILL_METADATA }; - - // call - instance.handle(cmd, (err) => { - // verify - expect(err).equal(undefined); - expect(infoStub.callCount).equal(5); - expect(infoStub.args[2][0]).equal('==================== Deploy Skill Metadata ===================='); - expect(infoStub.args[3][0]).equal('Skill package deployed successfully.'); - expect(infoStub.args[4][0].startsWith('Skill ID:')).equal(true); - expect(warnStub.callCount).equal(0); - done(); - }); - }); - - it('| helper deploy skill, expect error if non supported value provided for the target flag', (done) => { - // setup - const target = 'some-non-supported-target'; - const cmd = { ...TEST_CMD, target }; - - // call - instance.handle(cmd, (err) => { - // verify - expect(err.message).equal(`Target ${target} is not supported. Supported targets: ${Object.values(CONSTANTS.DEPLOY_TARGET)}.`); - done(); - }); - }); - }); - - describe('command handle - build skill code', () => { - beforeEach(() => { - sinon.stub(fse, 'existsSync').returns(true); - }); - - it('| helper build skill code fails, expect throw error', (done) => { - // setup - sinon.stub(helper, 'deploySkillMetadata').callsArgWith(1); - sinon.stub(helper, 'buildSkillCode').callsArgWith(2, 'error'); - // call - instance.handle(TEST_CMD, (err) => { - // verify - expect(err).equal('error'); - expect(errorStub.args[0][0]).equal('error'); - expect(infoStub.args[2][0]).equal('==================== Deploy Skill Metadata ===================='); - expect(infoStub.args[3][0]).equal('Skill package deployed successfully.'); - expect(infoStub.args[4][0].startsWith('Skill ID:')).equal(true); - expect(infoStub.args[5][0]).equal('\n==================== Build Skill Code ===================='); - expect(warnStub.callCount).equal(0); - done(); - }); - }); - }); - - describe('command handle - deploy skill infrastructure', () => { - const TEST_CODE_BUILD_RESULT = [{ - src: 'codeSrc', - build: { - file: 'buildFile', - folder: 'buildFolder' - }, - buildFlow: 'build-flow', - regionsList: ['default', 'NA'] - }]; - const TEST_CODE_SRC_BASENAME = 'base'; - - beforeEach(() => { - sinon.stub(fse, 'existsSync').returns(true); - }); - - it('| helper deploy skill infra without infraType, expect skip the flow by calling back', (done) => { - // setup - sinon.stub(helper, 'deploySkillMetadata').callsArgWith(1); - sinon.stub(helper, 'buildSkillCode').callsArgWith(2, null, TEST_CODE_BUILD_RESULT); - sinon.stub(helper, 'deploySkillInfrastructure').callsArgWith(2, 'error'); - sinon.stub(helper, 'enableSkill').callsArgWith(2); - sinon.stub(stringUtils, 'isNonBlankString').returns(true); - stringUtils.isNonBlankString.withArgs('@ask-cli/cfn-deployer').returns(false); - sinon.stub(path, 'resolve').returns(TEST_CODE_SRC_BASENAME); - sinon.stub(fs, 'statSync').returns({ - isDirectory: () => true - }); - path.join.withArgs(TEST_CODE_SRC_BASENAME).returns(TEST_CODE_SRC_BASENAME); - // call - instance.handle(TEST_CMD, (err) => { - // verify - expect(err).equal(undefined); - expect(infoStub.callCount).equal(8); - expect(infoStub.args[2][0]).equal('==================== Deploy Skill Metadata ===================='); - expect(infoStub.args[3][0]).equal('Skill package deployed successfully.'); - expect(infoStub.args[4][0].startsWith('Skill ID:')).equal(true); - expect(infoStub.args[5][0]).equal('\n==================== Build Skill Code ===================='); - expect(infoStub.args[6][0]).equal('Skill code built successfully.'); - expect(infoStub.args[7][0]).equal(`Code for region default+NA built to ${TEST_CODE_BUILD_RESULT[0].build.file} successfully \ -with build flow ${TEST_CODE_BUILD_RESULT[0].buildFlow}.`); - expect(warnStub.callCount).equal(0); - done(); - }); - }); - - it('| helper deploy skill with infrastructure target, expect skip skill metadata; build code and deploy infrastructure', (done) => { - // setup - sinon.stub(helper, 'deploySkillMetadata').callsArgWith(1); - sinon.stub(helper, 'enableSkill').callsArgWith(2); - sinon.stub(helper, 'buildSkillCode').callsArgWith(2, null, TEST_CODE_BUILD_RESULT); - sinon.stub(helper, 'deploySkillInfrastructure').callsArgWith(3); - sinon.stub(path, 'resolve').returns(TEST_CODE_SRC_BASENAME); - sinon.stub(fs, 'statSync').returns({ - isDirectory: () => true - }); - path.join.withArgs(TEST_CODE_SRC_BASENAME).returns(TEST_CODE_SRC_BASENAME); - const cmd = { ...TEST_CMD, target: CONSTANTS.DEPLOY_TARGET.SKILL_INFRASTRUCTURE }; - - // call - instance.handle(cmd, (err) => { - // verify - expect(err).equal(undefined); - expect(errorStub.callCount).equal(0); - expect(infoStub.callCount).equal(7); - expect(infoStub.args[2][0]).equal('\n==================== Build Skill Code ===================='); - expect(infoStub.args[3][0]).equal('Skill code built successfully.'); - expect(infoStub.args[4][0]).equal(`Code for region default+NA built to ${TEST_CODE_BUILD_RESULT[0].build.file} successfully \ -with build flow ${TEST_CODE_BUILD_RESULT[0].buildFlow}.`); - expect(infoStub.args[5][0]).equal('\n==================== Deploy Skill Infrastructure ===================='); - expect(infoStub.args[6][0]).equal('Skill infrastructures deployed successfully through @ask-cli/cfn-deployer.'); - expect(warnStub.callCount).equal(0); - expect(helper.enableSkill.calledOnce).equal(false); - done(); - }); - }); - - it('| helper deploy skill with infrastructure target, expect throw error when skill id does not exist', (done) => { - // setup - sinon.stub(ResourcesConfig.prototype, 'getSkillId').returns(undefined); - const cmd = { ...TEST_CMD, target: CONSTANTS.DEPLOY_TARGET.SKILL_INFRASTRUCTURE }; - - // call - instance.handle(cmd, (err) => { - // verify - expect(err.message).include('the skillId has not been created yet. Please deploy your skillMetadata first'); - done(); - }); - }); - - it('| helper deploy skill infra fails, expect throw error', (done) => { - // setup - sinon.stub(helper, 'deploySkillMetadata').callsArgWith(1); - sinon.stub(helper, 'buildSkillCode').callsArgWith(2, null, TEST_CODE_BUILD_RESULT); - sinon.stub(helper, 'deploySkillInfrastructure').callsArgWith(3, 'error'); - sinon.stub(helper, 'enableSkill').callsArgWith(2); - sinon.stub(path, 'resolve').returns(TEST_CODE_SRC_BASENAME); - sinon.stub(fs, 'statSync').returns({ - isDirectory: () => true - }); - path.join.withArgs(TEST_CODE_SRC_BASENAME).returns(TEST_CODE_SRC_BASENAME); - // call - instance.handle(TEST_CMD, (err) => { - // verify - expect(err).equal('error'); - expect(errorStub.args[0][0]).equal('error'); - expect(infoStub.args[2][0]).equal('==================== Deploy Skill Metadata ===================='); - expect(infoStub.args[3][0]).equal('Skill package deployed successfully.'); - expect(infoStub.args[4][0].startsWith('Skill ID:')).equal(true); - expect(infoStub.args[5][0]).equal('\n==================== Build Skill Code ===================='); - expect(infoStub.args[6][0]).equal('Skill code built successfully.'); - expect(infoStub.args[7][0]).equal(`Code for region default+NA built to ${TEST_CODE_BUILD_RESULT[0].build.file} successfully \ -with build flow ${TEST_CODE_BUILD_RESULT[0].buildFlow}.`); - expect(infoStub.args[8][0]).equal('\n==================== Deploy Skill Infrastructure ===================='); - expect(warnStub.callCount).equal(0); - done(); - }); - }); - - it('| deploy skill all pass, expect deploy succeeds and enableSkill get called', (done) => { - // setup - sinon.stub(helper, 'deploySkillMetadata').callsArgWith(1); - sinon.stub(helper, 'buildSkillCode').callsArgWith(2, null, TEST_CODE_BUILD_RESULT); - sinon.stub(helper, 'deploySkillInfrastructure').callsArgWith(3); - sinon.stub(helper, 'enableSkill').callsArgWith(2); - sinon.stub(path, 'resolve').returns(TEST_CODE_SRC_BASENAME); - sinon.stub(fs, 'statSync').returns({ - isDirectory: () => true - }); - path.join.withArgs(TEST_CODE_SRC_BASENAME).returns(TEST_CODE_SRC_BASENAME); - // call - instance.handle(TEST_CMD, (err) => { - // verify - expect(err).equal(undefined); - expect(errorStub.callCount).equal(0); - expect(infoStub.callCount).equal(10); - expect(infoStub.args[2][0]).equal('==================== Deploy Skill Metadata ===================='); - expect(infoStub.args[3][0]).equal('Skill package deployed successfully.'); - expect(infoStub.args[4][0].startsWith('Skill ID:')).equal(true); - expect(infoStub.args[5][0]).equal('\n==================== Build Skill Code ===================='); - expect(infoStub.args[6][0]).equal('Skill code built successfully.'); - expect(infoStub.args[7][0]).equal(`Code for region default+NA built to ${TEST_CODE_BUILD_RESULT[0].build.file} successfully \ -with build flow ${TEST_CODE_BUILD_RESULT[0].buildFlow}.`); - expect(infoStub.args[8][0]).equal('\n==================== Deploy Skill Infrastructure ===================='); - expect(infoStub.args[9][0]).equal('Skill infrastructures deployed successfully through @ask-cli/cfn-deployer.'); - expect(warnStub.callCount).equal(0); - expect(helper.enableSkill.calledOnce).equal(true); - done(); - }); - }); - }); - - describe('command handle - enable skill', () => { - const TEST_CODE_BUILD_RESULT = [{ - src: 'codeSrc', - build: { - file: 'buildFile', - folder: 'buildFolder' - }, - buildFlow: 'build-flow', - regionsList: ['default', 'NA'] - }]; - - beforeEach(() => { - sinon.stub(fse, 'existsSync').returns(true); - }); - - it('| can callbcak warn when enable fails with CliWarn class', (done) => { - // setup - const TEST_WARN = new CliWarn('warn'); - sinon.stub(helper, 'deploySkillMetadata').callsArgWith(1); - sinon.stub(helper, 'buildSkillCode').callsArgWith(2, null, TEST_CODE_BUILD_RESULT); - sinon.stub(helper, 'deploySkillInfrastructure').callsArgWith(3); - sinon.stub(helper, 'enableSkill').callsArgWith(2, TEST_WARN); - // call - instance.handle(TEST_CMD, (err) => { - // verify - expect(warnStub.args[0][0]).equal(TEST_WARN); - expect(err).equal(undefined); - done(); - }); - }); - - it('| can callbcak error when enable fails', (done) => { - // setup - const TEST_ERROR = 'error'; - sinon.stub(helper, 'deploySkillMetadata').callsArgWith(1); - sinon.stub(helper, 'buildSkillCode').callsArgWith(2, null, TEST_CODE_BUILD_RESULT); - sinon.stub(helper, 'deploySkillInfrastructure').callsArgWith(3); - sinon.stub(helper, 'enableSkill').callsArgWith(2, 'error'); - // call - instance.handle(TEST_CMD, (err) => { - // verify - expect(errorStub.args[0][0]).equal(TEST_ERROR); - expect(err).equal(TEST_ERROR); - done(); - }); - }); - }); - }); -}); diff --git a/test/unit/commands/deploy/index-test.ts b/test/unit/commands/deploy/index-test.ts new file mode 100644 index 00000000..a32d80d2 --- /dev/null +++ b/test/unit/commands/deploy/index-test.ts @@ -0,0 +1,514 @@ +import {expect} from "chai"; +import sinon from "sinon"; +import path from "path"; +import fs from "fs"; +import fse from "fs-extra"; +import DeployCommand from "../../../../lib/commands/deploy"; +import helper from "../../../../lib/commands/deploy/helper"; +import optionModel from "../../../../lib/commands/option-model.json"; +import CliWarn from "../../../../lib/exceptions/cli-warn"; +import ResourcesConfig from "../../../../lib/model/resources-config"; +import Messenger from "../../../../lib/view/messenger"; +import profileHelper from "../../../../lib/utils/profile-helper"; +import stringUtils from "../../../../lib/utils/string-utils"; +import CONSTANTS from "../../../../lib/utils/constants"; +import {OptionModel} from "../../../../lib/commands/option-validator"; +import CliError from "../../../../lib/exceptions/cli-error"; +import acUtils from "../../../../lib/utils/ac-util"; +import ui from "../../../../lib/commands/deploy/ui"; + +describe("Commands deploy test - command class test", () => { + const FIXTURE_RESOURCES_CONFIG_FILE_PATH = path.join( + process.cwd(), + "test", + "unit", + "fixture", + "model", + "regular-proj", + "ask-resources.json", + ); + const FIXTURE_MANIFEST_FILE = path.join(process.cwd(), "test", "unit", "fixture", "model", "manifest.json"); + const TEST_PROFILE = "default"; + const TEST_DEBUG = false; + const TEST_IGNORE_HASH = false; + + let infoStub: sinon.SinonStub; + let errorStub: sinon.SinonStub; + let warnStub: sinon.SinonStub; + + beforeEach(() => { + infoStub = sinon.stub(); + errorStub = sinon.stub(); + warnStub = sinon.stub(); + sinon.stub(Messenger, "getInstance").returns({ + info: infoStub, + error: errorStub, + warn: warnStub, + }); + }); + + afterEach(() => { + sinon.restore(); + }); + + it("| validate command information is set correctly", () => { + const instance = new DeployCommand(optionModel as OptionModel); + expect(instance.name()).equal("deploy"); + expect(instance.description()).equal("deploy the skill project"); + expect(instance.requiredOptions()).deep.equal([]); + expect(instance.optionalOptions()).deep.equal(["ignore-hash", "target", "profile", "debug"]); + }); + + describe("validate command handle", () => { + const TEST_CMD = { + profile: TEST_PROFILE, + debug: TEST_DEBUG, + ignoreHash: TEST_IGNORE_HASH, + }; + const TEST_SKILL_METADATA_SRC = "./skillPackage"; + let instance: DeployCommand; + let pathStub: sinon.SinonStub; + let profileHelperRuntimeProfile: sinon.SinonStub; + + beforeEach(() => { + profileHelperRuntimeProfile = sinon.stub(profileHelper, "runtimeProfile").returns(TEST_PROFILE); + pathStub = sinon.stub(path, "join"); + pathStub.withArgs(process.cwd(), CONSTANTS.FILE_PATH.ASK_RESOURCES_JSON_CONFIG).returns(FIXTURE_RESOURCES_CONFIG_FILE_PATH); + pathStub.withArgs(TEST_SKILL_METADATA_SRC, CONSTANTS.FILE_PATH.SKILL_PACKAGE.MANIFEST).returns(FIXTURE_MANIFEST_FILE); + pathStub.callThrough(); + instance = new DeployCommand(optionModel as OptionModel); + }); + + afterEach(() => { + sinon.restore(); + }); + + describe("command handle - before deploy resources", () => { + it("| when profile is not correct, expect throw error", async () => { + // setup + profileHelperRuntimeProfile.throws(new CliError("error")); + // call + await expect(instance.handle(TEST_CMD)).eventually.be.rejected.and.be.instanceOf(CliError); + // verify + expect(errorStub).calledOnceWith("error"); + expect(infoStub).not.called; + expect(warnStub).not.called; + }); + + it("| when ResourcesConfig initiation fails, expect throw error", async () => { + // setup + pathStub.withArgs(process.cwd(), CONSTANTS.FILE_PATH.ASK_RESOURCES_JSON_CONFIG).returns("invalidPath"); + // call + await expect(instance.handle(TEST_CMD)).rejected; + // verify + expect(warnStub).calledOnce; + expect(infoStub).not.called; + expect(errorStub).not.called; + }); + + it("| when deployer is alexa-hosted-deployer, expect throw warning", async () => { + // setup + sinon.stub(ResourcesConfig.prototype, "getSkillInfraType").returns(CONSTANTS.DEPLOYER_TYPE.HOSTED.NAME); + // call + await expect(instance.handle(TEST_CMD)).eventually.rejected.instanceOf(CliWarn); + // verify + expect(warnStub).calledOnce; + expect(infoStub).calledTwice; + expect(errorStub).not.called; + }); + + it("| when skillPackage src is not set, expect throw error", async () => { + // setup + sinon.stub(stringUtils, "isNonBlankString").returns(false); + // call + await expect(instance.handle(TEST_CMD)).eventually.rejected.property( + "message", + "Skill package src is not found in ask-resources.json.", + ); + // verify + expect(errorStub).calledOnceWith("Skill package src is not found in ask-resources.json."); + expect(infoStub).calledTwice; + expect(warnStub).not.called; + }); + + it("| when skillPackage src does not exist, expect throw error", async () => { + // setup + sinon.stub(fse, "existsSync").withArgs("./skillPackage").returns(false); + // call + await expect(instance.handle(TEST_CMD)).eventually.rejected.property( + "message", + "The skillMetadata src file ./skillPackage does not exist.", + ); + // verify + expect(errorStub).calledOnceWith("The skillMetadata src file ./skillPackage does not exist."); + expect(infoStub).calledTwice; + expect(warnStub).not.called; + }); + + it("| when Manifest initiation fails, expect throw error", async () => { + // setup + const fseExistsSync = sinon.stub(fse, "existsSync").withArgs("./skillPackage").returns(true); + fseExistsSync.withArgs("invalidPath").returns(false); + sinon.stub(stringUtils, "isNonBlankString").returns(true); + pathStub.withArgs("./skillPackage", CONSTANTS.FILE_PATH.SKILL_PACKAGE.MANIFEST).returns("invalidPath"); + // call + await expect(instance.handle(TEST_CMD)).eventually.rejected.property("message", "File invalidPath not exists."); + // verify + expect(warnStub).calledOnce; + expect(infoStub).calledTwice; + expect(errorStub).not.called; + }); + }); + + describe("command handle - deploy skill metadata", () => { + beforeEach(() => { + sinon.stub(fse, "existsSync").returns(true); + }); + + it("| helper deploy skill metadata fails, expect throw error", async () => { + // setup + sinon.stub(helper, "deploySkillMetadata").callsArgWith(1, "error"); + // call + await expect(instance.handle(TEST_CMD)).rejectedWith("error"); + // verify + expect(errorStub).calledOnceWith("error"); + expect(infoStub.getCall(0)).calledWith("Deploy configuration loaded from ask-resources.json"); + expect(infoStub.getCall(1)).calledWith(`Deploy project for profile [${TEST_PROFILE}]\n`); + expect(infoStub.getCall(2)).calledWith("==================== Deploy Skill Metadata ===================="); + expect(warnStub).not.called; + }); + + it("| helper deploy skill metadata with same hash skip result, expect display the message and continue", async () => { + // setup + sinon + .stub(helper, "deploySkillMetadata") + .callsArgWith( + 1, + "The hash of current skill package folder does not change compared to the last deploy hash result, " + + "CLI will skip the deploy of skill package.", + ); + sinon.stub(helper, "buildSkillCode").callsArgWith(2, "error"); + // call + await expect(instance.handle(TEST_CMD)).rejectedWith("error"); + // verify + expect(errorStub).calledOnceWith("error"); + expect(infoStub.getCall(2)).calledWith("==================== Deploy Skill Metadata ===================="); + expect(infoStub.getCall(3).args[0]).contains("Uploading the entire skill package and building the models. Normally it takes a few minutes..."); + expect(infoStub.getCall(4).args[0]).contains("Skill ID:"); + expect(warnStub).calledOnce; + }); + + it("| helper deploy skill metadata and no skillCode portion of work, expect quit with no error", async () => { + // setup + sinon + .stub(helper, "deploySkillMetadata") + .callsArgWith( + 1, + "The hash of current skill package folder does not change compared to the last deploy hash result, " + + "CLI will skip the deploy of skill package.", + ); + sinon.stub(ResourcesConfig.prototype, "getCodeRegions").returns([]); + sinon.stub(helper, "enableSkill").callsArgWith(2); + // call + await instance.handle(TEST_CMD); + // verify + expect(errorStub).not.called; + expect(infoStub.getCall(2)).calledWith("==================== Deploy Skill Metadata ===================="); + expect(infoStub.getCall(3).args[0]).contains("Uploading the entire skill package and building the models. Normally it takes a few minutes..."); + expect(infoStub.getCall(4).args[0]).contains("Skill ID:"); + expect(warnStub).calledOnce; + }); + + it("| helper deploy skill with skill metadata target, expect skip deploy metadata and skip build and infra deploy", async () => { + // setup + sinon.stub(helper, "deploySkillMetadata").callsArgWith(1); + sinon.stub(helper, "enableSkill").callsArgWith(2); + const cmd = {...TEST_CMD, target: CONSTANTS.DEPLOY_TARGET.SKILL_METADATA}; + + // call + await instance.handle(cmd); + // verify + expect(errorStub).not.called; + expect(infoStub.getCall(2)).calledWith("==================== Deploy Skill Metadata ===================="); + expect(infoStub.getCall(3).args[0]).contains("Uploading the entire skill package and building the models. Normally it takes a few minutes..."); + expect(infoStub.getCall(4).args[0]).contains("Skill package deployed and all models built successfully."); + expect(infoStub.getCall(5).args[0]).contains("Skill ID:"); + expect(warnStub).not.called; + }); + + it("| helper deploy skill, expect error if non supported value provided for the target flag", async () => { + // setup + const target = "some-non-supported-target"; + const cmd = {...TEST_CMD, target}; + + // call + await expect(instance.handle(cmd)).rejectedWith( + `Target ${target} is not supported. Supported targets: ${Object.values(CONSTANTS.DEPLOY_TARGET)}.`, + ); + }); + }); + + describe("command handle - build skill code", () => { + beforeEach(() => { + sinon.stub(fse, "existsSync").returns(true); + }); + + it("| helper build skill code fails, expect throw error", async () => { + // setup + sinon.stub(helper, "deploySkillMetadata").callsArgWith(1); + sinon.stub(helper, "buildSkillCode").callsArgWith(2, "error"); + // call + await expect(instance.handle(TEST_CMD)).rejectedWith("error"); + // verify + expect(errorStub).calledOnceWith("error"); + expect(infoStub.getCall(2)).calledWith("==================== Deploy Skill Metadata ===================="); + expect(infoStub.getCall(3).args[0]).contains("Uploading the entire skill package and building the models. Normally it takes a few minutes..."); + expect(infoStub.getCall(4).args[0]).equal("Skill package deployed and all models built successfully."); + expect(infoStub.getCall(5).args[0]).contains("Skill ID:"); + expect(infoStub.getCall(6).args[0]).equal("\n==================== Build Skill Code ===================="); + expect(warnStub).not.called; + }); + }); + + describe("command handle - deploy skill infrastructure", () => { + const TEST_CODE_BUILD_RESULT = [ + { + src: "codeSrc", + build: { + file: "buildFile", + folder: "buildFolder", + }, + buildFlow: "build-flow", + regionsList: ["default", "NA"], + }, + ]; + const TEST_CODE_SRC_BASENAME = "base"; + + beforeEach(() => { + sinon.stub(fse, "existsSync").returns(true); + }); + + it("| helper deploy skill infra without infraType, expect skip the flow by calling back", async () => { + // setup + sinon.stub(helper, "deploySkillMetadata").callsArgWith(1); + sinon.stub(helper, "buildSkillCode").callsArgWith(2, null, TEST_CODE_BUILD_RESULT); + sinon.stub(helper, "deploySkillInfrastructure").callsArgWith(2, "error"); + sinon.stub(helper, "enableSkill").callsArgWith(2); + const stringUtilsIsNonBlankString = sinon.stub(stringUtils, "isNonBlankString").returns(true); + stringUtilsIsNonBlankString.withArgs("@ask-cli/cfn-deployer").returns(false); + sinon.stub(path, "resolve").returns(TEST_CODE_SRC_BASENAME); + sinon.stub(fs, "statSync").returns({ + isDirectory: () => true, + } as any); + pathStub.withArgs(TEST_CODE_SRC_BASENAME).returns(TEST_CODE_SRC_BASENAME); + // call + await instance.handle(TEST_CMD); + // verify + expect(errorStub).not.called; + expect(infoStub.getCall(2).args[0]).equals("==================== Deploy Skill Metadata ===================="); + expect(infoStub.getCall(3).args[0]).contains("Uploading the entire skill package and building the models. Normally it takes a few minutes..."); + expect(infoStub.getCall(4).args[0]).equals("Skill package deployed and all models built successfully."); + expect(infoStub.getCall(5).args[0]).contains("Skill ID:"); + expect(infoStub.getCall(6).args[0]).equals("\n==================== Build Skill Code ===================="); + expect(infoStub.getCall(7).args[0]).equals("Skill code built successfully."); + expect(infoStub.getCall(8).args[0]) + .equals(`Code for region default+NA built to ${TEST_CODE_BUILD_RESULT[0].build.file} successfully \ +with build flow ${TEST_CODE_BUILD_RESULT[0].buildFlow}.`); + expect(warnStub).not.called; + }); + + it("| helper deploy skill with infrastructure target, expect skip skill metadata; build code and deploy infrastructure", async () => { + // setup + sinon.stub(helper, "deploySkillMetadata").callsArgWith(1); + const enabledStub = sinon.stub(helper, "enableSkill").callsArgWith(2); + sinon.stub(helper, "buildSkillCode").callsArgWith(2, null, TEST_CODE_BUILD_RESULT); + sinon.stub(helper, "deploySkillInfrastructure").callsArgWith(3); + sinon.stub(path, "resolve").returns(TEST_CODE_SRC_BASENAME); + sinon.stub(fs, "statSync").returns({ + isDirectory: () => true, + } as any); + pathStub.withArgs(TEST_CODE_SRC_BASENAME).returns(TEST_CODE_SRC_BASENAME); + const cmd = {...TEST_CMD, target: CONSTANTS.DEPLOY_TARGET.SKILL_INFRASTRUCTURE}; + + // call + await instance.handle(cmd); + // verify + expect(errorStub).not.called; + expect(infoStub.getCall(2).args[0]).equals("\n==================== Build Skill Code ===================="); + expect(infoStub.getCall(3).args[0]).equals("Skill code built successfully."); + expect(infoStub.getCall(4).args[0]) + .equals(`Code for region default+NA built to ${TEST_CODE_BUILD_RESULT[0].build.file} successfully \ +with build flow ${TEST_CODE_BUILD_RESULT[0].buildFlow}.`); + expect(infoStub.getCall(5).args[0]).equals("\n==================== Deploy Skill Infrastructure ===================="); + expect(infoStub.getCall(6).args[0]).equals("\nSkill infrastructures deployed successfully through @ask-cli/cfn-deployer."); + expect(warnStub).not.called; + expect(enabledStub).not.calledOnce; + }); + + it("| helper deploy skill with infrastructure target, expect throw error when skill id does not exist", async () => { + // setup + sinon.stub(ResourcesConfig.prototype, "getSkillId").returns(undefined); + const cmd = {...TEST_CMD, target: CONSTANTS.DEPLOY_TARGET.SKILL_INFRASTRUCTURE}; + + // call + await expect(instance.handle(cmd)) + .eventually.rejected.property("message") + .include("the skillId has not been created yet. Please deploy your skillMetadata first"); + }); + + it("| helper deploy skill infra fails, expect throw error", async () => { + // setup + sinon.stub(helper, "deploySkillMetadata").callsArgWith(1); + sinon.stub(helper, "buildSkillCode").callsArgWith(2, null, TEST_CODE_BUILD_RESULT); + sinon.stub(helper, "deploySkillInfrastructure").callsArgWith(3, "error"); + sinon.stub(helper, "enableSkill").callsArgWith(2); + sinon.stub(path, "resolve").returns(TEST_CODE_SRC_BASENAME); + sinon.stub(fs, "statSync").returns({ + isDirectory: () => true, + } as any); + pathStub.withArgs(TEST_CODE_SRC_BASENAME).returns(TEST_CODE_SRC_BASENAME); + // call + await expect(instance.handle(TEST_CMD)).rejectedWith("error"); + // verify + expect(errorStub).calledWith("error"); + expect(infoStub.getCall(2).args[0]).equals("==================== Deploy Skill Metadata ===================="); + expect(infoStub.getCall(3).args[0]).contains("Uploading the entire skill package and building the models. Normally it takes a few minutes..."); + expect(infoStub.getCall(4).args[0]).equals("Skill package deployed and all models built successfully."); + expect(infoStub.getCall(5).args[0]).contains("Skill ID:"); + expect(infoStub.getCall(6).args[0]).equals("\n==================== Build Skill Code ===================="); + expect(infoStub.getCall(7).args[0]).equals("Skill code built successfully."); + expect(infoStub.getCall(8).args[0]) + .equals(`Code for region default+NA built to ${TEST_CODE_BUILD_RESULT[0].build.file} successfully \ +with build flow ${TEST_CODE_BUILD_RESULT[0].buildFlow}.`); + expect(infoStub.getCall(9).args[0]).equals("\n==================== Deploy Skill Infrastructure ===================="); + expect(warnStub).not.called; + }); + + it("| deploy skill all pass, expect deploy succeeds and enableSkill get called", async () => { + // setup + sinon.stub(helper, "deploySkillMetadata").callsArgWith(1); + sinon.stub(helper, "buildSkillCode").callsArgWith(2, null, TEST_CODE_BUILD_RESULT); + sinon.stub(helper, "deploySkillInfrastructure").callsArgWith(3); + const enabledSkillStub = sinon.stub(helper, "enableSkill").callsArgWith(2); + sinon.stub(path, "resolve").returns(TEST_CODE_SRC_BASENAME); + sinon.stub(fs, "statSync").returns({ + isDirectory: () => true, + } as any); + pathStub.withArgs(TEST_CODE_SRC_BASENAME).returns(TEST_CODE_SRC_BASENAME); + // call + await instance.handle(TEST_CMD); + // verify + expect(errorStub).not.called; + expect(infoStub.getCall(2).args[0]).equals("==================== Deploy Skill Metadata ===================="); + expect(infoStub.getCall(3).args[0]).contains("Uploading the entire skill package and building the models. Normally it takes a few minutes..."); + expect(infoStub.getCall(4).args[0]).equals("Skill package deployed and all models built successfully."); + expect(infoStub.getCall(5).args[0]).contains("Skill ID:"); + expect(infoStub.getCall(6).args[0]).equals("\n==================== Build Skill Code ===================="); + expect(infoStub.getCall(7).args[0]).equals("Skill code built successfully."); + expect(infoStub.getCall(8).args[0]) + .equals(`Code for region default+NA built to ${TEST_CODE_BUILD_RESULT[0].build.file} successfully \ +with build flow ${TEST_CODE_BUILD_RESULT[0].buildFlow}.`); + expect(infoStub.getCall(9).args[0]).equals("\n==================== Deploy Skill Infrastructure ===================="); + expect(infoStub.getCall(10).args[0]).equals("\nSkill infrastructures deployed successfully through @ask-cli/cfn-deployer."); + expect(warnStub).not.called; + expect(enabledSkillStub).calledOnce; + }); + + it("| deploy skill succeeds for ac skill, expect ask states lastDeployType is AC", async () => { + // setup + const setLastDeployTypeStub = sinon.spy(ResourcesConfig.prototype, "setSkillMetaLastDeployType"); + sinon.stub(acUtils, "isAcSkill").returns(true); + sinon.stub(ui, "confirmDeploymentIfNeeded").callsArgWith(1, null, true); + sinon.stub(helper, "deploySkillMetadata").callsArgWith(1); + sinon.stub(helper, "buildSkillCode").callsArgWith(2, null, TEST_CODE_BUILD_RESULT); + sinon.stub(helper, "deploySkillInfrastructure").callsArgWith(3); + const enabledSkillStub = sinon.stub(helper, "enableSkill").callsArgWith(2); + sinon.stub(path, "resolve").returns(TEST_CODE_SRC_BASENAME); + sinon.stub(fs, "statSync").returns({ + isDirectory: () => true, + } as any); + pathStub.withArgs(TEST_CODE_SRC_BASENAME).returns(TEST_CODE_SRC_BASENAME); + + // call + await instance.handle(TEST_CMD); + + // verify + expect(infoStub.getCall(3).args[0]).contains("Uploading the entire skill package and building the models. For Alexa Conversations it can take 20-60 minutes..."); + expect(infoStub.getCall(10).args[0]).equals("\nSkill infrastructures deployed successfully through @ask-cli/cfn-deployer."); + expect(errorStub).not.called; + expect(warnStub).calledOnceWith(CONSTANTS.ACDL_BETA_MESSAGE + "\n"); + expect(enabledSkillStub).calledOnce; + expect(setLastDeployTypeStub).calledOnceWith(TEST_PROFILE, CONSTANTS.DEPLOYMENT_TYPE.ALEXA_CONVERSATIONS); + }); + + it("| deploy skill succeeds for IM skill, expect ask states lastDeployType is IM", async () => { + // setup + const setLastDeployTypeStub = sinon.stub(ResourcesConfig.prototype, "setSkillMetaLastDeployType"); + sinon.stub(acUtils, "isAcSkill").returns(false); + sinon.stub(helper, "deploySkillMetadata").callsArgWith(1); + sinon.stub(helper, "buildSkillCode").callsArgWith(2, null, TEST_CODE_BUILD_RESULT); + sinon.stub(helper, "deploySkillInfrastructure").callsArgWith(3); + const enabledSkillStub = sinon.stub(helper, "enableSkill").callsArgWith(2); + sinon.stub(path, "resolve").returns(TEST_CODE_SRC_BASENAME); + sinon.stub(fs, "statSync").returns({ + isDirectory: () => true, + } as any); + pathStub.withArgs(TEST_CODE_SRC_BASENAME).returns(TEST_CODE_SRC_BASENAME); + // call + await instance.handle(TEST_CMD); + + // verify + expect(infoStub.getCall(3).args[0]).contains("Uploading the entire skill package and building the models. Normally it takes a few minutes..."); + expect(infoStub.getCall(10).args[0]).equals("\nSkill infrastructures deployed successfully through @ask-cli/cfn-deployer."); + expect(errorStub).not.called; + expect(warnStub).not.called; + expect(enabledSkillStub).calledOnce; + expect(setLastDeployTypeStub).calledOnceWith(TEST_PROFILE, CONSTANTS.DEPLOYMENT_TYPE.INTERACTION_MODEL); + }); + }); + + describe("command handle - enable skill", () => { + const TEST_CODE_BUILD_RESULT = [ + { + src: "codeSrc", + build: { + file: "buildFile", + folder: "buildFolder", + }, + buildFlow: "build-flow", + regionsList: ["default", "NA"], + }, + ]; + + beforeEach(() => { + sinon.stub(fse, "existsSync").returns(true); + }); + + it("| can callback warn when enable fails with CliWarn class", async () => { + // setup + const TEST_WARN = new CliWarn("warn"); + sinon.stub(helper, "deploySkillMetadata").callsArgWith(1); + sinon.stub(helper, "buildSkillCode").callsArgWith(2, null, TEST_CODE_BUILD_RESULT); + sinon.stub(helper, "deploySkillInfrastructure").callsArgWith(3); + sinon.stub(helper, "enableSkill").callsArgWith(2, TEST_WARN); + // call + await instance.handle(TEST_CMD); + // verify + expect(warnStub).calledWith(TEST_WARN); + }); + + it("| can callback error when enable fails", async () => { + // setup + const TEST_ERROR = "error"; + sinon.stub(helper, "deploySkillMetadata").callsArgWith(1); + sinon.stub(helper, "buildSkillCode").callsArgWith(2, null, TEST_CODE_BUILD_RESULT); + sinon.stub(helper, "deploySkillInfrastructure").callsArgWith(3); + sinon.stub(helper, "enableSkill").callsArgWith(2, "error"); + // call + await expect(instance.handle(TEST_CMD)).rejectedWith(TEST_ERROR); + // verify + expect(errorStub).calledWith(TEST_ERROR); + }); + }); + }); +}); diff --git a/test/unit/commands/deploy/ui-test.js b/test/unit/commands/deploy/ui-test.js new file mode 100644 index 00000000..9832ef56 --- /dev/null +++ b/test/unit/commands/deploy/ui-test.js @@ -0,0 +1,130 @@ +const {expect} = require("chai"); +const sinon = require("sinon"); + +const Messenger = require("../../../../lib/view/messenger"); +const CONSTANTS = require("../../../../lib/utils/constants"); +const inquirer = require("inquirer"); +const ResourcesConfig = require("../../../../lib/model/resources-config"); +const acUtils = require("../../../../lib/utils/ac-util"); +const {confirmDeploymentIfNeeded} = require("../../../../lib/commands/deploy/ui"); + +describe("Commands deploy test - ui test", () => { + const TEST_PROFILE = "default"; + + let infoStub; + let errorStub; + let warnStub; + let inquirerStub; + let getLastDeployTypeStub; + let isACSkillStub; + let callbackStub; + + beforeEach(() => { + infoStub = sinon.stub(); + errorStub = sinon.stub(); + warnStub = sinon.stub(); + inquirerStub = sinon.stub(inquirer, "prompt").resolves({confirmation: true}); + sinon.stub(Messenger, "getInstance").returns({ + error: errorStub, + warn: warnStub, + }); + getLastDeployTypeStub = sinon.stub(); + isACSkillStub = sinon.stub(acUtils, "isAcSkill"); + callbackStub = sinon.stub(); + sinon.stub(ResourcesConfig, "getInstance").returns({ + getSkillMetaLastDeployType: getLastDeployTypeStub, + }); + }); + + afterEach(() => { + sinon.restore(); + }); + + it("callback is called with false when user answers no when confirming deployment", (done) => { + // setup + getLastDeployTypeStub.returns(undefined); + isACSkillStub.returns(true); + inquirerStub.resolves({confirmation: false}); + // call + confirmDeploymentIfNeeded(TEST_PROFILE, (err, answer) => { + // verify + expect(inquirerStub.called).to.be.true; + expect(err).equal(null); + expect(answer).to.be.false; + done(); + }); + }); + + it("deployment confirmation is skipped if non AC skill", (done) => { + // setup + getLastDeployTypeStub.returns(CONSTANTS.DEPLOYMENT_TYPE.ALEXA_CONVERSATIONS); + isACSkillStub.returns(false); + // call + confirmDeploymentIfNeeded(TEST_PROFILE, (err, answer) => { + // verify + expect(inquirerStub.called).to.be.false; + expect(err).equal(null); + expect(answer).to.be.true; + done(); + }); + }); + + it("deployment confirmation is skipped if project is ACDL ask states last deploy type is AC", (done) => { + // setup + getLastDeployTypeStub.returns(CONSTANTS.DEPLOYMENT_TYPE.ALEXA_CONVERSATIONS); + isACSkillStub.returns(true); + + // call + confirmDeploymentIfNeeded(TEST_PROFILE, (err, answer) => { + // verify + expect(inquirerStub.called).to.be.false; + expect(err).equal(null); + expect(answer).to.be.true; + done(); + }); + }); + + it("deployment confirmation is skipped if project is IM Skill and last deploy type is AC", (done) => { + // setup + getLastDeployTypeStub.returns(CONSTANTS.DEPLOYMENT_TYPE.ALEXA_CONVERSATIONS); + isACSkillStub.returns(false); + + // call + confirmDeploymentIfNeeded(TEST_PROFILE, (err, answer) => { + // verify + expect(inquirerStub.called).to.be.false; + expect(err).equal(null); + expect(answer).to.be.true; + done(); + }); + }); + + it("deployment confirmation is prompted when ac skill and ask states last deploy type is unset", (done) => { + // setup + getLastDeployTypeStub.returns(undefined); + isACSkillStub.returns(true); + + // call + confirmDeploymentIfNeeded(TEST_PROFILE, (err, answer) => { + // verify + expect(inquirerStub.called).to.be.true; + expect(err).equal(null); + expect(answer).to.be.true; + done(); + }); + }); + + it("deployment confirmation is prompted when ac skill and last deploy type is interaction model", (done) => { + // setup + getLastDeployTypeStub.returns(CONSTANTS.DEPLOYMENT_TYPE.INTERACTION_MODEL); + isACSkillStub.returns(true); + // call + confirmDeploymentIfNeeded(TEST_PROFILE, (err, answer) => { + // verify + expect(inquirerStub.called).to.be.true; + expect(err).equal(null); + expect(answer).to.be.true; + done(); + }); + }); +}); diff --git a/test/unit/commands/dialog/helper-test.js b/test/unit/commands/dialog/helper-test.js deleted file mode 100644 index 1bcf340f..00000000 --- a/test/unit/commands/dialog/helper-test.js +++ /dev/null @@ -1,263 +0,0 @@ -const { expect } = require('chai'); -const sinon = require('sinon'); - -const SmapiClient = require('@src/clients/smapi-client'); -const helper = require('@src/commands/dialog/helper'); -const DialogController = require('@src/controllers/dialog-controller'); - -describe('# Commands Dialog test - helper test', () => { - describe('# test validateDialogArgs', () => { - const TEST_SKILL_ID = 'skillId'; - const TEST_STAGE = 'development'; - const TEST_LOCALE = 'en-US'; - const TEST_MSG = 'test_msg'; - const dialogMode = new DialogController({ - smapiClient: new SmapiClient({ profile: 'default', doDebug: false }), - skillId: TEST_SKILL_ID, - stage: TEST_STAGE, - locale: TEST_LOCALE - }); - - let manifestStub; - let enablementStub; - - beforeEach(() => { - manifestStub = sinon.stub(dialogMode.smapiClient.skill.manifest, 'getManifest'); - enablementStub = sinon.stub(dialogMode.smapiClient.skill, 'getSkillEnablement'); - }); - - afterEach(() => { - sinon.restore(); - }); - - it('| Skill Manifest request error runs error callback', (done) => { - // setup - manifestStub.callsArgWith(2, TEST_MSG, null); - // call - helper.validateDialogArgs(dialogMode, (err, response) => { - // verify - expect(err).equal(TEST_MSG); - expect(response).equal(undefined); - done(); - }); - }); - - it('| Skill Manifest non 200 response runs error callback', (done) => { - // setup - const errorMsg = `SMAPI get-manifest request error: 400 - ${TEST_MSG}`; - manifestStub.callsArgWith(2, null, { - statusCode: 400, - body: { - message: TEST_MSG - } - }); - // call - helper.validateDialogArgs(dialogMode, (err, response) => { - // verify - expect(err).equal(errorMsg); - expect(response).equal(undefined); - done(); - }); - }); - - it('| Skill Manifest response body with no api JSON field runs error callback', (done) => { - // setup - const errorMsg = 'Ensure "manifest.apis" object exists in the skill manifest.'; - manifestStub.callsArgWith(2, null, { - statusCode: 200, - body: {} - }); - // call - helper.validateDialogArgs(dialogMode, (err, response) => { - // verify - expect(err).equal(errorMsg); - expect(response).equal(undefined); - done(); - }); - }); - - it('| Skill Manifest response body with api JSON field but no api keys runs error callback', (done) => { - // setup - const errorMsg = 'Dialog command only supports custom skill type.'; - manifestStub.callsArgWith(2, null, { - statusCode: 200, - body: { - manifest: { - apis: {} - } - } - }); - // call - helper.validateDialogArgs(dialogMode, (err, response) => { - // verify - expect(err).equal(errorMsg); - expect(response).equal(undefined); - done(); - }); - }); - - it('| Skill Manifest response body with api JSON field not custom runs error callback', (done) => { - // setup - const errorMsg = 'Dialog command only supports custom skill type, but current skill is a "smartHome" type.'; - manifestStub.callsArgWith(2, null, { - statusCode: 200, - body: { - manifest: { - apis: { - smartHome: {} - } - } - } - }); - // call - helper.validateDialogArgs(dialogMode, (err, response) => { - // verify - expect(err).equal(errorMsg); - expect(response).equal(undefined); - done(); - }); - }); - - it('| Skill Manifest response body with no locales JSON field runs error callback', (done) => { - // setup - const errorMsg = 'Ensure the "manifest.publishingInformation.locales" exists in the skill manifest before simulating your skill.'; - manifestStub.callsArgWith(2, null, { - statusCode: 200, - body: { - manifest: { - apis: { - custom: {} - } - }, - publishingInformation: {} - } - }); - // call - helper.validateDialogArgs(dialogMode, (err, response) => { - // verify - expect(err).equal(errorMsg); - expect(response).equal(undefined); - done(); - }); - }); - - it('| Skill Manifest response body does not contain locale passed into constructor runs error callback', (done) => { - // setup - const errorMsg = 'Locale en-US was not found for your skill. ' - + 'Ensure the locale you want to simulate exists in your publishingInformation.'; - manifestStub.callsArgWith(2, null, { - statusCode: 200, - body: { - manifest: { - apis: { - custom: {} - }, - publishingInformation: { - locales: { - } - } - } - } - }); - // call - helper.validateDialogArgs(dialogMode, (err, response) => { - // verify - expect(err).equal(errorMsg); - expect(response).equal(undefined); - done(); - }); - }); - - it('| Skill Manifest callback successful, Skill Enablement request error runs error callback', (done) => { - // setup - manifestStub.callsArgWith(2, null, { - statusCode: 200, - body: { - manifest: { - apis: { - custom: {} - }, - publishingInformation: { - locales: { - 'en-US': {} - } - } - } - } - }); - enablementStub.callsArgWith(2, TEST_MSG, null); - // call - helper.validateDialogArgs(dialogMode, (err, response) => { - // verify - expect(err).equal(TEST_MSG); - expect(response).equal(undefined); - done(); - }); - }); - - it('| Skill Manifest callback successful, Skill Enablement response of >= 300 runs error callback', (done) => { - // setup - const errorMsg = `SMAPI get-skill-enablement request error: 400 - ${TEST_MSG}`; - manifestStub.callsArgWith(2, null, { - statusCode: 200, - body: { - manifest: { - apis: { - custom: {} - }, - publishingInformation: { - locales: { - 'en-US': {} - } - } - } - } - }); - enablementStub.callsArgWith(2, null, { - statusCode: 400, - body: { - message: TEST_MSG - } - }); - // call - helper.validateDialogArgs(dialogMode, (err, response) => { - // verify - expect(err).equal(errorMsg); - expect(response).equal(undefined); - done(); - }); - }); - - it('| Skill Manifest callback successful, Skill Enablement successful', (done) => { - // setup - const TEST_RES = { - statusCode: 204, - body: { - message: TEST_MSG - } - }; - manifestStub.callsArgWith(2, null, { - statusCode: 200, - body: { - manifest: { - apis: { - custom: {} - }, - publishingInformation: { - locales: { - 'en-US': {} - } - } - } - } - }); - enablementStub.callsArgWith(2, null, TEST_RES); - // call - helper.validateDialogArgs(dialogMode, (err) => { - // verify - expect(err).equal(undefined); - done(); - }); - }); - }); -}); diff --git a/test/unit/commands/dialog/helper.spec.ts b/test/unit/commands/dialog/helper.spec.ts new file mode 100644 index 00000000..372620ed --- /dev/null +++ b/test/unit/commands/dialog/helper.spec.ts @@ -0,0 +1,239 @@ +import {expect} from "chai"; +import sinon from "sinon"; + +import * as helper from "../../../../lib/commands/dialog/helper"; +import {DialogController} from "../../../../lib/controllers/dialog-controller"; + +describe("# Commands Dialog test - helper test", () => { + describe("# test validateDialogArgs", () => { + const TEST_SKILL_ID = "skillId"; + const TEST_STAGE = "development"; + const TEST_LOCALE = "en-US"; + const TEST_MSG = "test_msg"; + let dialogMode: DialogController; + + let manifestStub: sinon.SinonStub; + let enablementStub: sinon.SinonStub; + + beforeEach(() => { + manifestStub = sinon.stub(); + enablementStub = sinon.stub(); + dialogMode = new DialogController({ + smapiClient: { + skill: { + manifest: { + getManifest: manifestStub, + } as any, + getSkillEnablement: enablementStub, + } as any, + } as any, + skillId: TEST_SKILL_ID, + stage: TEST_STAGE, + locale: TEST_LOCALE, + } as any); + }); + + afterEach(() => { + sinon.restore(); + }); + + it("| Skill Manifest request error runs error callback", async () => { + // setup + manifestStub.rejects(Error(TEST_MSG)); + // call + await expect(helper.validateDialogArgs(dialogMode)) + // verify + .eventually.rejectedWith(TEST_MSG); + }); + + it("| Skill Manifest non 200 response runs error callback", async () => { + // setup + const errorMsg = `SMAPI get-manifest request error: 400 - ${TEST_MSG}`; + manifestStub.resolves({ + statusCode: 400, + body: { + message: TEST_MSG, + }, + }); + // call + await expect(helper.validateDialogArgs(dialogMode)) + // verify + .rejectedWith(errorMsg); + }); + + it("| Skill Manifest response body with no api JSON field runs error callback", async () => { + // setup + const errorMsg = 'Ensure "manifest.apis" object exists in the skill manifest.'; + manifestStub.resolves({ + statusCode: 200, + body: {}, + }); + // call + await expect(helper.validateDialogArgs(dialogMode)) + // verify + .rejectedWith(errorMsg); + }); + + it("| Skill Manifest response body with api JSON field but no api keys runs error callback", async () => { + // setup + const errorMsg = "Dialog command only supports custom skill type."; + manifestStub.resolves({ + statusCode: 200, + body: { + manifest: { + apis: {}, + }, + }, + }); + // call + await expect(helper.validateDialogArgs(dialogMode)) + // verify + .rejectedWith(errorMsg); + }); + + it("| Skill Manifest response body with api JSON field not custom runs error callback", async () => { + // setup + const errorMsg = 'Dialog command only supports custom skill type, but current skill is a "smartHome" type.'; + manifestStub.resolves({ + statusCode: 200, + body: { + manifest: { + apis: { + smartHome: {}, + }, + }, + }, + }); + // call + await expect(helper.validateDialogArgs(dialogMode)) + // verify + .rejectedWith(errorMsg); + }); + + it("| Skill Manifest response body with no locales JSON field runs error callback", async () => { + // setup + const errorMsg = 'Ensure the "manifest.publishingInformation.locales" exists in the skill manifest before simulating your skill.'; + manifestStub.resolves({ + statusCode: 200, + body: { + manifest: { + apis: { + custom: {}, + }, + }, + publishingInformation: {}, + }, + }); + // call + await expect(helper.validateDialogArgs(dialogMode)) + // verify + .rejectedWith(errorMsg); + }); + + it("| Skill Manifest response body does not contain locale passed into constructor runs error callback", async () => { + // setup + const errorMsg = + "Locale en-US was not found for your skill. " + "Ensure the locale you want to simulate exists in your publishingInformation."; + manifestStub.resolves({ + statusCode: 200, + body: { + manifest: { + apis: { + custom: {}, + }, + publishingInformation: { + locales: {}, + }, + }, + }, + }); + // call + await expect(helper.validateDialogArgs(dialogMode)) + // verify + .rejectedWith(errorMsg); + }); + + it("| Skill Manifest callback successful, Skill Enablement request error runs error callback", async () => { + // setup + manifestStub.resolves({ + statusCode: 200, + body: { + manifest: { + apis: { + custom: {}, + }, + publishingInformation: { + locales: { + "en-US": {}, + }, + }, + }, + }, + }); + enablementStub.rejects(Error(TEST_MSG)); + // call + await expect(helper.validateDialogArgs(dialogMode)) + // verify + .eventually.rejectedWith(TEST_MSG); + }); + + it("| Skill Manifest callback successful, Skill Enablement response of >= 300 runs error callback", async () => { + // setup + const errorMsg = `SMAPI get-skill-enablement request error: 400 - ${TEST_MSG}`; + manifestStub.resolves({ + statusCode: 200, + body: { + manifest: { + apis: { + custom: {}, + }, + publishingInformation: { + locales: { + "en-US": {}, + }, + }, + }, + }, + }); + enablementStub.resolves({ + statusCode: 400, + body: { + message: TEST_MSG, + }, + }); + // call + await expect(helper.validateDialogArgs(dialogMode)) + // verify + .rejectedWith(errorMsg); + }); + + it("| Skill Manifest callback successful, Skill Enablement successful", async () => { + // setup + const TEST_RES = { + statusCode: 204, + body: { + message: TEST_MSG, + }, + }; + manifestStub.resolves({ + statusCode: 200, + body: { + manifest: { + apis: { + custom: {}, + }, + publishingInformation: { + locales: { + "en-US": {}, + }, + }, + }, + }, + }); + enablementStub.resolves(TEST_RES); + // call + // verify + expect(helper.validateDialogArgs(dialogMode)).eventually.fulfilled; + }); + }); +}); diff --git a/test/unit/commands/dialog/index-test.js b/test/unit/commands/dialog/index-test.js deleted file mode 100644 index 0e75e35a..00000000 --- a/test/unit/commands/dialog/index-test.js +++ /dev/null @@ -1,414 +0,0 @@ -const { expect } = require('chai'); -const sinon = require('sinon'); -const path = require('path'); - -const AuthorizationController = require('@src/controllers/authorization-controller'); -const DialogCommand = require('@src/commands/dialog'); -const DialogReplayFile = require('@src/model/dialog-replay-file'); -const helper = require('@src/commands/dialog/helper'); -const httpClient = require('@src/clients/http-client'); -const InteractiveMode = require('@src/commands/dialog/interactive-mode'); -const optionModel = require('@src/commands/option-model'); -const ResourcesConfig = require('@src/model/resources-config'); -const jsonView = require('@src/view/json-view'); -const CONSTANTS = require('@src/utils/constants'); -const profileHelper = require('@src/utils/profile-helper'); -const stringUtils = require('@src/utils/string-utils'); -const Messenger = require('@src/view/messenger'); -const SpinnerView = require('@src/view/spinner-view'); - -describe('Commands Dialog test - command class test', () => { - const TEST_ERROR = 'error'; - const DIALOG_FIXTURE_PATH = path.join(process.cwd(), 'test', 'unit', 'fixture', 'model', 'dialog'); - const RESOURCE_CONFIG_FIXTURE_PATH = path.join(process.cwd(), 'test', 'unit', 'fixture', 'model', 'regular-proj'); - const DIALOG_REPLAY_FILE_JSON_PATH = path.join(DIALOG_FIXTURE_PATH, 'dialog-replay-file.json'); - const INVALID_DIALOG_REPLAY_FILE_JSON_PATH = path.join(DIALOG_FIXTURE_PATH, 'invalid-dialog-replay-file.json'); - const INVALID_RESOURCES_CONFIG_JSON_PATH = path.join(RESOURCE_CONFIG_FIXTURE_PATH, 'random-json-config.json'); - const VALID_RESOURCES_CONFIG_JSON_PATH = path.join(RESOURCE_CONFIG_FIXTURE_PATH, 'ask-resources.json'); - const VALID_MANIFEST_JSON_PATH = path.join(process.cwd(), 'test', 'unit', 'fixture', 'model', 'manifest.json'); - const TEST_PROFILE = 'default'; - const TEST_CMD = { - profile: TEST_PROFILE - }; - - let errorStub; - let infoStub; - beforeEach(() => { - errorStub = sinon.stub(); - infoStub = sinon.stub(); - sinon.stub(Messenger, 'getInstance').returns({ - error: errorStub, - info: infoStub - }); - sinon.stub(AuthorizationController.prototype, 'tokenRefreshAndRead').yields(); - }); - - afterEach(() => { - sinon.restore(); - }); - - it('| validate command information is set correctly', () => { - const instance = new DialogCommand(optionModel); - expect(instance.name()).eq('dialog'); - expect(instance.description()).eq('simulate your skill via an interactive dialog with Alexa'); - expect(instance.requiredOptions()).deep.eq([]); - expect(instance.optionalOptions()).deep.eq(['skill-id', 'locale', 'stage', 'replay', 'save-skill-io', 'simulation-type', 'profile', 'debug']); - }); - - describe('# validate command handle', () => { - let instance; - let spinnerStartStub; - let spinnerTerminateStub; - - beforeEach(() => { - spinnerStartStub = sinon.stub(SpinnerView.prototype, 'start'); - spinnerTerminateStub = sinon.stub(SpinnerView.prototype, 'terminate'); - instance = new DialogCommand(optionModel); - }); - - afterEach(() => { - sinon.restore(); - }); - - it('| error while creating dialogMode', (done) => { - // setup - sinon.stub(DialogCommand.prototype, '_getDialogConfig').yields(new Error(TEST_ERROR)); - - // call - instance.handle(TEST_CMD, (err) => { - // verify - expect(errorStub.args[0][0].message).eq(TEST_ERROR); - expect(err.message).eq(TEST_ERROR); - done(); - }); - }); - - it('| error while validating dialog arguments', (done) => { - // setup - sinon.stub(DialogCommand.prototype, '_getDialogConfig').yields(); - sinon.stub(DialogCommand.prototype, '_dialogModeFactory'); - sinon.stub(helper, 'validateDialogArgs').callsArgWith(1, TEST_ERROR); - // call - instance.handle(TEST_CMD, (err) => { - // verify - expect(err).eq(TEST_ERROR); - expect(spinnerStartStub.calledOnce).eq(true); - expect(spinnerStartStub.args[0][0]).eq('Checking if skill is ready to simulate...'); - expect(spinnerTerminateStub.calledOnce).eq(true); - expect(spinnerTerminateStub.args[0][0]).eq(SpinnerView.TERMINATE_STYLE.FAIL); - expect(spinnerTerminateStub.args[0][1]).eq('Failed to validate command options'); - expect(errorStub.args[0][0]).eq(TEST_ERROR); - done(); - }); - }); - - it('| dialogMode returns error', (done) => { - // setup - sinon.stub(DialogCommand.prototype, '_getDialogConfig').yields(null, {}); - sinon.stub(InteractiveMode.prototype, 'start').callsArgWith(0, TEST_ERROR); - sinon.stub(helper, 'validateDialogArgs').callsArgWith(1, null); - // call - instance.handle(TEST_CMD, (err) => { - // verify - expect(err).eq(TEST_ERROR); - expect(spinnerStartStub.calledOnce).eq(true); - expect(spinnerStartStub.args[0][0]).eq('Checking if skill is ready to simulate...'); - expect(spinnerTerminateStub.calledOnce).eq(true); - expect(errorStub.args[0][0]).eq(TEST_ERROR); - done(); - }); - }); - - it('| dialog command successfully completes execution', (done) => { - // setup - sinon.stub(DialogCommand.prototype, '_getDialogConfig').yields(null, {}); - sinon.stub(InteractiveMode.prototype, 'start').callsArgWith(0, null); - sinon.stub(helper, 'validateDialogArgs').callsArgWith(1, null); - // call - instance.handle(TEST_CMD, (err) => { - // verify - expect(err).eq(undefined); - expect(spinnerStartStub.calledOnce).eq(true); - expect(spinnerStartStub.args[0][0]).eq('Checking if skill is ready to simulate...'); - expect(spinnerTerminateStub.calledOnce).eq(true); - done(); - }); - }); - }); - - describe('# test _getDialogConfig', () => { - let instance; - let manifest; - - beforeEach(() => { - instance = new DialogCommand(optionModel); - manifest = { publishingInformation: { locales: { us: {} } } }; - }); - - describe('# test with replay option', () => { - it('| empty skillId throws error', (done) => { - // setup - const TEST_CMD_WITH_VALUES = { - stage: 'development', - replay: INVALID_DIALOG_REPLAY_FILE_JSON_PATH - }; - sinon.stub(profileHelper, 'runtimeProfile').returns(TEST_PROFILE); - sinon.stub(httpClient, 'request').yields(null, { statusCode: 200, body: { manifest } }); - // call - instance.handle(TEST_CMD_WITH_VALUES, (err) => { - // verify - expect(err.message).eq('Replay file must contain skillId'); - done(); - }); - }); - - it('| empty locale throws error', (done) => { - // setup - const TEST_CMD_WITH_VALUES = { - stage: '', - replay: INVALID_DIALOG_REPLAY_FILE_JSON_PATH - }; - sinon.stub(profileHelper, 'runtimeProfile').returns(TEST_PROFILE); - sinon.stub(httpClient, 'request').yields(null, { statusCode: 200, body: { manifest } }); - const stringUtilsStub = sinon.stub(stringUtils, 'isNonBlankString'); - stringUtilsStub.onCall(0).returns('skillId'); - // call - instance.handle(TEST_CMD_WITH_VALUES, (err) => { - // verify - expect(err.message).eq('Replay file must contain locale'); - done(); - }); - }); - - it('| invalid user inputs throws error', (done) => { - // setup - const TEST_CMD_WITH_VALUES = { - stage: '', - replay: INVALID_DIALOG_REPLAY_FILE_JSON_PATH - }; - sinon.stub(profileHelper, 'runtimeProfile').returns(TEST_PROFILE); - sinon.stub(httpClient, 'request').yields(null, { statusCode: 200, body: { manifest } }); - const stringUtilsStub = sinon.stub(stringUtils, 'isNonBlankString'); - stringUtilsStub.onCall(0).returns('skillId'); - stringUtilsStub.onCall(1).returns('locale'); - // call - instance.handle(TEST_CMD_WITH_VALUES, (err) => { - // verify - expect(err.message).eq("Replay file's userInput cannot contain empty string."); - done(); - }); - }); - - it('| returns valid config', (done) => { - // setup - const TEST_CMD_WITH_VALUES = { - stage: '', - replay: DIALOG_REPLAY_FILE_JSON_PATH, - simulationType: 'NFI_ISOLATED_SIMULATION' - }; - sinon.stub(profileHelper, 'runtimeProfile').returns(TEST_PROFILE); - sinon.stub(httpClient, 'request').yields(null, { statusCode: 200, body: { manifest } }); - // call - instance._getDialogConfig(TEST_CMD_WITH_VALUES, (err, config) => { - // verify - expect(config.debug).equal(false); - expect(config.locale).equal('en-US'); - expect(config.profile).equal('default'); - expect(config.replay).equal(DIALOG_REPLAY_FILE_JSON_PATH); - expect(config.skillId).equal('amzn1.ask.skill.1234567890'); - expect(config.stage).equal('development'); - expect(config.simulationType).equal('NFI_ISOLATED_SIMULATION'); - expect(config.userInputs).deep.equal(['hello', 'world']); - done(); - }); - }); - - it('| returns valid config with default simulation type', (done) => { - // setup - const TEST_CMD_WITH_VALUES = { - stage: '', - replay: DIALOG_REPLAY_FILE_JSON_PATH, - }; - sinon.stub(profileHelper, 'runtimeProfile').returns(TEST_PROFILE); - sinon.stub(httpClient, 'request').yields(null, { statusCode: 200, body: { manifest } }); - // call - instance._getDialogConfig(TEST_CMD_WITH_VALUES, (err, config) => { - // verify - expect(config.debug).equal(false); - expect(config.locale).equal('en-US'); - expect(config.profile).equal('default'); - expect(config.replay).equal(DIALOG_REPLAY_FILE_JSON_PATH); - expect(config.skillId).equal('amzn1.ask.skill.1234567890'); - expect(config.stage).equal('development'); - expect(config.simulationType).equal(undefined); - expect(config.userInputs).deep.equal(['hello', 'world']); - done() - }); - }); - - it('| returns error when initialization of DialogReplayFile fails', (done) => { - // setup - const TEST_CMD_WITH_VALUES = { - stage: '', - replay: DIALOG_REPLAY_FILE_JSON_PATH - }; - const error = 'error'; - sinon.stub(profileHelper, 'runtimeProfile').returns(TEST_PROFILE); - sinon.stub(DialogReplayFile.prototype, 'readFileContent').throws(new Error(error)); - // call - instance._getDialogConfig(TEST_CMD_WITH_VALUES, (err) => { - // verify - expect(err.message).eq(error); - done(); - }); - }); - - it('| returns return error when smapi get manifest call fails', (done) => { - // setup - const TEST_CMD_WITH_VALUES = { - stage: '', - replay: DIALOG_REPLAY_FILE_JSON_PATH - }; - const smapiError = 'error'; - sinon.stub(profileHelper, 'runtimeProfile').returns(TEST_PROFILE); - sinon.stub(httpClient, 'request').yields(smapiError); - // call - instance._getDialogConfig(TEST_CMD_WITH_VALUES, (err) => { - // verify - expect(err).eq(smapiError); - done(); - }); - }); - - it('| returns return error when smapi get manifest call returns failure http status code', (done) => { - // setup - const TEST_CMD_WITH_VALUES = { - stage: '', - replay: DIALOG_REPLAY_FILE_JSON_PATH - }; - const smapiError = 'error'; - sinon.stub(profileHelper, 'runtimeProfile').returns(TEST_PROFILE); - sinon.stub(httpClient, 'request').yields(null, { statusCode: 400, body: { message: smapiError } }); - // call - instance._getDialogConfig(TEST_CMD_WITH_VALUES, (err) => { - // verify - expect(err).eq(jsonView.toString({ message: smapiError })); - done(); - }); - }); - }); - - describe('# test with default (interactive) option', () => { - - it('| no resources config file found', (done) => { - // setup - const TEST_CMD_WITH_VALUES = {}; - sinon.stub(profileHelper, 'runtimeProfile').returns(TEST_PROFILE); - sinon.stub(path, 'join').returns(INVALID_RESOURCES_CONFIG_JSON_PATH); - sinon.stub(ResourcesConfig.prototype, 'getSkillId').throws(new Error()); - // call - instance.handle(TEST_CMD_WITH_VALUES, (err) => { - // verify - expect(err.message).equal('Failed to read project resource file. Please run the command within a ask-cli project.'); - done(); - }); - }); - - it('| unable to fetch skillId from resources config file', (done) => { - // setup - const TEST_CMD_WITH_VALUES = {}; - sinon.stub(profileHelper, 'runtimeProfile').returns(TEST_PROFILE); - sinon.stub(path, 'join').returns(INVALID_RESOURCES_CONFIG_JSON_PATH); - // call - instance.handle(TEST_CMD_WITH_VALUES, (err) => { - // verify - expect(err.message).equal(`Failed to obtain skill-id from project resource file ${CONSTANTS.FILE_PATH.ASK_RESOURCES_JSON_CONFIG}`); - done(); - }); - }); - - it('| check valid values are returned in interactive mode', (done) => { - // setup - const TEST_CMD_WITH_VALUES = {}; - sinon.stub(profileHelper, 'runtimeProfile').returns(TEST_PROFILE); - sinon.stub(httpClient, 'request').yields(null, { statusCode: 200, body: { manifest } }); - const pathJoinStub = sinon.stub(path, 'join'); - pathJoinStub.withArgs( - process.cwd(), CONSTANTS.FILE_PATH.ASK_RESOURCES_JSON_CONFIG - ).returns(VALID_RESOURCES_CONFIG_JSON_PATH); - pathJoinStub.withArgs( - './skillPackage', CONSTANTS.FILE_PATH.SKILL_PACKAGE.MANIFEST - ).returns(VALID_MANIFEST_JSON_PATH); - path.join.callThrough(); - process.env.ASK_DEFAULT_DEVICE_LOCALE = 'en-US'; - // call - instance._getDialogConfig(TEST_CMD_WITH_VALUES, (err, config) => { - // verify - expect(config.debug).equal(false); - expect(config.locale).equal('en-US'); - expect(config.profile).equal('default'); - expect(config.replay).equal(undefined); - expect(config.skillId).equal('amzn1.ask.skill.1234567890'); - expect(config.stage).equal('development'); - expect(config.userInputs).equal(undefined); - done(); - }); - }); - - it('| check locale defaults to first value from manifest', (done) => { - // setup - const [expectedLocale] = Object.keys(manifest.publishingInformation.locales); - const TEST_CMD_WITH_VALUES = {}; - sinon.stub(profileHelper, 'runtimeProfile').returns(TEST_PROFILE); - sinon.stub(httpClient, 'request').yields(null, { statusCode: 200, body: { manifest } }); - const pathJoinStub = sinon.stub(path, 'join'); - pathJoinStub.withArgs( - process.cwd(), CONSTANTS.FILE_PATH.ASK_RESOURCES_JSON_CONFIG - ).returns(VALID_RESOURCES_CONFIG_JSON_PATH); - path.join.callThrough(); - - // call - instance._getDialogConfig(TEST_CMD_WITH_VALUES, (err, config) => { - // verify - expect(config.debug).equal(false); - expect(infoStub.args[0][0]).eq(`Defaulting locale to the first value from the skill manifest: ${expectedLocale}`); - expect(config.locale).equal(expectedLocale); - expect(config.profile).equal('default'); - expect(config.replay).equal(undefined); - expect(config.skillId).equal('amzn1.ask.skill.1234567890'); - expect(config.stage).equal('development'); - expect(config.userInputs).equal(undefined); - done(); - }); - }); - - afterEach(() => { - sinon.restore(); - delete process.env.ASK_DEFAULT_DEVICE_LOCALE; - }); - }); - - afterEach(() => { - sinon.restore(); - }); - }); - - describe('# test _validateUserInputs', () => { - let instance; - - beforeEach(() => { - instance = new DialogCommand(optionModel); - }); - - it('| all valid inputs', () => { - // setup - const userInputs = [' open hello world ', 'help']; - - // call - const validatedInputs = instance._validateUserInputs(userInputs); - - // verify - expect(validatedInputs).deep.equal(['open hello world', 'help']); - }); - }); -}); diff --git a/test/unit/commands/dialog/index.spec.ts b/test/unit/commands/dialog/index.spec.ts new file mode 100644 index 00000000..b38091e5 --- /dev/null +++ b/test/unit/commands/dialog/index.spec.ts @@ -0,0 +1,371 @@ +import {expect} from "chai"; +import sinon from "sinon"; +import path from "path"; + +import AuthorizationController from "../../../../lib/controllers/authorization-controller"; +import {DialogCommand} from "../../../../lib/commands/dialog"; +import DialogReplayFile from "../../../../lib/model/dialog-replay-file"; +import * as helper from "../../../../lib/commands/dialog/helper"; +import httpClient from "../../../../lib/clients/http-client"; +import {InteractiveMode} from "../../../../lib/commands/dialog/interactive-mode"; +import ResourcesConfig from "../../../../lib/model/resources-config"; +import jsonView from "../../../../lib/view/json-view"; +import CONSTANTS from "../../../../lib/utils/constants"; +import profileHelper from "../../../../lib/utils/profile-helper"; +import stringUtils from "../../../../lib/utils/string-utils"; +import Messenger from "../../../../lib/view/messenger"; +import SpinnerView from "../../../../lib/view/spinner-view"; +import * as optionModel from "../../../../lib/commands/option-model.json"; +import {OptionModel} from "../../../../lib/commands/option-validator"; +import {SmapiClientLateBound} from "../../../../lib/clients/smapi-client"; +import {v1} from "ask-smapi-model"; + +describe("Commands Dialog test - command class test", () => { + const TEST_ERROR = "error"; + const DIALOG_FIXTURE_PATH = path.join(process.cwd(), "test", "unit", "fixture", "model", "dialog"); + const RESOURCE_CONFIG_FIXTURE_PATH = path.join(process.cwd(), "test", "unit", "fixture", "model", "regular-proj"); + const DIALOG_REPLAY_FILE_JSON_PATH = path.join(DIALOG_FIXTURE_PATH, "dialog-replay-file.json"); + const INVALID_DIALOG_REPLAY_FILE_JSON_PATH = path.join(DIALOG_FIXTURE_PATH, "invalid-dialog-replay-file.json"); + const INVALID_RESOURCES_CONFIG_JSON_PATH = path.join(RESOURCE_CONFIG_FIXTURE_PATH, "random-json-config.json"); + const VALID_RESOURCES_CONFIG_JSON_PATH = path.join(RESOURCE_CONFIG_FIXTURE_PATH, "ask-resources.json"); + const VALID_MANIFEST_JSON_PATH = path.join(process.cwd(), "test", "unit", "fixture", "model", "manifest.json"); + const TEST_PROFILE = "default"; + const TEST_CMD = { + profile: TEST_PROFILE, + }; + + let errorStub: sinon.SinonStub; + let infoStub: sinon.SinonStub; + beforeEach(() => { + errorStub = sinon.stub(); + infoStub = sinon.stub(); + sinon.stub(Messenger, "getInstance").returns({ + error: errorStub, + info: infoStub, + }); + sinon.stub(AuthorizationController.prototype, "tokenRefreshAndRead").callsArgWith(1, null, "accesstoken"); + }); + + afterEach(() => { + sinon.restore(); + }); + + it("| validate command information is set correctly", () => { + const instance = new DialogCommand(new SmapiClientLateBound(), optionModel as OptionModel); + expect(instance.name()).eq("dialog"); + expect(instance.description()).eq("simulate your skill via an interactive dialog with Alexa"); + expect(instance.requiredOptions()).deep.eq([]); + expect(instance.optionalOptions()).deep.eq([ + "skill-id", + "locale", + "stage", + "replay", + "save-skill-io", + "profile", + "debug", + ]); + }); + + describe("# validate command handle", () => { + let instance: DialogCommand; + let spinnerStartStub: sinon.SinonStub; + let spinnerTerminateStub: sinon.SinonStub; + + beforeEach(() => { + spinnerStartStub = sinon.stub(SpinnerView.prototype, "start"); + spinnerTerminateStub = sinon.stub(SpinnerView.prototype, "terminate"); + instance = new DialogCommand(new SmapiClientLateBound(), optionModel as OptionModel); + }); + + afterEach(() => { + sinon.restore(); + }); + + it("| error while creating dialogMode", async () => { + // setup + sinon.stub(DialogCommand.prototype, "_getDialogConfig").rejects(new Error(TEST_ERROR)); + + // call + await expect(instance.handle(TEST_CMD)).eventually.rejected.property("message", TEST_ERROR); + + // verify + expect(errorStub).calledOnceWith(sinon.match({message: TEST_ERROR})); + }); + + it("| error while validating dialog arguments", async () => { + // setup + sinon.stub(DialogCommand.prototype, "_getDialogConfig").resolves(); + sinon.stub(DialogCommand.prototype, "_dialogModeFactory"); + sinon.stub(helper, "validateDialogArgs").rejects(Error(TEST_ERROR)); + // call + await expect(instance.handle(TEST_CMD)).eventually.rejected.property("message", TEST_ERROR); + + // verify + expect(spinnerStartStub).calledOnceWith("Checking if skill is ready to simulate..."); + expect(spinnerTerminateStub).calledOnceWith(SpinnerView.TERMINATE_STYLE.FAIL, "Failed to validate command options"); + expect(errorStub).calledOnceWith(sinon.match({message: TEST_ERROR})); + }); + + it("| dialogMode returns error", async () => { + // setup + sinon.stub(DialogCommand.prototype, "_getDialogConfig").resolves({} as any); + sinon.stub(InteractiveMode.prototype, "start").rejects(Error(TEST_ERROR)); + sinon.stub(helper, "validateDialogArgs").resolves(); + // call + await expect(instance.handle(TEST_CMD)).eventually.rejected.property("message", TEST_ERROR); + + // verify + expect(spinnerStartStub).calledOnceWith("Checking if skill is ready to simulate..."); + expect(spinnerTerminateStub).calledOnce; + expect(errorStub).calledOnceWith(sinon.match({message: TEST_ERROR})); + }); + + it("| dialog command successfully completes execution", async () => { + // setup + sinon.stub(DialogCommand.prototype, "_getDialogConfig").resolves({} as any); + sinon.stub(InteractiveMode.prototype, "start").resolves(); + sinon.stub(helper, "validateDialogArgs").resolves(); + // call + await instance.handle(TEST_CMD); + + // verify + expect(spinnerStartStub).calledOnceWith("Checking if skill is ready to simulate..."); + expect(spinnerTerminateStub).calledOnce; + }); + }); + + describe("# test _getDialogConfig", () => { + let instance: DialogCommand; + let manifest: v1.skill.Manifest.SkillManifest; + + beforeEach(() => { + instance = new DialogCommand(new SmapiClientLateBound(), optionModel as OptionModel); + manifest = {publishingInformation: {locales: {us: { name: 'test'}}}}; + }); + + describe("# test with replay option", () => { + it("| empty skillId throws error", async () => { + // setup + const TEST_CMD_WITH_VALUES = { + stage: "development", + replay: INVALID_DIALOG_REPLAY_FILE_JSON_PATH, + }; + sinon.stub(profileHelper, "runtimeProfile").returns(TEST_PROFILE); + sinon.stub(httpClient, "request").yields(null, {statusCode: 200, body: {manifest}}); + // call + await expect(instance._getDialogConfig(TEST_CMD_WITH_VALUES)).rejectedWith("Replay file must contain skillId"); + }); + + it("| dialog command uses skillId passed in as argument", async () => { + // setup + const TEST_CMD_WITH_VALUES = { + profile: TEST_PROFILE, + skillId: "foo", + }; + const validateDialogArgsStub = sinon.stub(helper, "validateDialogArgs").resolves(); + sinon.stub(profileHelper, "runtimeProfile").returns(TEST_PROFILE); + sinon.stub(InteractiveMode.prototype, "start").resolves(); + sinon.stub(httpClient, "request").yields(null, {statusCode: 200, body: {manifest}}); + // call + await instance.handle(TEST_CMD_WITH_VALUES); + expect(validateDialogArgsStub).calledOnceWith(sinon.match({ + profile: TEST_PROFILE, + skillId: "foo", + })); + }); + + it("| empty locale throws error", async () => { + // setup + const TEST_CMD_WITH_VALUES = { + stage: "", + replay: INVALID_DIALOG_REPLAY_FILE_JSON_PATH, + }; + sinon.stub(profileHelper, "runtimeProfile").returns(TEST_PROFILE); + sinon.stub(httpClient, "request").yields(null, {statusCode: 200, body: {manifest}}); + const stringUtilsStub = sinon.stub(stringUtils, "isNonBlankString"); + stringUtilsStub.onCall(0).returns(true); + stringUtilsStub.onCall(1).returns(false); + // call + await expect(instance._getDialogConfig(TEST_CMD_WITH_VALUES)).rejectedWith("Replay file must contain locale"); + }); + + it("| invalid user inputs throws error", async () => { + // setup + const TEST_CMD_WITH_VALUES = { + stage: "", + replay: INVALID_DIALOG_REPLAY_FILE_JSON_PATH, + }; + sinon.stub(profileHelper, "runtimeProfile").returns(TEST_PROFILE); + sinon.stub(httpClient, "request").yields(null, {statusCode: 200, body: {manifest}}); + const stringUtilsStub = sinon.stub(stringUtils, "isNonBlankString"); + stringUtilsStub.onCall(0).returns(true); + stringUtilsStub.onCall(1).returns(true); + // call + await expect(instance._getDialogConfig(TEST_CMD_WITH_VALUES)).rejectedWith("Replay file's userInput cannot contain empty string."); + }); + + it("| returns valid config", async () => { + // setup + const TEST_CMD_WITH_VALUES = { + stage: "", + replay: DIALOG_REPLAY_FILE_JSON_PATH, + }; + sinon.stub(profileHelper, "runtimeProfile").returns(TEST_PROFILE); + sinon.stub(httpClient, "request").yields(null, {statusCode: 200, body: {manifest}}); + // call + await expect(instance._getDialogConfig(TEST_CMD_WITH_VALUES)).eventually.fulfilled.deep.include({ + debug: undefined, + locale: "en-US", + profile: "default", + replay: DIALOG_REPLAY_FILE_JSON_PATH, + skillId: "amzn1.ask.skill.1234567890", + stage: "development", + userInputs: ["hello", "world"], + }); + }); + + it("| returns error when initialization of DialogReplayFile fails", async () => { + // setup + const TEST_CMD_WITH_VALUES = { + stage: "", + replay: DIALOG_REPLAY_FILE_JSON_PATH, + }; + const error = "error"; + sinon.stub(profileHelper, "runtimeProfile").returns(TEST_PROFILE); + sinon.stub(DialogReplayFile.prototype, "readFileContent").throws(new Error(error)); + // call + await expect(instance._getDialogConfig(TEST_CMD_WITH_VALUES)).rejectedWith(error); + }); + + it("| returns return error when smapi get manifest call fails", async () => { + // setup + const TEST_CMD_WITH_VALUES = { + stage: "", + replay: DIALOG_REPLAY_FILE_JSON_PATH, + }; + const smapiError = "error"; + sinon.stub(profileHelper, "runtimeProfile").returns(TEST_PROFILE); + sinon.stub(httpClient, "request").yields(smapiError); + // call + await expect(instance._getDialogConfig(TEST_CMD_WITH_VALUES)).rejectedWith(smapiError); + }); + + it("| returns return error when smapi get manifest call returns failure http status code", async () => { + // setup + const TEST_CMD_WITH_VALUES = { + stage: "", + replay: DIALOG_REPLAY_FILE_JSON_PATH, + }; + const smapiError = "error"; + sinon.stub(profileHelper, "runtimeProfile").returns(TEST_PROFILE); + sinon.stub(httpClient, "request").yields(null, {statusCode: 400, body: {message: smapiError}}); + // call + await expect(instance._getDialogConfig(TEST_CMD_WITH_VALUES)).rejectedWith(jsonView.toString({message: smapiError})); + }); + }); + + describe("# test with default (interactive) option", () => { + it("| no resources config file found", async () => { + // setup + const TEST_CMD_WITH_VALUES = {}; + sinon.stub(profileHelper, "runtimeProfile").returns(TEST_PROFILE); + sinon.stub(path, "join").returns(INVALID_RESOURCES_CONFIG_JSON_PATH); + sinon.stub(ResourcesConfig.prototype, "getSkillId").throws(new Error()); + // call + await expect(instance._getDialogConfig(TEST_CMD_WITH_VALUES)).rejectedWith( + "Failed to read project resource file. Please run the command within a ask-cli project.", + ); + }); + + it("| unable to fetch skillId from resources config file", async () => { + // setup + const TEST_CMD_WITH_VALUES = {}; + sinon.stub(profileHelper, "runtimeProfile").returns(TEST_PROFILE); + sinon.stub(path, "join").returns(INVALID_RESOURCES_CONFIG_JSON_PATH); + // call + const expectedFilePath = path.join( + process.cwd(), + CONSTANTS.FILE_PATH.HIDDEN_ASK_FOLDER, + CONSTANTS.FILE_PATH.ASK_STATES_JSON_CONFIG, + ); + await expect(instance._getDialogConfig(TEST_CMD_WITH_VALUES)).rejectedWith( + `Failed to obtain skill-id from project file ${expectedFilePath}`, + ); + }); + + it("| check valid values are returned in interactive mode", async () => { + // setup + const TEST_CMD_WITH_VALUES = {}; + sinon.stub(profileHelper, "runtimeProfile").returns(TEST_PROFILE); + sinon.stub(httpClient, "request").yields(null, {statusCode: 200, body: {manifest}}); + const pathJoinStub = sinon.stub(path, "join"); + pathJoinStub.withArgs(process.cwd(), CONSTANTS.FILE_PATH.ASK_RESOURCES_JSON_CONFIG).returns(VALID_RESOURCES_CONFIG_JSON_PATH); + pathJoinStub.withArgs("./skillPackage", CONSTANTS.FILE_PATH.SKILL_PACKAGE.MANIFEST).returns(VALID_MANIFEST_JSON_PATH); + pathJoinStub.callThrough(); + process.env.ASK_DEFAULT_DEVICE_LOCALE = "en-US"; + // call + await expect(instance._getDialogConfig(TEST_CMD_WITH_VALUES)).eventually.fulfilled.include({ + debug: undefined, + locale: "en-US", + profile: "default", + replay: undefined, + skillId: "amzn1.ask.skill.1234567890", + stage: "development", + userInputs: undefined, + }); + }); + + it("| check locale defaults to first value from manifest", async () => { + // setup + const [expectedLocale] = Object.keys(manifest.publishingInformation?.locales || {}); + const TEST_CMD_WITH_VALUES = {}; + sinon.stub(profileHelper, "runtimeProfile").returns(TEST_PROFILE); + sinon.stub(httpClient, "request").yields(null, {statusCode: 200, body: {manifest}}); + const pathJoinStub = sinon.stub(path, "join"); + pathJoinStub.withArgs(process.cwd(), CONSTANTS.FILE_PATH.ASK_RESOURCES_JSON_CONFIG).returns(VALID_RESOURCES_CONFIG_JSON_PATH); + pathJoinStub.callThrough(); + + // call + await expect(instance._getDialogConfig(TEST_CMD_WITH_VALUES)).eventually.fulfilled.include({ + debug: undefined, + locale: expectedLocale, + profile: "default", + replay: undefined, + skillId: "amzn1.ask.skill.1234567890", + stage: "development", + userInputs: undefined, + }); + + expect(infoStub).calledOnceWith(`Defaulting locale to the first value from the skill manifest: ${expectedLocale}`); + }); + + afterEach(() => { + sinon.restore(); + delete process.env.ASK_DEFAULT_DEVICE_LOCALE; + }); + }); + + afterEach(() => { + sinon.restore(); + }); + }); + + describe("# test _validateUserInputs", () => { + let instance: DialogCommand; + + beforeEach(() => { + instance = new DialogCommand(new SmapiClientLateBound(), optionModel as OptionModel); + }); + + it("| all valid inputs", () => { + // setup + const userInputs = [" open hello world ", "help"]; + + // call + const validatedInputs = instance._validateUserInputs(userInputs); + + // verify + expect(validatedInputs).deep.equal(["open hello world", "help"]); + }); + }); +}); diff --git a/test/unit/commands/dialog/interactive-mode-test.js b/test/unit/commands/dialog/interactive-mode-test.js deleted file mode 100644 index eea2274c..00000000 --- a/test/unit/commands/dialog/interactive-mode-test.js +++ /dev/null @@ -1,41 +0,0 @@ -const { expect } = require('chai'); -const sinon = require('sinon'); - -const InteractiveMode = require('@src/commands/dialog/interactive-mode'); -const DialogController = require('@src/controllers/dialog-controller'); -const DialogReplView = require('@src/view/dialog-repl-view'); - -describe('# Command: Dialog - Interactive Mode test ', () => { - const TEST_ERROR = 'error'; - const dialogReplViewPrototype = Object.getPrototypeOf(DialogReplView); - - afterEach(() => { - Object.setPrototypeOf(DialogReplView, dialogReplViewPrototype); - sinon.restore(); - }); - - it('| test interactive mode start, dialog repl view creation throws error', () => { - // setup - const dialogReplViewStub = sinon.stub().throws(new Error(TEST_ERROR)); - Object.setPrototypeOf(DialogReplView, dialogReplViewStub); - const interactiveMode = new InteractiveMode({}); - // call - interactiveMode.start((error) => { - // verify - expect(error.message).equal(TEST_ERROR); - }); - }); - - it('| test interactive mode start, setupSpecialCommands throws error', () => { - // setup - const dialogReplViewStub = sinon.stub(); - Object.setPrototypeOf(DialogReplView, dialogReplViewStub); - sinon.stub(DialogController.prototype, 'setupSpecialCommands').callsArgWith(1, TEST_ERROR); - const interactiveMode = new InteractiveMode({}); - // call - interactiveMode.start((error) => { - // verify - expect(error).equal(TEST_ERROR); - }); - }); -}); diff --git a/test/unit/commands/dialog/interactive-mode.spec.ts b/test/unit/commands/dialog/interactive-mode.spec.ts new file mode 100644 index 00000000..3a76f3b0 --- /dev/null +++ b/test/unit/commands/dialog/interactive-mode.spec.ts @@ -0,0 +1,35 @@ +import {expect} from "chai"; +import sinon from "sinon"; + +import {InteractiveMode} from "../../../../lib/commands/dialog/interactive-mode"; +import {DialogController} from "../../../../lib/controllers/dialog-controller"; +import {DialogReplView} from "../../../../lib/view/dialog-repl-view"; + +describe("# Command: Dialog - Interactive Mode test ", () => { + const TEST_ERROR = "error"; + const dialogReplViewPrototype = Object.getPrototypeOf(DialogReplView); + + afterEach(() => { + Object.setPrototypeOf(DialogReplView, dialogReplViewPrototype); + sinon.restore(); + }); + + it("| test interactive mode start, dialog repl view creation throws error", async () => { + // setup + const dialogReplViewStub = sinon.stub().throws(new Error(TEST_ERROR)); + Object.setPrototypeOf(DialogReplView, dialogReplViewStub); + const interactiveMode = new InteractiveMode({} as any); + // call + await expect(interactiveMode.start()).rejectedWith(TEST_ERROR); + }); + + it("| test interactive mode start, setupSpecialCommands throws error", async () => { + // setup + const dialogReplViewStub = sinon.stub(); + Object.setPrototypeOf(DialogReplView, dialogReplViewStub); + sinon.stub(DialogController.prototype, "setupSpecialCommands").rejects(Error(TEST_ERROR)); + const interactiveMode = new InteractiveMode({} as any); + // call + await expect(interactiveMode.start()).rejectedWith(TEST_ERROR); + }); +}); diff --git a/test/unit/commands/dialog/replay-mode-test.js b/test/unit/commands/dialog/replay-mode-test.js deleted file mode 100644 index 1af6108a..00000000 --- a/test/unit/commands/dialog/replay-mode-test.js +++ /dev/null @@ -1,101 +0,0 @@ -const { expect } = require('chai'); -const sinon = require('sinon'); - -const InteractiveMode = require('@src/commands/dialog/interactive-mode'); -const ReplayMode = require('@src/commands/dialog/replay-mode'); -const DialogController = require('@src/controllers/dialog-controller'); -const DialogReplView = require('@src/view/dialog-repl-view'); - -describe('# Command: Dialog - Replay Mode test ', () => { - const TEST_ERROR = 'error'; - const dialogReplViewPrototype = Object.getPrototypeOf(DialogReplView); - - afterEach(() => { - Object.setPrototypeOf(DialogReplView, dialogReplViewPrototype); - sinon.restore(); - }); - - it('| test replay mode start, dialog repl view creation throws error', () => { - // setup - const dialogReplViewStub = sinon.stub().throws(new Error(TEST_ERROR)); - Object.setPrototypeOf(DialogReplView, dialogReplViewStub); - const replayMode = new ReplayMode({}); - - // call - replayMode.start((error) => { - // verify - expect(error.message).equal(TEST_ERROR); - }); - }); - - it('test replay mode start, setupSpecialCommands throws error', () => { - // setup - const dialogReplViewStub = sinon.stub().callsFake(); - Object.setPrototypeOf(DialogReplView, dialogReplViewStub); - sinon.stub(DialogController.prototype, 'setupSpecialCommands').callsArgWith(1, TEST_ERROR); - const replayMode = new ReplayMode({ - userInputs: ['hello'] - }); - - // call - replayMode.start((error) => { - // verify - expect(error).equal(TEST_ERROR); - }); - }); - - describe('# test _evaluateInput', () => { - let replayCallbackStub; - - beforeEach(() => { - replayCallbackStub = sinon.stub(); - }); - - afterEach(() => { - sinon.restore(); - }); - - it('| continue in replay mode', () => { - // setup - const replayMode = new ReplayMode({ - userInputs: ['hello'] - }); - const inputStream = []; - sinon.stub(DialogController.prototype, 'evaluateUtterance').callsArgWith(2, ''); - - // call - replayMode._evaluateInput({}, {}, inputStream, replayCallbackStub, () => {}); - - // verify - expect(inputStream[0]).equal('hello\n'); - expect(replayCallbackStub.calledOnce).equal(true); - }); - - it('| switch to interactive mode', () => { - // setup - const config = { - userInputs: [] - }; - const replayMode = new ReplayMode(config); - const clearSpecialCommandsStub = sinon.stub(); - const replViewCloseStub = sinon.stub(); - const replViewStub = { - clearSpecialCommands: clearSpecialCommandsStub, - close: replViewCloseStub - }; - const inputStream = []; - sinon.stub(DialogController.prototype, 'evaluateUtterance').callsArgWith(2, ''); - const interactiveStartStub = sinon.stub(InteractiveMode.prototype, 'start'); - // call - replayMode._evaluateInput({}, replViewStub, inputStream, replayCallbackStub, () => {}); - - // verify - expect(inputStream.length).equal(0); - expect(clearSpecialCommandsStub.calledOnce).equal(true); - expect(replViewCloseStub.calledOnce).equal(true); - expect(config.header).equal('Switching to interactive dialog.\n' - + 'To automatically quit after replay, append \'.quit\' to the userInput of your replay file.\n'); - expect(interactiveStartStub.calledOnce).equal(true); - }); - }); -}); diff --git a/test/unit/commands/dialog/replay-mode.spec.ts b/test/unit/commands/dialog/replay-mode.spec.ts new file mode 100644 index 00000000..0aadc0d8 --- /dev/null +++ b/test/unit/commands/dialog/replay-mode.spec.ts @@ -0,0 +1,96 @@ +import {expect} from "chai"; +import sinon from "sinon"; + +import {InteractiveMode} from "../../../../lib/commands/dialog/interactive-mode"; +import {ReplayMode} from "../../../../lib/commands/dialog/replay-mode"; +import {DialogController} from "../../../../lib/controllers/dialog-controller"; +import {DialogReplView} from "../../../../lib/view/dialog-repl-view"; + +describe("# Command: Dialog - Replay Mode test ", () => { + const TEST_ERROR = "error"; + const dialogReplViewPrototype = Object.getPrototypeOf(DialogReplView); + + afterEach(() => { + Object.setPrototypeOf(DialogReplView, dialogReplViewPrototype); + sinon.restore(); + }); + + it("| test replay mode start, dialog repl view creation throws error", async () => { + // setup + const dialogReplViewStub = sinon.stub().throws(new Error(TEST_ERROR)); + Object.setPrototypeOf(DialogReplView, dialogReplViewStub); + const replayMode = new ReplayMode({} as any); + + // call + await expect(replayMode.start()).rejectedWith(TEST_ERROR); + }); + + it("test replay mode start, setupSpecialCommands throws error", async () => { + // setup + const dialogReplViewStub = sinon.stub().callsFake(() => {}); + Object.setPrototypeOf(DialogReplView, dialogReplViewStub); + sinon.stub(DialogController.prototype, "setupSpecialCommands").rejects(Error(TEST_ERROR)); + const replayMode = new ReplayMode({ + userInputs: ["hello"], + } as any); + + // call + await expect(replayMode.start()).rejectedWith(TEST_ERROR); + }); + + describe("# test _evaluateInput", () => { + let replayCallbackStub: sinon.SinonStub; + + beforeEach(() => { + replayCallbackStub = sinon.stub(); + }); + + afterEach(() => { + sinon.restore(); + }); + + it("| continue in replay mode", async () => { + // setup + const replayMode = new ReplayMode({ + userInputs: ["hello"], + } as any); + const inputStream: string[] = []; + sinon.stub(DialogController.prototype, "evaluateUtterance").rejects(Error("")); + + // call + await replayMode._evaluateInput({}, {}, inputStream, replayCallbackStub); + + // verify + expect(inputStream[0]).equal("hello\n"); + expect(replayCallbackStub.calledOnce).equal(true); + }); + + it("| switch to interactive mode", async () => { + // setup + const config = { + userInputs: [], + } as any; + const replayMode = new ReplayMode(config); + const clearSpecialCommandsStub = sinon.stub(); + const replViewCloseStub = sinon.stub(); + const replViewStub = { + clearSpecialCommands: clearSpecialCommandsStub, + close: replViewCloseStub, + }; + const inputStream: string[] = []; + sinon.stub(DialogController.prototype, "evaluateUtterance").rejects(Error("")); + const interactiveStartStub = sinon.stub(InteractiveMode.prototype, "start").resolves(); + // call + await replayMode._evaluateInput({}, replViewStub, inputStream, replayCallbackStub); + + // verify + expect(inputStream.length).equal(0); + expect(clearSpecialCommandsStub.calledOnce).equal(true); + expect(replViewCloseStub.calledOnce).equal(true); + expect(replayMode.config.header).equal( + "Switching to interactive dialog.\n" + "To automatically quit after replay, append '.quit' to the userInput of your replay file.\n", + ); + expect(interactiveStartStub.calledOnce).equal(true); + }); + }); +}); diff --git a/test/unit/commands/init/helper-test.js b/test/unit/commands/init/helper-test.js index c711b759..c100b218 100644 --- a/test/unit/commands/init/helper-test.js +++ b/test/unit/commands/init/helper-test.js @@ -1,428 +1,437 @@ -const { expect } = require('chai'); -const sinon = require('sinon'); -const fs = require('fs-extra'); -const path = require('path'); - -const SkillInfrastructureController = require('@src/controllers/skill-infrastructure-controller'); -const helper = require('@src/commands/init/helper'); -const ui = require('@src/commands/init/ui'); -const ResourcesConfig = require('@src/model/resources-config'); -const AskResources = require('@src/model/resources-config/ask-resources'); -const AskStates = require('@src/model/resources-config/ask-states'); -const CONSTANTS = require('@src/utils/constants'); -const Messenger = require('@src/view/messenger'); - - -describe('Commands init - helper test', () => { - const FIXTURE_RESOURCES_CONFIG_FILE_PATH = path.join(process.cwd(), 'test', 'unit', 'fixture', 'model', 'regular-proj', 'ask-resources.json'); - const TEST_PROFILE = 'default'; - const TEST_SKILL_ID = 'skillId'; - const TEST_SRC = 'src'; - const TEST_ROOT = 'root'; - const TEST_ERROR = 'init error'; - - describe('# unit test for method preInitCheck', () => { - let uiShowInitStub; - let uiConfirmOverwriteStub; - let fsExistsStub; - - beforeEach(() => { - uiShowInitStub = sinon.stub(ui, 'showInitInstruction'); - fsExistsStub = sinon.stub(fs, 'existsSync').returns(true); - uiConfirmOverwriteStub = sinon.stub(ui, 'confirmOverwrite'); - }); - - afterEach(() => { - sinon.restore(); - }); - - it('| verify init instruction displayed, but overwrite confirmation fails', (done) => { - // setup - uiConfirmOverwriteStub.callsArgWith(0, TEST_ERROR); - // call - helper.preInitCheck(TEST_ROOT, TEST_PROFILE, (err, res) => { - // verify - expect(uiShowInitStub.callCount).equal(1); - expect(err).equal(TEST_ERROR); - expect(res).equal(undefined); - done(); - }); - }); - - it('| pre init check and overwrite confirmation returns false', (done) => { - // setup - uiConfirmOverwriteStub.callsArgWith(0, null, false); - // call - helper.preInitCheck(TEST_ROOT, TEST_PROFILE, (err, res) => { - // verify - expect(uiShowInitStub.callCount).equal(1); - expect(err.message).equal(`Please modify the existing ${CONSTANTS.FILE_PATH.ASK_RESOURCES_JSON_CONFIG} file or choose to overwrite.`); - expect(err.name).equal('CliWarn'); - expect(res).equal(undefined); - done(); - }); - }); - - it('| pre init check and overwrite confirmation returns true', (done) => { - // setup - uiConfirmOverwriteStub.callsArgWith(0, null, true); - // call - helper.preInitCheck(TEST_ROOT, TEST_PROFILE, (err, res) => { - // verify - expect(uiShowInitStub.callCount).equal(1); - expect(err).equal(undefined); - expect(res).equal(undefined); - done(); - }); - }); +const {expect} = require("chai"); +const sinon = require("sinon"); +const fs = require("fs-extra"); +const path = require("path"); + +const SkillInfrastructureController = require("../../../../lib/controllers/skill-infrastructure-controller"); +const helper = require("../../../../lib/commands/init/helper"); +const ui = require("../../../../lib/commands/init/ui"); +const ResourcesConfig = require("../../../../lib/model/resources-config"); +const AskResources = require("../../../../lib/model/resources-config/ask-resources"); +const AskStates = require("../../../../lib/model/resources-config/ask-states"); +const CONSTANTS = require("../../../../lib/utils/constants"); +const Messenger = require("../../../../lib/view/messenger"); + +describe("Commands init - helper test", () => { + const FIXTURE_RESOURCES_CONFIG_FILE_PATH = path.join( + process.cwd(), + "test", + "unit", + "fixture", + "model", + "regular-proj", + "ask-resources.json", + ); + const TEST_PROFILE = "default"; + const TEST_SKILL_ID = "skillId"; + const TEST_SRC = "src"; + const TEST_ROOT = "root"; + const TEST_ERROR = "init error"; + + describe("# unit test for method preInitCheck", () => { + let uiShowInitStub; + let uiConfirmOverwriteStub; + let fsExistsStub; + + beforeEach(() => { + uiShowInitStub = sinon.stub(ui, "showInitInstruction"); + fsExistsStub = sinon.stub(fs, "existsSync").returns(true); + uiConfirmOverwriteStub = sinon.stub(ui, "confirmOverwrite"); + }); - it('| pre init check and ask resources file not exists', (done) => { - // setup - fsExistsStub.returns(false); - // call - helper.preInitCheck(TEST_ROOT, TEST_PROFILE, (err, res) => { - // verify - expect(uiShowInitStub.callCount).equal(1); - expect(err).equal(undefined); - expect(res).equal(undefined); - done(); - }); - }); + afterEach(() => { + sinon.restore(); }); - describe('# unit test for method getSkillIdUserInput', () => { - beforeEach(() => { - sinon.stub(ui, 'getSkillId'); - }); + it("| verify init instruction displayed, but overwrite confirmation fails", (done) => { + // setup + uiConfirmOverwriteStub.callsArgWith(0, TEST_ERROR); + // call + helper.preInitCheck(TEST_ROOT, TEST_PROFILE, (err, res) => { + // verify + expect(uiShowInitStub.callCount).equal(1); + expect(err).equal(TEST_ERROR); + expect(res).equal(undefined); + done(); + }); + }); - afterEach(() => { - sinon.restore(); - }); + it("| pre init check and overwrite confirmation returns false", (done) => { + // setup + uiConfirmOverwriteStub.callsArgWith(0, null, false); + // call + helper.preInitCheck(TEST_ROOT, TEST_PROFILE, (err, res) => { + // verify + expect(uiShowInitStub.callCount).equal(1); + expect(err.message).equal( + `Please modify the existing ${CONSTANTS.FILE_PATH.ASK_RESOURCES_JSON_CONFIG} file or choose to overwrite.`, + ); + expect(err.name).equal("CliWarn"); + expect(res).equal(undefined); + done(); + }); + }); - it('| get skillId from user but error happens', (done) => { - // setup - ui.getSkillId.callsArgWith(0, TEST_ERROR); - // call - helper.getSkillIdUserInput((err, response) => { - // verify - expect(err).equal(TEST_ERROR); - expect(response).equal(null); - done(); - }); - }); + it("| pre init check and overwrite confirmation returns true", (done) => { + // setup + uiConfirmOverwriteStub.callsArgWith(0, null, true); + // call + helper.preInitCheck(TEST_ROOT, TEST_PROFILE, (err, res) => { + // verify + expect(uiShowInitStub.callCount).equal(1); + expect(err).equal(undefined); + expect(res).equal(undefined); + done(); + }); + }); - it('| get skillId from user inputs success', (done) => { - // setup - ui.getSkillId.callsArgWith(0, null, TEST_SKILL_ID); - // call - helper.getSkillIdUserInput((err, response) => { - // verify - expect(err).equal(null); - expect(response).equal(TEST_SKILL_ID); - done(); - }); - }); + it("| pre init check and ask resources file not exists", (done) => { + // setup + fsExistsStub.returns(false); + // call + helper.preInitCheck(TEST_ROOT, TEST_PROFILE, (err, res) => { + // verify + expect(uiShowInitStub.callCount).equal(1); + expect(err).equal(undefined); + expect(res).equal(undefined); + done(); + }); }); + }); - describe('# unit test for method getSkillMetadataUserInput', () => { - beforeEach(() => { - sinon.stub(ui, 'getSkillMetaSrc'); - }); + describe("# unit test for method getSkillIdUserInput", () => { + beforeEach(() => { + sinon.stub(ui, "getSkillId"); + }); - afterEach(() => { - sinon.restore(); - }); + afterEach(() => { + sinon.restore(); + }); - it('| getSkillMetaSrc from user but error happens', (done) => { - // setup - ui.getSkillMetaSrc.callsArgWith(0, TEST_ERROR); - // call - helper.getSkillMetadataUserInput((err, response) => { - // verify - expect(err).equal(TEST_ERROR); - expect(response).equal(null); - done(); - }); - }); + it("| get skillId from user but error happens", (done) => { + // setup + ui.getSkillId.callsArgWith(0, TEST_ERROR); + // call + helper.getSkillIdUserInput((err, response) => { + // verify + expect(err).equal(TEST_ERROR); + expect(response).equal(null); + done(); + }); + }); - it('| getSkillMetaSrc from user inputs success', (done) => { - // setup - ui.getSkillMetaSrc.callsArgWith(0, null, TEST_SRC); - // call - helper.getSkillMetadataUserInput((err, response) => { - // verify - expect(err).equal(null); - expect(response).deep.equal({ src: TEST_SRC }); - done(); - }); - }); + it("| get skillId from user inputs success", (done) => { + // setup + ui.getSkillId.callsArgWith(0, null, TEST_SKILL_ID); + // call + helper.getSkillIdUserInput((err, response) => { + // verify + expect(err).equal(null); + expect(response).equal(TEST_SKILL_ID); + done(); + }); }); + }); - describe('# unit test for method getSkillCodeUserInput', () => { - beforeEach(() => { - sinon.stub(ui, 'getCodeSrcForRegion'); - }); + describe("# unit test for method getSkillMetadataUserInput", () => { + beforeEach(() => { + sinon.stub(ui, "getSkillMetaSrc"); + }); - afterEach(() => { - sinon.restore(); - }); + afterEach(() => { + sinon.restore(); + }); - it('| getSkillCodeUserInput from user but error happens', (done) => { - // setup - ui.getCodeSrcForRegion.callsArgWith(1, TEST_ERROR); - // call - helper.getSkillCodeUserInput((err, response) => { - // verify - expect(err).equal(TEST_ERROR); - expect(response).equal(undefined); - done(); - }); - }); + it("| getSkillMetaSrc from user but error happens", (done) => { + // setup + ui.getSkillMetaSrc.callsArgWith(0, TEST_ERROR); + // call + helper.getSkillMetadataUserInput((err, response) => { + // verify + expect(err).equal(TEST_ERROR); + expect(response).equal(null); + done(); + }); + }); - it('| getSkillCodeUserInput from user as empty string', (done) => { - // setup - ui.getCodeSrcForRegion.callsArgWith(1, null, ''); - // call - helper.getSkillCodeUserInput((err, response) => { - // verify - expect(err).equal(undefined); - expect(response).equal(undefined); - done(); - }); - }); + it("| getSkillMetaSrc from user inputs success", (done) => { + // setup + ui.getSkillMetaSrc.callsArgWith(0, null, TEST_SRC); + // call + helper.getSkillMetadataUserInput((err, response) => { + // verify + expect(err).equal(null); + expect(response).deep.equal({src: TEST_SRC}); + done(); + }); + }); + }); - it('| getSkillCodeUserInput from user inputs success', (done) => { - // setup - ui.getCodeSrcForRegion.callsArgWith(1, null, TEST_SRC); - // call - helper.getSkillCodeUserInput((err, response) => { - // verify - expect(err).equal(null); - expect(response).deep.equal({ default: { src: TEST_SRC } }); - done(); - }); - }); + describe("# unit test for method getSkillCodeUserInput", () => { + beforeEach(() => { + sinon.stub(ui, "getCodeSrcForRegion"); }); - describe('# unit test for method getSkillInfraUserInput', () => { - function TEST_INFRA(isUsingCfn, runtime, handler) { - return { isUsingCfn, runtime, handler }; - } + afterEach(() => { + sinon.restore(); + }); - beforeEach(() => { - sinon.stub(ui, 'getSkillInfra'); - }); + it("| getSkillCodeUserInput from user but error happens", (done) => { + // setup + ui.getCodeSrcForRegion.callsArgWith(1, TEST_ERROR); + // call + helper.getSkillCodeUserInput((err, response) => { + // verify + expect(err).equal(TEST_ERROR); + expect(response).equal(undefined); + done(); + }); + }); - afterEach(() => { - sinon.restore(); - }); + it("| getSkillCodeUserInput from user as empty string", (done) => { + // setup + ui.getCodeSrcForRegion.callsArgWith(1, null, ""); + // call + helper.getSkillCodeUserInput((err, response) => { + // verify + expect(err).equal(undefined); + expect(response).equal(undefined); + done(); + }); + }); - it('| getSkillInfraUserInput from user but error happens', (done) => { - // setup - ui.getSkillInfra.callsArgWith(0, TEST_ERROR); - // call - helper.getSkillInfraUserInput((err, response) => { - // verify - expect(err).equal(TEST_ERROR); - expect(response).equal(undefined); - done(); - }); - }); + it("| getSkillCodeUserInput from user inputs success", (done) => { + // setup + ui.getCodeSrcForRegion.callsArgWith(1, null, TEST_SRC); + // call + helper.getSkillCodeUserInput((err, response) => { + // verify + expect(err).equal(null); + expect(response).deep.equal({default: {src: TEST_SRC}}); + done(); + }); + }); + }); - it('| getSkillInfraUserInput from user input success', (done) => { - // setup - ui.getSkillInfra.callsArgWith(0, null, TEST_INFRA(true, 'runtime', 'handler')); - // call - helper.getSkillInfraUserInput((err, response) => { - // verify - expect(err).equal(null); - expect(response).deep.equal({ - type: '@ask-cli/cfn-deployer', - userConfig: { - runtime: 'runtime', - handler: 'handler' - } - }); - done(); - }); - }); + describe("# unit test for method getSkillInfraUserInput", () => { + function TEST_INFRA(isUsingCfn, runtime, handler) { + return {isUsingCfn, runtime, handler}; + } - it('| getSkillInfraUserInput from user input success, without using cfn', (done) => { - // setup - ui.getSkillInfra.callsArgWith(0, null, TEST_INFRA(false, 'runtime', 'handler')); - // call - helper.getSkillInfraUserInput((err, response) => { - // verify - expect(err).equal(null); - expect(response).deep.equal({ - type: '@ask-cli/lambda-deployer', - userConfig: { - runtime: 'runtime', - handler: 'handler' - } - }); - done(); - }); - }); + beforeEach(() => { + sinon.stub(ui, "getSkillInfra"); }); - describe('# unit test for method previewAndWriteAskResources', () => { - const TEST_USER_INPUT = { - skillId: TEST_SKILL_ID, - skillMeta: { - src: TEST_SRC - }, - skillCode: { - default: { - src: TEST_SRC - } - }, - skillInfra: { - type: '@ask-cli/cfn-deployer', - userConfig: { - runtime: 'runtime', - handler: 'handler' - } - } - }; - - beforeEach(() => { - sinon.stub(ui, 'showPreviewAndConfirm'); - sinon.stub(fs, 'removeSync'); - sinon.stub(path, 'join').returns(TEST_SRC); - sinon.stub(AskResources, 'withContent'); - sinon.stub(AskStates, 'withContent'); - }); + afterEach(() => { + sinon.restore(); + }); - afterEach(() => { - sinon.restore(); - }); + it("| getSkillInfraUserInput from user but error happens", (done) => { + // setup + ui.getSkillInfra.callsArgWith(0, TEST_ERROR); + // call + helper.getSkillInfraUserInput((err, response) => { + // verify + expect(err).equal(TEST_ERROR); + expect(response).equal(undefined); + done(); + }); + }); - it('| previewAndWriteAskResources fails when displaying the preview and confirming', (done) => { - // setup - ui.showPreviewAndConfirm.callsArgWith(2, TEST_ERROR); - // call - helper.previewAndWriteAskResources(TEST_ROOT, TEST_USER_INPUT, TEST_PROFILE, (err, response) => { - // verify - expect(err).equal(TEST_ERROR); - expect(response).equal(undefined); - done(); - }); - }); + it("| getSkillInfraUserInput from user input success", (done) => { + // setup + ui.getSkillInfra.callsArgWith(0, null, TEST_INFRA(true, "runtime", "handler")); + // call + helper.getSkillInfraUserInput((err, response) => { + // verify + expect(err).equal(null); + expect(response).deep.equal({ + type: "@ask-cli/cfn-deployer", + userConfig: { + runtime: "runtime", + handler: "handler", + }, + }); + done(); + }); + }); - it('| previewAndWriteAskResources fails when user does not confirm', (done) => { - // setup - ui.showPreviewAndConfirm.callsArgWith(2, null, false); - // call - helper.previewAndWriteAskResources(TEST_ROOT, TEST_USER_INPUT, TEST_PROFILE, (err, response) => { - // verify - expect(err.message).equal('Project init aborted.'); - expect(err.name).equal('CliWarn'); - expect(response).equal(undefined); - done(); - }); - }); + it("| getSkillInfraUserInput from user input success, without using cfn", (done) => { + // setup + ui.getSkillInfra.callsArgWith(0, null, TEST_INFRA(false, "runtime", "handler")); + // call + helper.getSkillInfraUserInput((err, response) => { + // verify + expect(err).equal(null); + expect(response).deep.equal({ + type: "@ask-cli/lambda-deployer", + userConfig: { + runtime: "runtime", + handler: "handler", + }, + }); + done(); + }); + }); + }); + + describe("# unit test for method previewAndWriteAskResources", () => { + const TEST_USER_INPUT = { + skillId: TEST_SKILL_ID, + skillMeta: { + src: TEST_SRC, + }, + skillCode: { + default: { + src: TEST_SRC, + }, + }, + skillInfra: { + type: "@ask-cli/cfn-deployer", + userConfig: { + runtime: "runtime", + handler: "handler", + }, + }, + }; + + beforeEach(() => { + sinon.stub(ui, "showPreviewAndConfirm"); + sinon.stub(fs, "removeSync"); + sinon.stub(path, "join").returns(TEST_SRC); + sinon.stub(AskResources, "withContent"); + sinon.stub(AskStates, "withContent"); + }); - it('| previewAndWriteAskResources fails when remove file/folder fails', (done) => { - // setup - ui.showPreviewAndConfirm.callsArgWith(2, null, true); - fs.removeSync.throws(TEST_ERROR); - // call - helper.previewAndWriteAskResources(TEST_ROOT, TEST_USER_INPUT, TEST_PROFILE, (err, response) => { - // verify - expect(err.name).equal(TEST_ERROR); - expect(response).equal(undefined); - done(); - }); - }); + afterEach(() => { + sinon.restore(); + }); - it('| previewAndWriteAskResources succeeds', (done) => { - // setup - ui.showPreviewAndConfirm.callsArgWith(2, null, true); - // call - helper.previewAndWriteAskResources(TEST_ROOT, TEST_USER_INPUT, TEST_PROFILE, (err, response) => { - // verify - expect(fs.removeSync.args[0][0]).equal(TEST_SRC); - expect(fs.removeSync.args[1][0]).equal(TEST_SRC); - expect(AskResources.withContent.args[0][0]).equal(TEST_SRC); - expect(AskResources.withContent.args[0][1].profiles[TEST_PROFILE]).deep.equal({ - skillMetadata: { - src: TEST_SRC - }, - code: { - default: { - src: TEST_SRC - } - }, - skillInfrastructure: { - type: '@ask-cli/cfn-deployer', - userConfig: { - runtime: 'runtime', - handler: 'handler' - } - } - }); - expect(AskStates.withContent.args[0][0]).equal(TEST_SRC); - expect(AskStates.withContent.args[0][1].profiles[TEST_PROFILE]).deep.equal({ - skillId: TEST_SKILL_ID, - skillInfrastructure: { - '@ask-cli/cfn-deployer': { - deployState: {} - } - } - }); - expect(err).equal(undefined); - expect(response).equal(undefined); - done(); - }); - }); + it("| previewAndWriteAskResources fails when displaying the preview and confirming", (done) => { + // setup + ui.showPreviewAndConfirm.callsArgWith(2, TEST_ERROR); + // call + helper.previewAndWriteAskResources(TEST_ROOT, TEST_USER_INPUT, TEST_PROFILE, (err, response) => { + // verify + expect(err).equal(TEST_ERROR); + expect(response).equal(undefined); + done(); + }); }); - describe('# unit test for method bootstrapSkillInfra', () => { - const TEST_ROOT_PATH = 'root'; - let infoStub; + it("| previewAndWriteAskResources fails when user does not confirm", (done) => { + // setup + ui.showPreviewAndConfirm.callsArgWith(2, null, false); + // call + helper.previewAndWriteAskResources(TEST_ROOT, TEST_USER_INPUT, TEST_PROFILE, (err, response) => { + // verify + expect(err.message).equal("Project init aborted."); + expect(err.name).equal("CliWarn"); + expect(response).equal(undefined); + done(); + }); + }); - beforeEach(() => { - sinon.stub(path, 'join'); - path.join.withArgs(TEST_ROOT_PATH, CONSTANTS.FILE_PATH.ASK_RESOURCES_JSON_CONFIG).returns(FIXTURE_RESOURCES_CONFIG_FILE_PATH); - path.join.callThrough(); - sinon.stub(fs, 'ensureDirSync'); - sinon.stub(SkillInfrastructureController.prototype, 'bootstrapInfrastructures'); + it("| previewAndWriteAskResources fails when remove file/folder fails", (done) => { + // setup + ui.showPreviewAndConfirm.callsArgWith(2, null, true); + fs.removeSync.throws(TEST_ERROR); + // call + helper.previewAndWriteAskResources(TEST_ROOT, TEST_USER_INPUT, TEST_PROFILE, (err, response) => { + // verify + expect(err.name).equal(TEST_ERROR); + expect(response).equal(undefined); + done(); + }); + }); - infoStub = sinon.stub(); - sinon.stub(Messenger, 'getInstance').returns({ - info: infoStub - }); + it("| previewAndWriteAskResources succeeds", (done) => { + // setup + ui.showPreviewAndConfirm.callsArgWith(2, null, true); + // call + helper.previewAndWriteAskResources(TEST_ROOT, TEST_USER_INPUT, TEST_PROFILE, (err, response) => { + // verify + expect(fs.removeSync.args[0][0]).equal(TEST_SRC); + expect(fs.removeSync.args[1][0]).equal(TEST_SRC); + expect(AskResources.withContent.args[0][0]).equal(TEST_SRC); + expect(AskResources.withContent.args[0][1].profiles[TEST_PROFILE]).deep.equal({ + skillMetadata: { + src: TEST_SRC, + }, + code: { + default: { + src: TEST_SRC, + }, + }, + skillInfrastructure: { + type: "@ask-cli/cfn-deployer", + userConfig: { + runtime: "runtime", + handler: "handler", + }, + }, + }); + expect(AskStates.withContent.args[0][0]).equal(TEST_SRC); + expect(AskStates.withContent.args[0][1].profiles[TEST_PROFILE]).deep.equal({ + skillId: TEST_SKILL_ID, + skillInfrastructure: { + "@ask-cli/cfn-deployer": { + deployState: {}, + }, + }, }); + expect(err).equal(undefined); + expect(response).equal(undefined); + done(); + }); + }); + }); + + describe("# unit test for method bootstrapSkillInfra", () => { + const TEST_ROOT_PATH = "root"; + let infoStub; + + beforeEach(() => { + sinon.stub(path, "join"); + path.join.withArgs(TEST_ROOT_PATH, CONSTANTS.FILE_PATH.ASK_RESOURCES_JSON_CONFIG).returns(FIXTURE_RESOURCES_CONFIG_FILE_PATH); + path.join.callThrough(); + sinon.stub(fs, "ensureDirSync"); + sinon.stub(SkillInfrastructureController.prototype, "bootstrapInfrastructures"); + + infoStub = sinon.stub(); + sinon.stub(Messenger, "getInstance").returns({ + info: infoStub, + }); + }); - afterEach(() => { - ResourcesConfig.dispose(); - sinon.restore(); - }); + afterEach(() => { + ResourcesConfig.dispose(); + sinon.restore(); + }); - it('| post init bootstrap method but error happens', (done) => { - // setup - SkillInfrastructureController.prototype.bootstrapInfrastructures.callsArgWith(1, TEST_ERROR); - // call - helper.bootstrapSkillInfra(TEST_ROOT_PATH, TEST_PROFILE, false, (err, response) => { - // verify - expect(err).equal(TEST_ERROR); - expect(response).equal(undefined); - done(); - }); - }); + it("| post init bootstrap method but error happens", (done) => { + // setup + SkillInfrastructureController.prototype.bootstrapInfrastructures.callsArgWith(1, TEST_ERROR); + // call + helper.bootstrapSkillInfra(TEST_ROOT_PATH, TEST_PROFILE, false, (err, response) => { + // verify + expect(err).equal(TEST_ERROR); + expect(response).equal(undefined); + done(); + }); + }); - it('| post init and bootstrap succeeds with ask-cli deployer', (done) => { - // setup - SkillInfrastructureController.prototype.bootstrapInfrastructures.callsArgWith(1, null); - // call - helper.bootstrapSkillInfra(TEST_ROOT_PATH, TEST_PROFILE, false, (err, response) => { - // verify - expect(infoStub.args[0][0]).equal('Project bootstrap from deployer "@ask-cli/cfn-deployer" succeeded.'); - expect(err).equal(undefined); - expect(response).equal(undefined); - done(); - }); - }); + it("| post init and bootstrap succeeds with ask-cli deployer", (done) => { + // setup + SkillInfrastructureController.prototype.bootstrapInfrastructures.callsArgWith(1, null); + // call + helper.bootstrapSkillInfra(TEST_ROOT_PATH, TEST_PROFILE, false, (err, response) => { + // verify + expect(infoStub.args[0][0]).equal('Project bootstrap from deployer "@ask-cli/cfn-deployer" succeeded.'); + expect(err).equal(undefined); + expect(response).equal(undefined); + done(); + }); }); + }); }); diff --git a/test/unit/commands/init/index-test.js b/test/unit/commands/init/index-test.js deleted file mode 100644 index fe7dd609..00000000 --- a/test/unit/commands/init/index-test.js +++ /dev/null @@ -1,620 +0,0 @@ -const { expect } = require('chai'); -const sinon = require('sinon'); - -const AuthorizationController = require('@src/controllers/authorization-controller'); -const InitCommand = require('@src/commands/init'); -const helper = require('@src/commands/init/helper'); -const HostedSkillController = require('@src/controllers/hosted-skill-controller'); -const httpClient = require('@src/clients/http-client'); -const CliWarn = require('@src/exceptions/cli-warn'); -const jsonView = require('@src/view/json-view'); -const optionModel = require('@src/commands/option-model'); -const Messenger = require('@src/view/messenger'); -const profileHelper = require('@src/utils/profile-helper'); - -const ui = require('@src/commands/init/ui'); - -describe('Commands init test - command class test', () => { - const TEST_PROFILE = 'default'; - const TEST_ERROR = 'init error'; - const TEST_WARN = new CliWarn('init warn'); - const TEST_SKILL_ID = 'skillId'; - const TEST_SKILL_NAME = 'TEST_SKILL_NAME'; - const TEST_SRC = 'src'; - const TEST_SKILL_META = { src: TEST_SRC }; - const TEST_SKILL_CODE = { src: TEST_SRC }; - const TEST_SKILL_INFRA = {}; - const TEST_HOSTED_SKILL_ID = 'hosted skill id'; - - let infoStub; - let errorStub; - let warnStub; - - beforeEach(() => { - infoStub = sinon.stub(); - errorStub = sinon.stub(); - warnStub = sinon.stub(); - sinon.stub(Messenger, 'getInstance').returns({ - info: infoStub, - error: errorStub, - warn: warnStub - }); - }); - - afterEach(() => { - sinon.restore(); - }); - - it('| validate command information is set correctly', () => { - const instance = new InitCommand(optionModel); - expect(instance.name()).equal('init'); - expect(instance.description()).equal('setup a new or existing Alexa skill project'); - expect(instance.requiredOptions()).deep.equal([]); - expect(instance.optionalOptions()).deep.equal(['hosted-skill-id', 'profile', 'debug']); - }); - - describe('validate command handle', () => { - describe('command handle - pre init check', () => { - let instance; - - beforeEach(() => { - instance = new InitCommand(optionModel); - sinon.stub(profileHelper, 'runtimeProfile').returns(TEST_PROFILE); - }); - - afterEach(() => { - sinon.restore(); - }); - - it('| when profile is not correct, expect throw error', (done) => { - // setup - const TEST_CMD = { - profile: TEST_PROFILE - }; - profileHelper.runtimeProfile.throws(new Error('error')); - // call - instance.handle(TEST_CMD, (err) => { - // verify - expect(err.message).equal('error'); - expect(errorStub.args[0][0].message).equal('error'); - expect(infoStub.callCount).equal(0); - expect(warnStub.callCount).equal(0); - done(); - }); - }); - - it('| when pre init check fails, expect throw error', (done) => { - // setup - const TEST_CMD = { - profile: TEST_PROFILE - }; - sinon.stub(helper, 'preInitCheck').callsArgWith(2, TEST_ERROR); - // call - instance.handle(TEST_CMD, (err) => { - // verify - expect(err).equal(TEST_ERROR); - expect(errorStub.args[0][0]).equal(TEST_ERROR); - expect(infoStub.callCount).equal(0); - expect(warnStub.callCount).equal(0); - done(); - }); - }); - - it('| when pre init check returns CliWarn, expect provide users warnings', (done) => { - // setup - const TEST_CMD = { - profile: TEST_PROFILE - }; - sinon.stub(helper, 'preInitCheck').callsArgWith(2, TEST_WARN); - // call - instance.handle(TEST_CMD, (err) => { - // verify - expect(err).deep.equal(TEST_WARN); - expect(warnStub.args[0][0]).equal(TEST_WARN.message); - expect(infoStub.callCount).equal(0); - expect(errorStub.callCount).equal(0); - done(); - }); - }); - }); - - describe('command handle - collect ask resources', () => { - let instance; - - beforeEach(() => { - instance = new InitCommand(optionModel); - sinon.stub(profileHelper, 'runtimeProfile').returns(TEST_PROFILE); - sinon.stub(helper, 'preInitCheck').callsArgWith(2); - sinon.stub(helper, 'getSkillIdUserInput'); - sinon.stub(helper, 'getSkillMetadataUserInput'); - sinon.stub(helper, 'getSkillCodeUserInput'); - sinon.stub(helper, 'getSkillInfraUserInput'); - sinon.stub(helper, 'previewAndWriteAskResources').callsArgWith(3, TEST_ERROR); - }); - - afterEach(() => { - sinon.restore(); - }); - - it('| when collect skill id fails, expect throw error', (done) => { - // setup - const TEST_CMD = { - profile: TEST_PROFILE - }; - helper.getSkillIdUserInput.callsArgWith(0, TEST_ERROR); - // call - instance.handle(TEST_CMD, (err) => { - // verify - expect(err).equal(TEST_ERROR); - expect(errorStub.args[0][0]).equal(TEST_ERROR); - expect(infoStub.callCount).equal(0); - expect(warnStub.callCount).equal(0); - done(); - }); - }); - - it('| when collect skill meta src fails, expect throw error', (done) => { - // setup - const TEST_CMD = { - profile: TEST_PROFILE - }; - helper.getSkillIdUserInput.callsArgWith(0, null, TEST_SKILL_ID); - helper.getSkillMetadataUserInput.callsArgWith(0, TEST_ERROR); - // call - instance.handle(TEST_CMD, (err) => { - // verify - expect(err).equal(TEST_ERROR); - expect(errorStub.args[0][0]).equal(TEST_ERROR); - expect(infoStub.callCount).equal(0); - expect(warnStub.callCount).equal(0); - done(); - }); - }); - - it('| when collect skill code src fails, expect throw error', (done) => { - // setup - const TEST_CMD = { - profile: TEST_PROFILE - }; - helper.getSkillIdUserInput.callsArgWith(0, null, TEST_SKILL_ID); - helper.getSkillMetadataUserInput.callsArgWith(0, null, TEST_SKILL_META); - helper.getSkillCodeUserInput.callsArgWith(0, TEST_ERROR); - // call - instance.handle(TEST_CMD, (err) => { - // verify - expect(err).equal(TEST_ERROR); - expect(errorStub.args[0][0]).equal(TEST_ERROR); - expect(infoStub.callCount).equal(0); - expect(warnStub.callCount).equal(0); - done(); - }); - }); - - it('| when collect skill code src is not provided, callback without continuing', (done) => { - // setup - const TEST_CMD = { - profile: TEST_PROFILE - }; - helper.getSkillIdUserInput.callsArgWith(0, null, TEST_SKILL_ID); - helper.getSkillMetadataUserInput.callsArgWith(0, null, TEST_SKILL_META); - helper.getSkillCodeUserInput.callsArgWith(0, null, null); - // call - instance.handle(TEST_CMD, (err) => { - // verify - expect(helper.previewAndWriteAskResources.args[0][1]).deep.equal({ - skillId: TEST_SKILL_ID, - skillMeta: { - src: TEST_SRC - } - }); - expect(err).equal(TEST_ERROR); - expect(errorStub.args[0][0]).equal(TEST_ERROR); - expect(infoStub.callCount).equal(0); - expect(warnStub.callCount).equal(0); - done(); - }); - }); - - it('| when collect skill infra fails, expect throw error', (done) => { - // setup - const TEST_CMD = { - profile: TEST_PROFILE - }; - helper.getSkillIdUserInput.callsArgWith(0, null, TEST_SKILL_ID); - helper.getSkillMetadataUserInput.callsArgWith(0, null, TEST_SKILL_META); - helper.getSkillCodeUserInput.callsArgWith(0, null, TEST_SKILL_CODE); - helper.getSkillInfraUserInput.callsArgWith(0, TEST_ERROR); - // call - instance.handle(TEST_CMD, (err) => { - // verify - expect(err).equal(TEST_ERROR); - expect(errorStub.args[0][0]).equal(TEST_ERROR); - expect(infoStub.callCount).equal(0); - expect(warnStub.callCount).equal(0); - done(); - }); - }); - - it('| when collect skill info all succeed, expect it passes correct user input', (done) => { - // setup - const TEST_CMD = { - profile: TEST_PROFILE - }; - helper.getSkillIdUserInput.callsArgWith(0, null, TEST_SKILL_ID); - helper.getSkillMetadataUserInput.callsArgWith(0, null, TEST_SKILL_META); - helper.getSkillCodeUserInput.callsArgWith(0, null, TEST_SKILL_CODE); - helper.getSkillInfraUserInput.callsArgWith(0, null, TEST_SKILL_INFRA); - // call - instance.handle(TEST_CMD, (err) => { - // verify - expect(helper.previewAndWriteAskResources.args[0][1]).deep.equal({ - skillId: TEST_SKILL_ID, - skillMeta: TEST_SKILL_META, - skillCode: TEST_SKILL_CODE, - skillInfra: TEST_SKILL_INFRA - }); - expect(err).equal(TEST_ERROR); - expect(errorStub.args[0][0]).equal(TEST_ERROR); - expect(infoStub.callCount).equal(0); - expect(warnStub.callCount).equal(0); - done(); - }); - }); - }); - - describe('command handle - post user input logics', () => { - let instance; - - beforeEach(() => { - instance = new InitCommand(optionModel); - sinon.stub(profileHelper, 'runtimeProfile').returns(TEST_PROFILE); - sinon.stub(helper, 'preInitCheck').callsArgWith(2); - sinon.stub(helper, 'getSkillIdUserInput').callsArgWith(0, null, TEST_SKILL_ID); - sinon.stub(helper, 'getSkillMetadataUserInput').callsArgWith(0, null, TEST_SKILL_META); - sinon.stub(helper, 'getSkillCodeUserInput').callsArgWith(0, null, TEST_SKILL_CODE); - sinon.stub(helper, 'getSkillInfraUserInput').callsArgWith(0, null, TEST_SKILL_INFRA); - - sinon.stub(helper, 'previewAndWriteAskResources'); - sinon.stub(helper, 'bootstrapSkillInfra'); - }); - - afterEach(() => { - sinon.restore(); - }); - - it('| when preview and write fails, expect throws error', (done) => { - // setup - const TEST_CMD = { - profile: TEST_PROFILE - }; - helper.previewAndWriteAskResources.callsArgWith(3, TEST_ERROR); - // call - instance.handle(TEST_CMD, (err) => { - // verify - expect(err).equal(TEST_ERROR); - expect(errorStub.args[0][0]).equal(TEST_ERROR); - expect(infoStub.callCount).equal(0); - expect(warnStub.callCount).equal(0); - done(); - }); - }); - - it('| when preview and write returns CliWarn, expect display warnings', (done) => { - // setup - const TEST_CMD = { - profile: TEST_PROFILE - }; - helper.previewAndWriteAskResources.callsArgWith(3, TEST_WARN); - // call - instance.handle(TEST_CMD, (err) => { - // verify - expect(err).deep.equal(TEST_WARN); - expect(warnStub.args[0][0]).equal(TEST_WARN.message); - expect(infoStub.callCount).equal(0); - expect(errorStub.callCount).equal(0); - done(); - }); - }); - - it('| when post init executions fails, expect throws error', (done) => { - // setup - const TEST_CMD = { - profile: TEST_PROFILE - }; - helper.previewAndWriteAskResources.callsArgWith(3); - helper.bootstrapSkillInfra.callsArgWith(3, TEST_ERROR); - // call - instance.handle(TEST_CMD, (err) => { - // verify - expect(err).equal(TEST_ERROR); - expect(errorStub.args[0][0]).equal(TEST_ERROR); - expect(infoStub.callCount).equal(0); - expect(warnStub.callCount).equal(0); - done(); - }); - }); - - it('| when all the steps succeed, expect seeing success message', (done) => { - // setup - const TEST_CMD = { - profile: TEST_PROFILE - }; - helper.previewAndWriteAskResources.callsArgWith(3); - helper.bootstrapSkillInfra.callsArgWith(3); - // call - instance.handle(TEST_CMD, (err) => { - // verify - expect(err).equal(undefined); - expect(infoStub.args[0][0]).equal('\nSuccess! Run "ask deploy" to deploy your skill.'); - expect(infoStub.callCount).equal(1); - expect(errorStub.callCount).equal(0); - expect(warnStub.callCount).equal(0); - done(); - }); - }); - }); - }); - - describe('command handle - get skill name', () => { - let instance; - const TEST_CMD = { - profile: TEST_PROFILE, - hostedSkillId: TEST_HOSTED_SKILL_ID - }; - - beforeEach(() => { - instance = new InitCommand(optionModel); - sinon.stub(AuthorizationController.prototype, 'tokenRefreshAndRead').callsArgWith(1); - sinon.stub(profileHelper, 'runtimeProfile').returns(TEST_PROFILE); - }); - - afterEach(() => { - sinon.restore(); - }); - - it('| get skill manifest fails, expect error thrown', (done) => { - // setup - sinon.stub(httpClient, 'request').callsArgWith(3, TEST_ERROR); // stub getManifest request - // call - instance.handle(TEST_CMD, (err) => { - // verify - expect(err).equal(TEST_ERROR); - expect(errorStub.args[0][0]).equal(TEST_ERROR); - done(); - }); - }); - - it('| get skill manifest response with status code >= 300, expect error thrown', (done) => { - // setup - const GET_MANIFEST_ERROR = { - statusCode: 403, - body: { - error: TEST_ERROR - } - }; - sinon.stub(httpClient, 'request').callsArgWith(3, null, GET_MANIFEST_ERROR); // stub getManifest request - // call - instance.handle(TEST_CMD, (err) => { - // verify - expect(err).equal(jsonView.toString({ error: TEST_ERROR })); - expect(errorStub.args[0][0]).equal(jsonView.toString({ error: TEST_ERROR })); - done(); - }); - }); - - it('| get skill manifest succeed without locales, expect error thrown', (done) => { - // setup - const TEST_NO_FOUND_ERROR = 'No skill name found.'; - const GET_MANIFEST_RESPONSE_NO_LOCALES = { - statusCode: 200, - headers: {}, - body: { - manifest: { - publishingInformation: {} - } - } - }; - sinon.stub(httpClient, 'request').callsArgWith(3, null, GET_MANIFEST_RESPONSE_NO_LOCALES); // stub getManifest request - // call - instance.handle(TEST_CMD, (err) => { - // verify - expect(err).equal(TEST_NO_FOUND_ERROR); - expect(errorStub.args[0][0]).equal(TEST_NO_FOUND_ERROR); - done(); - }); - }); - }); - - describe('command handle - confirm project folder name', () => { - let instance; - const TEST_CMD = { - profile: TEST_PROFILE, - hostedSkillId: TEST_HOSTED_SKILL_ID - }; - const TEST_LOCALE = 'en-US'; - - beforeEach(() => { - instance = new InitCommand(optionModel); - sinon.stub(AuthorizationController.prototype, 'tokenRefreshAndRead').callsArgWith(1); - sinon.stub(profileHelper, 'runtimeProfile').returns(TEST_PROFILE); - }); - - afterEach(() => { - sinon.restore(); - }); - it('| get project name, ui get project folder name fails, expect error thrown', (done) => { - // setup - const GET_MANIFEST_RESPONSE = { - statusCode: 200, - headers: {}, - body: { - manifest: { - publishingInformation: { - locales: { - [TEST_LOCALE]: { - name: TEST_SKILL_NAME - } - } - } - } - } - }; - const TEST_UI_ERROR = 'TEST_UI_ERROR'; - sinon.stub(httpClient, 'request').callsArgWith(3, null, GET_MANIFEST_RESPONSE); // stub getManifest request - sinon.stub(ui, 'getProjectFolderName').callsArgWith(1, TEST_UI_ERROR); - // call - instance.handle(TEST_CMD, (err) => { - // verify - expect(err).equal(TEST_UI_ERROR); - expect(errorStub.args[0][0]).equal(TEST_UI_ERROR); - done(); - }); - }); - }); - - describe('command handle - clone', () => { - let instance; - const TEST_CMD = { - profile: TEST_PROFILE, - hostedSkillId: TEST_HOSTED_SKILL_ID - }; - const TEST_LOCALE_CA = 'en-CA'; - - beforeEach(() => { - instance = new InitCommand(optionModel); - sinon.stub(AuthorizationController.prototype, 'tokenRefreshAndRead').callsArgWith(1); - sinon.stub(profileHelper, 'runtimeProfile').returns(TEST_PROFILE); - }); - - afterEach(() => { - sinon.restore(); - }); - - it('| hosted skill controller updateAskSystemScripts fails, expect error thrown', (done) => { - // setup - const TEST_FOLDER_NAME = 'TEST_FOLDER_NAME'; - const GET_MANIFEST_RESPONSE = { - statusCode: 200, - headers: {}, - body: { - manifest: { - publishingInformation: { - locales: { - [TEST_LOCALE_CA]: { - name: TEST_SKILL_NAME - } - } - } - } - } - }; - sinon.stub(httpClient, 'request').callsArgWith(3, null, GET_MANIFEST_RESPONSE); // stub getManifest request - sinon.stub(ui, 'getProjectFolderName').callsArgWith(1, null, TEST_FOLDER_NAME); - sinon.stub(HostedSkillController.prototype, 'updateAskSystemScripts').callsArgWith(0, TEST_ERROR); - // call - instance.handle(TEST_CMD, (err) => { - // verify - expect(err).equal(TEST_ERROR); - expect(errorStub.args[0][0]).equal(TEST_ERROR); - done(); - }); - }); - - it('| hosted skill controller clone fails, expect error thrown', (done) => { - // setup - const TEST_FOLDER_NAME = 'TEST_FOLDER_NAME'; - const GET_MANIFEST_RESPONSE = { - statusCode: 200, - headers: {}, - body: { - manifest: { - publishingInformation: { - locales: { - [TEST_LOCALE_CA]: { - name: TEST_SKILL_NAME - } - } - } - } - } - }; - sinon.stub(httpClient, 'request').callsArgWith(3, null, GET_MANIFEST_RESPONSE); // stub getManifest request - sinon.stub(ui, 'getProjectFolderName').callsArgWith(1, null, TEST_FOLDER_NAME); - sinon.stub(HostedSkillController.prototype, 'updateAskSystemScripts').callsArgWith(0, null); - sinon.stub(HostedSkillController.prototype, 'clone').callsArgWith(3, TEST_ERROR); - // call - instance.handle(TEST_CMD, (err) => { - // verify - expect(err).equal(TEST_ERROR); - expect(errorStub.args[0][0]).equal(TEST_ERROR); - done(); - }); - }); - - it('| downloadAskScripts fails, expect error thrown', (done) => { - // setup - const TEST_FOLDER_NAME = 'TEST_FOLDER_NAME'; - const TEST_LOCALE = 'en-US'; - const GET_MANIFEST_RESPONSE = { - statusCode: 200, - headers: {}, - body: { - manifest: { - publishingInformation: { - locales: { - [TEST_LOCALE]: { - name: TEST_SKILL_NAME - } - } - } - } - } - }; - sinon.stub(httpClient, 'request').callsArgWith(3, null, GET_MANIFEST_RESPONSE); // stub getManifest request - sinon.stub(ui, 'getProjectFolderName').callsArgWith(1, null, TEST_FOLDER_NAME); - sinon.stub(HostedSkillController.prototype, 'updateAskSystemScripts').callsArgWith(0, null); - sinon.stub(HostedSkillController.prototype, 'clone').callsArgWith(3, null); - sinon.stub(HostedSkillController.prototype, 'updateSkillPrePushScript').callsArgWith(1, TEST_ERROR); - // call - instance.handle(TEST_CMD, (err) => { - // verify - expect(err).equal(TEST_ERROR); - expect(errorStub.args[0][0]).equal(TEST_ERROR); - done(); - }); - }); - - it('| hosted skill controller clone succeed, expect project initialized', (done) => { - // setup - const TEST_FOLDER_NAME = 'TEST_FOLDER_NAME'; - const TEST_LOCALE = 'en-US'; - const GET_MANIFEST_RESPONSE = { - statusCode: 200, - headers: {}, - body: { - manifest: { - publishingInformation: { - locales: { - [TEST_LOCALE]: { - name: TEST_SKILL_NAME - } - } - } - } - } - }; - sinon.stub(httpClient, 'request').callsArgWith(3, null, GET_MANIFEST_RESPONSE); // stub getManifest request - sinon.stub(ui, 'getProjectFolderName').callsArgWith(1, null, TEST_FOLDER_NAME); - sinon.stub(HostedSkillController.prototype, 'updateAskSystemScripts').callsArgWith(0, null); - sinon.stub(HostedSkillController.prototype, 'clone').callsArgWith(3, null); - sinon.stub(HostedSkillController.prototype, 'updateSkillPrePushScript').callsArgWith(1, null); - // call - instance.handle(TEST_CMD, (err) => { - // verify - expect(err).equal(undefined); - expect(Messenger.getInstance().info.args[0][0]).equal(`\n${TEST_SKILL_NAME} successfully initialized.\n`); - done(); - }); - }); - }); -}); diff --git a/test/unit/commands/init/index-test.ts b/test/unit/commands/init/index-test.ts new file mode 100644 index 00000000..b500222f --- /dev/null +++ b/test/unit/commands/init/index-test.ts @@ -0,0 +1,568 @@ +import {expect} from "chai"; +import sinon from "sinon"; +import AuthorizationController from "../../../../lib/controllers/authorization-controller"; +import InitCommand from "../../../../lib/commands/init"; +import helper from "../../../../lib/commands/init/helper"; +import HostedSkillController from "../../../../lib/controllers/hosted-skill-controller"; +import httpClient from "../../../../lib/clients/http-client"; +import CliWarn from "../../../../lib/exceptions/cli-warn"; +import jsonView from "../../../../lib/view/json-view"; +import optionModel from "../../../../lib/commands/option-model.json"; +import Messenger from "../../../../lib/view/messenger"; +import profileHelper from "../../../../lib/utils/profile-helper"; +import ui from "../../../../lib/commands/init/ui"; +import {OptionModel} from "../../../../lib/commands/option-validator"; + +describe("Commands init test - command class test", () => { + const TEST_PROFILE = "default"; + const TEST_ERROR = Error("init error"); + const TEST_WARN = new CliWarn("init warn"); + const TEST_SKILL_ID = "skillId"; + const TEST_SKILL_NAME = "TEST_SKILL_NAME"; + const TEST_SRC = "src"; + const TEST_SKILL_META = {src: TEST_SRC}; + const TEST_SKILL_CODE = {src: TEST_SRC}; + const TEST_SKILL_INFRA = {}; + const TEST_HOSTED_SKILL_ID = "hosted skill id"; + + let infoStub: sinon.SinonStub; + let errorStub: sinon.SinonStub; + let warnStub: sinon.SinonStub; + + beforeEach(() => { + infoStub = sinon.stub(); + errorStub = sinon.stub(); + warnStub = sinon.stub(); + sinon.stub(Messenger, "getInstance").returns({ + info: infoStub, + error: errorStub, + warn: warnStub, + }); + }); + + afterEach(() => { + sinon.restore(); + }); + + it("| validate command information is set correctly", () => { + const instance = new InitCommand(optionModel as OptionModel); + expect(instance.name()).equal("init"); + expect(instance.description()).equal("setup a new or existing Alexa skill project"); + expect(instance.requiredOptions()).deep.equal([]); + expect(instance.optionalOptions()).deep.equal(["hosted-skill-id", "profile", "debug"]); + }); + + describe("validate command handle", () => { + describe("command handle - pre init check", () => { + let instance: InitCommand; + let profileHelperStub: sinon.SinonStub; + + beforeEach(() => { + instance = new InitCommand(optionModel as OptionModel); + profileHelperStub = sinon.stub(profileHelper, "runtimeProfile").returns(TEST_PROFILE); + }); + + afterEach(() => { + sinon.restore(); + }); + + it("| when profile is not correct, expect throw error", async () => { + // setup + const TEST_CMD = { + profile: TEST_PROFILE, + }; + profileHelperStub.throws(TEST_ERROR); + // call + await expect(instance.handle(TEST_CMD)).rejectedWith(TEST_ERROR); + // verify + expect(errorStub).calledOnceWith(TEST_ERROR); + expect(infoStub).not.called; + expect(warnStub).not.called; + }); + + it("| when pre init check fails, expect throw error", async () => { + // setup + const TEST_CMD = { + profile: TEST_PROFILE, + }; + sinon.stub(helper, "preInitCheck").callsArgWith(2, TEST_ERROR); + // call + await expect(instance.handle(TEST_CMD)).rejectedWith(TEST_ERROR); + // verify + expect(errorStub).calledOnceWith(TEST_ERROR); + expect(infoStub).not.called; + expect(warnStub).not.called; + }); + + it("| when pre init check returns CliWarn, expect provide users warnings", async () => { + // setup + const TEST_CMD = { + profile: TEST_PROFILE, + }; + sinon.stub(helper, "preInitCheck").callsArgWith(2, TEST_WARN); + // call + await expect(instance.handle(TEST_CMD)).rejectedWith(TEST_WARN); + // verify + expect(warnStub).calledOnceWith(TEST_WARN.message); + expect(infoStub).not.called; + expect(errorStub).not.called; + }); + }); + + describe("command handle - collect ask resources", () => { + let instance: InitCommand; + + let helperGetSkillIdUserInputStub: sinon.SinonStub; + let helperGetSkillMetadataUserInput: sinon.SinonStub; + let helperGetSkillCodeUserInput: sinon.SinonStub; + let helperPreviewAndWriteAskResources: sinon.SinonStub; + let helperGetSkillInfraUserInput: sinon.SinonStub; + + beforeEach(() => { + instance = new InitCommand(optionModel as OptionModel); + sinon.stub(profileHelper, "runtimeProfile").returns(TEST_PROFILE); + sinon.stub(helper, "preInitCheck").callsArgWith(2); + helperGetSkillIdUserInputStub = sinon.stub(helper, "getSkillIdUserInput"); + helperGetSkillMetadataUserInput = sinon.stub(helper, "getSkillMetadataUserInput"); + helperGetSkillCodeUserInput = sinon.stub(helper, "getSkillCodeUserInput"); + helperGetSkillInfraUserInput = sinon.stub(helper, "getSkillInfraUserInput"); + helperPreviewAndWriteAskResources = sinon.stub(helper, "previewAndWriteAskResources").callsArgWith(3, TEST_ERROR); + }); + + afterEach(() => { + sinon.restore(); + }); + + it("| when collect skill id fails, expect throw error", async () => { + // setup + const TEST_CMD = { + profile: TEST_PROFILE, + }; + helperGetSkillIdUserInputStub.callsArgWith(0, TEST_ERROR); + // call + await expect(instance.handle(TEST_CMD)).rejectedWith(TEST_ERROR); + // verify + expect(errorStub).calledOnceWith(TEST_ERROR); + expect(infoStub).not.called; + expect(warnStub).not.called; + }); + + it("| when collect skill meta src fails, expect throw error", async () => { + // setup + const TEST_CMD = { + profile: TEST_PROFILE, + }; + helperGetSkillIdUserInputStub.callsArgWith(0, null, TEST_SKILL_ID); + helperGetSkillMetadataUserInput.callsArgWith(0, TEST_ERROR); + // call + await expect(instance.handle(TEST_CMD)).rejectedWith(TEST_ERROR); + // verify + expect(errorStub).calledOnceWith(TEST_ERROR); + expect(infoStub).not.called; + expect(warnStub).not.called; + }); + + it("| when collect skill code src fails, expect throw error", async () => { + // setup + const TEST_CMD = { + profile: TEST_PROFILE, + }; + helperGetSkillIdUserInputStub.callsArgWith(0, null, TEST_SKILL_ID); + helperGetSkillMetadataUserInput.callsArgWith(0, null, TEST_SKILL_META); + helperGetSkillCodeUserInput.callsArgWith(0, TEST_ERROR); + // call + await expect(instance.handle(TEST_CMD)).rejectedWith(TEST_ERROR); + // verify + expect(errorStub).calledOnceWith(TEST_ERROR); + expect(infoStub).not.called; + expect(warnStub).not.called; + }); + + it("| when collect skill code src is not provided, callback without continuing", async () => { + // setup + const TEST_CMD = { + profile: TEST_PROFILE, + }; + helperGetSkillIdUserInputStub.callsArgWith(0, null, TEST_SKILL_ID); + helperGetSkillMetadataUserInput.callsArgWith(0, null, TEST_SKILL_META); + helperGetSkillCodeUserInput.callsArgWith(0, null, null); + // call + await expect(instance.handle(TEST_CMD)).rejectedWith(TEST_ERROR); + // verify + expect(errorStub).calledOnceWith(TEST_ERROR); + expect(infoStub).not.called; + expect(warnStub).not.called; + + expect(helperPreviewAndWriteAskResources.getCall(0).args[1]).deep.equal({ + skillId: TEST_SKILL_ID, + skillMeta: { + src: TEST_SRC, + }, + }); + }); + + it("| when collect skill infra fails, expect throw error", async () => { + // setup + const TEST_CMD = { + profile: TEST_PROFILE, + }; + helperGetSkillIdUserInputStub.callsArgWith(0, null, TEST_SKILL_ID); + helperGetSkillMetadataUserInput.callsArgWith(0, null, TEST_SKILL_META); + helperGetSkillCodeUserInput.callsArgWith(0, null, TEST_SKILL_CODE); + helperGetSkillInfraUserInput.callsArgWith(0, TEST_ERROR); + // call + await expect(instance.handle(TEST_CMD)).rejectedWith(TEST_ERROR); + // verify + expect(errorStub).calledOnceWith(TEST_ERROR); + expect(infoStub).not.called; + expect(warnStub).not.called; + }); + + it("| when collect skill info all succeed, expect it passes correct user input", async () => { + // setup + const TEST_CMD = { + profile: TEST_PROFILE, + }; + helperGetSkillIdUserInputStub.callsArgWith(0, null, TEST_SKILL_ID); + helperGetSkillMetadataUserInput.callsArgWith(0, null, TEST_SKILL_META); + helperGetSkillCodeUserInput.callsArgWith(0, null, TEST_SKILL_CODE); + helperGetSkillInfraUserInput.callsArgWith(0, null, TEST_SKILL_INFRA); + // call + await expect(instance.handle(TEST_CMD)).rejectedWith(TEST_ERROR); + // verify + expect(errorStub).calledOnceWith(TEST_ERROR); + expect(infoStub).not.called; + expect(warnStub).not.called; + + expect(helperPreviewAndWriteAskResources.getCall(0).args[1]).deep.equal({ + skillId: TEST_SKILL_ID, + skillMeta: TEST_SKILL_META, + skillCode: TEST_SKILL_CODE, + skillInfra: TEST_SKILL_INFRA, + }); + }); + }); + + describe("command handle - post user input logics", () => { + let instance: InitCommand; + + let helperPreviewAndWriteAskResources: sinon.SinonStub; + let helperBootstrapSkillInfra: sinon.SinonStub; + + beforeEach(() => { + instance = new InitCommand(optionModel as OptionModel); + sinon.stub(profileHelper, "runtimeProfile").returns(TEST_PROFILE); + sinon.stub(helper, "preInitCheck").callsArgWith(2); + sinon.stub(helper, "getSkillIdUserInput").callsArgWith(0, null, TEST_SKILL_ID); + sinon.stub(helper, "getSkillMetadataUserInput").callsArgWith(0, null, TEST_SKILL_META); + sinon.stub(helper, "getSkillCodeUserInput").callsArgWith(0, null, TEST_SKILL_CODE); + sinon.stub(helper, "getSkillInfraUserInput").callsArgWith(0, null, TEST_SKILL_INFRA); + + helperPreviewAndWriteAskResources = sinon.stub(helper, "previewAndWriteAskResources"); + helperBootstrapSkillInfra = sinon.stub(helper, "bootstrapSkillInfra"); + }); + + afterEach(() => { + sinon.restore(); + }); + + it("| when preview and write fails, expect throws error", async () => { + // setup + const TEST_CMD = { + profile: TEST_PROFILE, + }; + helperPreviewAndWriteAskResources.callsArgWith(3, TEST_ERROR); + // call + await expect(instance.handle(TEST_CMD)).rejectedWith(TEST_ERROR); + // verify + expect(errorStub).calledOnceWith(TEST_ERROR); + expect(infoStub).not.called; + expect(warnStub).not.called; + }); + + it("| when preview and write returns CliWarn, expect display warnings", async () => { + // setup + const TEST_CMD = { + profile: TEST_PROFILE, + }; + helperPreviewAndWriteAskResources.callsArgWith(3, TEST_WARN); + // call + await expect(instance.handle(TEST_CMD)).rejectedWith(TEST_WARN); + // verify + expect(warnStub).calledOnceWith(TEST_WARN.message); + expect(infoStub).not.called; + expect(errorStub).not.called; + }); + + it("| when post init executions fails, expect throws error", async () => { + // setup + const TEST_CMD = { + profile: TEST_PROFILE, + }; + helperPreviewAndWriteAskResources.callsArgWith(3); + helperBootstrapSkillInfra.callsArgWith(3, TEST_ERROR); + // call + await expect(instance.handle(TEST_CMD)).rejectedWith(TEST_ERROR); + // verify + expect(errorStub).calledOnceWith(TEST_ERROR); + expect(infoStub).not.called; + expect(warnStub).not.called; + }); + + it("| when all the steps succeed, expect seeing success message", async () => { + // setup + const TEST_CMD = { + profile: TEST_PROFILE, + }; + helperPreviewAndWriteAskResources.callsArgWith(3); + helperBootstrapSkillInfra.callsArgWith(3); + // call + await instance.handle(TEST_CMD); + // verify + expect(infoStub).calledOnceWith('\nSuccess! Run "ask deploy" to deploy your skill.'); + expect(errorStub).not.called; + expect(warnStub).not.called; + }); + }); + }); + + describe("command handle - get skill name", () => { + let instance: InitCommand; + const TEST_CMD = { + profile: TEST_PROFILE, + hostedSkillId: TEST_HOSTED_SKILL_ID, + }; + + beforeEach(() => { + instance = new InitCommand(optionModel as OptionModel); + sinon.stub(AuthorizationController.prototype, "tokenRefreshAndRead").callsArgWith(1); + sinon.stub(profileHelper, "runtimeProfile").returns(TEST_PROFILE); + }); + + afterEach(() => { + sinon.restore(); + }); + + it("| get skill manifest fails, expect error thrown", async () => { + // setup + sinon.stub(httpClient, "request").callsArgWith(3, TEST_ERROR); // stub getManifest request + // call + await expect(instance.handle(TEST_CMD)).rejectedWith(TEST_ERROR); + // verify + expect(errorStub).calledOnceWith(TEST_ERROR); + }); + + it("| get skill manifest response with status code >= 300, expect error thrown", async () => { + // setup + const GET_MANIFEST_ERROR = { + statusCode: 403, + body: { + error: TEST_ERROR, + }, + }; + sinon.stub(httpClient, "request").callsArgWith(3, null, GET_MANIFEST_ERROR); // stub getManifest request + // call + await expect(instance.handle(TEST_CMD)).rejectedWith(jsonView.toString({error: TEST_ERROR})); + // verify + expect(errorStub).calledOnceWith(jsonView.toString({error: TEST_ERROR})); + }); + + it("| get skill manifest succeed without locales, expect error thrown", async () => { + // setup + const TEST_NO_FOUND_ERROR = "No skill name found."; + const GET_MANIFEST_RESPONSE_NO_LOCALES = { + statusCode: 200, + headers: {}, + body: { + manifest: { + publishingInformation: {}, + }, + }, + }; + sinon.stub(httpClient, "request").callsArgWith(3, null, GET_MANIFEST_RESPONSE_NO_LOCALES); // stub getManifest request + // call + await expect(instance.handle(TEST_CMD)).rejectedWith(TEST_NO_FOUND_ERROR); + // verify + expect(errorStub).calledOnceWith(TEST_NO_FOUND_ERROR); + }); + }); + + describe("command handle - confirm project folder name", () => { + let instance: InitCommand; + const TEST_CMD = { + profile: TEST_PROFILE, + hostedSkillId: TEST_HOSTED_SKILL_ID, + }; + const TEST_LOCALE = "en-US"; + + beforeEach(() => { + instance = new InitCommand(optionModel as OptionModel); + sinon.stub(AuthorizationController.prototype, "tokenRefreshAndRead").callsArgWith(1); + sinon.stub(profileHelper, "runtimeProfile").returns(TEST_PROFILE); + }); + + afterEach(() => { + sinon.restore(); + }); + + it("| get project name, ui get project folder name fails, expect error thrown", async () => { + // setup + const GET_MANIFEST_RESPONSE = { + statusCode: 200, + headers: {}, + body: { + manifest: { + publishingInformation: { + locales: { + [TEST_LOCALE]: { + name: TEST_SKILL_NAME, + }, + }, + }, + }, + }, + }; + const TEST_UI_ERROR = "TEST_UI_ERROR"; + sinon.stub(httpClient, "request").callsArgWith(3, null, GET_MANIFEST_RESPONSE); // stub getManifest request + sinon.stub(ui, "getProjectFolderName").callsArgWith(1, TEST_UI_ERROR); + // call + await expect(instance.handle(TEST_CMD)).rejectedWith(TEST_UI_ERROR); + // verify + expect(errorStub).calledOnceWith(TEST_UI_ERROR); + }); + }); + + describe("command handle - clone", () => { + let instance: InitCommand; + const TEST_CMD = { + profile: TEST_PROFILE, + hostedSkillId: TEST_HOSTED_SKILL_ID, + }; + const TEST_LOCALE_CA = "en-CA"; + + beforeEach(() => { + instance = new InitCommand(optionModel as OptionModel); + sinon.stub(AuthorizationController.prototype, "tokenRefreshAndRead").callsArgWith(1); + sinon.stub(profileHelper, "runtimeProfile").returns(TEST_PROFILE); + }); + + afterEach(() => { + sinon.restore(); + }); + + it("| hosted skill controller updateAskSystemScripts fails, expect error thrown", async () => { + // setup + const TEST_FOLDER_NAME = "TEST_FOLDER_NAME"; + const GET_MANIFEST_RESPONSE = { + statusCode: 200, + headers: {}, + body: { + manifest: { + publishingInformation: { + locales: { + [TEST_LOCALE_CA]: { + name: TEST_SKILL_NAME, + }, + }, + }, + }, + }, + }; + sinon.stub(httpClient, "request").callsArgWith(3, null, GET_MANIFEST_RESPONSE); // stub getManifest request + sinon.stub(ui, "getProjectFolderName").callsArgWith(1, null, TEST_FOLDER_NAME); + sinon.stub(HostedSkillController.prototype, "updateAskSystemScripts").callsArgWith(0, TEST_ERROR); + // call + await expect(instance.handle(TEST_CMD)).rejectedWith(TEST_ERROR); + // verify + expect(errorStub).calledOnceWith(TEST_ERROR); + }); + + it("| hosted skill controller clone fails, expect error thrown", async () => { + // setup + const TEST_FOLDER_NAME = "TEST_FOLDER_NAME"; + const GET_MANIFEST_RESPONSE = { + statusCode: 200, + headers: {}, + body: { + manifest: { + publishingInformation: { + locales: { + [TEST_LOCALE_CA]: { + name: TEST_SKILL_NAME, + }, + }, + }, + }, + }, + }; + sinon.stub(httpClient, "request").callsArgWith(3, null, GET_MANIFEST_RESPONSE); // stub getManifest request + sinon.stub(ui, "getProjectFolderName").callsArgWith(1, null, TEST_FOLDER_NAME); + sinon.stub(HostedSkillController.prototype, "updateAskSystemScripts").callsArgWith(0, null); + sinon.stub(HostedSkillController.prototype, "clone").callsArgWith(3, TEST_ERROR); + // call + await expect(instance.handle(TEST_CMD)).rejectedWith(TEST_ERROR); + // verify + expect(errorStub).calledOnceWith(TEST_ERROR); + }); + + it("| downloadAskScripts fails, expect error thrown", async () => { + // setup + const TEST_FOLDER_NAME = "TEST_FOLDER_NAME"; + const TEST_LOCALE = "en-US"; + const GET_MANIFEST_RESPONSE = { + statusCode: 200, + headers: {}, + body: { + manifest: { + publishingInformation: { + locales: { + [TEST_LOCALE]: { + name: TEST_SKILL_NAME, + }, + }, + }, + }, + }, + }; + sinon.stub(httpClient, "request").callsArgWith(3, null, GET_MANIFEST_RESPONSE); // stub getManifest request + sinon.stub(ui, "getProjectFolderName").callsArgWith(1, null, TEST_FOLDER_NAME); + sinon.stub(HostedSkillController.prototype, "updateAskSystemScripts").callsArgWith(0, null); + sinon.stub(HostedSkillController.prototype, "clone").callsArgWith(3, null); + sinon.stub(HostedSkillController.prototype, "updateSkillPrePushScript").callsArgWith(1, TEST_ERROR); + // call + await expect(instance.handle(TEST_CMD)).rejectedWith(TEST_ERROR); + // verify + expect(errorStub).calledOnceWith(TEST_ERROR); + }); + + it("| hosted skill controller clone succeed, expect project initialized", async () => { + // setup + const TEST_FOLDER_NAME = "TEST_FOLDER_NAME"; + const TEST_LOCALE = "en-US"; + const GET_MANIFEST_RESPONSE = { + statusCode: 200, + headers: {}, + body: { + manifest: { + publishingInformation: { + locales: { + [TEST_LOCALE]: { + name: TEST_SKILL_NAME, + }, + }, + }, + }, + }, + }; + sinon.stub(httpClient, "request").callsArgWith(3, null, GET_MANIFEST_RESPONSE); // stub getManifest request + sinon.stub(ui, "getProjectFolderName").callsArgWith(1, null, TEST_FOLDER_NAME); + sinon.stub(HostedSkillController.prototype, "updateAskSystemScripts").callsArgWith(0, null); + sinon.stub(HostedSkillController.prototype, "clone").callsArgWith(3, null); + sinon.stub(HostedSkillController.prototype, "updateSkillPrePushScript").callsArgWith(1, null); + // call + await instance.handle(TEST_CMD); + // verify + expect(infoStub).calledOnceWith(`\n${TEST_SKILL_NAME} successfully initialized.\n`); + }); + }); +}); diff --git a/test/unit/commands/init/ui-test.js b/test/unit/commands/init/ui-test.js index 695790cd..7ed765d5 100644 --- a/test/unit/commands/init/ui-test.js +++ b/test/unit/commands/init/ui-test.js @@ -1,368 +1,365 @@ -const { expect } = require('chai'); -const fs = require('fs'); -const inquirer = require('inquirer'); -const path = require('path'); -const sinon = require('sinon'); +const {expect} = require("chai"); +const fs = require("fs"); +const inquirer = require("inquirer"); +const path = require("path"); +const sinon = require("sinon"); -const CONSTANTS = require('@src/utils/constants'); -const Messenger = require('@src/view/messenger'); -const JsonView = require('@src/view/json-view'); +const CONSTANTS = require("../../../../lib/utils/constants"); +const Messenger = require("../../../../lib/view/messenger"); +const JsonView = require("../../../../lib/view/json-view"); -const ui = require('@src/commands/init/ui'); +const ui = require("../../../../lib/commands/init/ui"); function validateInquirerConfig(stub, expectedConfig) { - const { message, type, defaultValue, choices } = expectedConfig; - expect(stub.message).equal(message); - expect(stub.type).equal(type); - if (defaultValue) { - expect(stub.default).equal(defaultValue); - } - if (choices) { - expect(stub.choices).deep.equal(choices); - } + const {message, type, defaultValue, choices} = expectedConfig; + expect(stub.message).equal(message); + expect(stub.type).equal(type); + if (defaultValue) { + expect(stub.default).equal(defaultValue); + } + if (choices) { + expect(stub.choices).deep.equal(choices); + } } -describe('Commands init - UI test', () => { - const TEST_PROFILE = 'profile'; - const TEST_ERROR = 'init error'; +describe("Commands init - UI test", () => { + const TEST_PROFILE = "profile"; + const TEST_ERROR = "init error"; - new Messenger({}); - let infoStub; + new Messenger({}); + let infoStub; - describe('# validate ui.showInitInstruction', () => { - beforeEach(() => { - infoStub = sinon.stub(); - sinon.stub(Messenger, 'getInstance').returns({ - info: infoStub - }); - }); + describe("# validate ui.showInitInstruction", () => { + beforeEach(() => { + infoStub = sinon.stub(); + sinon.stub(Messenger, "getInstance").returns({ + info: infoStub, + }); + }); - afterEach(() => { - sinon.restore(); - }); + afterEach(() => { + sinon.restore(); + }); - it('| showInitInstruction display by messenger info', () => { - // call - ui.showInitInstruction(TEST_PROFILE); - // verify - expect(infoStub.args[0][0].includes(TEST_PROFILE)).equal(true); - }); + it("| showInitInstruction display by messenger info", () => { + // call + ui.showInitInstruction(TEST_PROFILE); + // verify + expect(infoStub.args[0][0].includes(TEST_PROFILE)).equal(true); }); + }); - describe('# validate ui.confirmOverwrite', () => { - beforeEach(() => { - sinon.stub(inquirer, 'prompt'); - }); + describe("# validate ui.confirmOverwrite", () => { + beforeEach(() => { + sinon.stub(inquirer, "prompt"); + }); - afterEach(() => { - sinon.restore(); - }); + afterEach(() => { + sinon.restore(); + }); - it('| confirm overwrite from user but error happens', (done) => { - // setup - inquirer.prompt.rejects(TEST_ERROR); - // call - ui.confirmOverwrite((err, response) => { - // verify - validateInquirerConfig(inquirer.prompt.args[0][0][0], { - message: `${CONSTANTS.FILE_PATH.ASK_RESOURCES_JSON_CONFIG} already exists in current directory. Do you want to overwrite it? `, - type: 'confirm', - default: true, - }); - expect(err.name).equal(TEST_ERROR); - expect(response).equal(undefined); - done(); - }); + it("| confirm overwrite from user but error happens", (done) => { + // setup + inquirer.prompt.rejects(TEST_ERROR); + // call + ui.confirmOverwrite((err, response) => { + // verify + validateInquirerConfig(inquirer.prompt.args[0][0][0], { + message: `${CONSTANTS.FILE_PATH.ASK_RESOURCES_JSON_CONFIG} already exists in current directory. Do you want to overwrite it? `, + type: "confirm", + default: true, }); + expect(err.name).equal(TEST_ERROR); + expect(response).equal(undefined); + done(); + }); + }); - it('| confirm overwrite from user inputs', (done) => { - // setup - inquirer.prompt.resolves({ isOverwriteConfirmed: true }); - // call - ui.confirmOverwrite((err, response) => { - // verify - expect(err).equal(null); - expect(response).equal(true); - done(); - }); - }); + it("| confirm overwrite from user inputs", (done) => { + // setup + inquirer.prompt.resolves({isOverwriteConfirmed: true}); + // call + ui.confirmOverwrite((err, response) => { + // verify + expect(err).equal(null); + expect(response).equal(true); + done(); + }); }); + }); - describe('# validate ui.getSkillId', () => { - beforeEach(() => { - sinon.stub(inquirer, 'prompt'); - }); + describe("# validate ui.getSkillId", () => { + beforeEach(() => { + sinon.stub(inquirer, "prompt"); + }); - afterEach(() => { - sinon.restore(); - }); + afterEach(() => { + sinon.restore(); + }); - it('| get skillId but error happens', (done) => { - // setup - inquirer.prompt.rejects(TEST_ERROR); - // call - ui.getSkillId((err, response) => { - // verify - validateInquirerConfig(inquirer.prompt.args[0][0][0], { - message: 'Skill Id (leave empty to create one): ', - type: 'input', - name: 'skillId' - }); - expect(err.name).equal(TEST_ERROR); - expect(response).equal(undefined); - done(); - }); + it("| get skillId but error happens", (done) => { + // setup + inquirer.prompt.rejects(TEST_ERROR); + // call + ui.getSkillId((err, response) => { + // verify + validateInquirerConfig(inquirer.prompt.args[0][0][0], { + message: "Skill Id (leave empty to create one): ", + type: "input", + name: "skillId", }); + expect(err.name).equal(TEST_ERROR); + expect(response).equal(undefined); + done(); + }); + }); - it('| get skillId with user input succeeds', (done) => { - // setup - inquirer.prompt.resolves({ skillId: ' skill ' }); - // call - ui.getSkillId((err, response) => { - // verify - expect(err).equal(null); - expect(response).equal('skill'); - done(); - }); - }); + it("| get skillId with user input succeeds", (done) => { + // setup + inquirer.prompt.resolves({skillId: " skill "}); + // call + ui.getSkillId((err, response) => { + // verify + expect(err).equal(null); + expect(response).equal("skill"); + done(); + }); }); + }); - describe('# validate ui.getSkillMetaSrc', () => { - beforeEach(() => { - sinon.stub(inquirer, 'prompt'); - }); + describe("# validate ui.getSkillMetaSrc", () => { + beforeEach(() => { + sinon.stub(inquirer, "prompt"); + }); - afterEach(() => { - sinon.restore(); - }); + afterEach(() => { + sinon.restore(); + }); - it('| get skillMeta src but error happens', (done) => { - // setup - inquirer.prompt.rejects(TEST_ERROR); - // call - ui.getSkillMetaSrc((err, response) => { - // verify - validateInquirerConfig(inquirer.prompt.args[0][0][0], { - message: 'Skill package path: ', - type: 'input', - default: './skill-package', - }); - expect(err.name).equal(TEST_ERROR); - expect(response).equal(undefined); - done(); - }); + it("| get skillMeta src but error happens", (done) => { + // setup + inquirer.prompt.rejects(TEST_ERROR); + // call + ui.getSkillMetaSrc((err, response) => { + // verify + validateInquirerConfig(inquirer.prompt.args[0][0][0], { + message: "Skill package path: ", + type: "input", + default: "./skill-package", }); + expect(err.name).equal(TEST_ERROR); + expect(response).equal(undefined); + done(); + }); + }); - it('| get skillMeta src with user input succeeds', (done) => { - // setup - sinon.stub(fs, 'existsSync').returns(true); - inquirer.prompt.resolves({ skillMetaSrc: 'src' }); - // call - ui.getSkillMetaSrc((err, response) => { - // verify - expect(inquirer.prompt.args[0][0][0].validate('src')).equal(true); - expect(err).equal(null); - expect(response).equal('src'); - done(); - }); - }); + it("| get skillMeta src with user input succeeds", (done) => { + // setup + sinon.stub(fs, "existsSync").returns(true); + inquirer.prompt.resolves({skillMetaSrc: "src"}); + // call + ui.getSkillMetaSrc((err, response) => { + // verify + expect(inquirer.prompt.args[0][0][0].validate("src")).equal(true); + expect(err).equal(null); + expect(response).equal("src"); + done(); + }); + }); - it('| check the validate logic from inquirer and path is empty', (done) => { - // setup - inquirer.prompt.resolves({ skillMetaSrc: 'src' }); - // call - ui.getSkillMetaSrc(() => { - // verify - expect(inquirer.prompt.args[0][0][0].validate(' ')) - .equal('Path for skill package cannot be empty.'); - done(); - }); - }); + it("| check the validate logic from inquirer and path is empty", (done) => { + // setup + inquirer.prompt.resolves({skillMetaSrc: "src"}); + // call + ui.getSkillMetaSrc(() => { + // verify + expect(inquirer.prompt.args[0][0][0].validate(" ")).equal("Path for skill package cannot be empty."); + done(); + }); + }); - it('| check the validate logic from inquirer and file does not exist', (done) => { - // setup - sinon.stub(fs, 'existsSync').returns(false); - inquirer.prompt.resolves({ skillMetaSrc: 'src' }); - // call - ui.getSkillMetaSrc(() => { - // verify - expect(inquirer.prompt.args[0][0][0].validate('path')) - .equal('File path does not exist.'); - done(); - }); - }); + it("| check the validate logic from inquirer and file does not exist", (done) => { + // setup + sinon.stub(fs, "existsSync").returns(false); + inquirer.prompt.resolves({skillMetaSrc: "src"}); + // call + ui.getSkillMetaSrc(() => { + // verify + expect(inquirer.prompt.args[0][0][0].validate("path")).equal("File path does not exist."); + done(); + }); }); + }); - describe('# validate ui.getCodeSrcForRegion', () => { - const TEST_REGION = 'region'; + describe("# validate ui.getCodeSrcForRegion", () => { + const TEST_REGION = "region"; - beforeEach(() => { - sinon.stub(inquirer, 'prompt'); - }); + beforeEach(() => { + sinon.stub(inquirer, "prompt"); + }); - afterEach(() => { - sinon.restore(); - }); + afterEach(() => { + sinon.restore(); + }); - it('| ask for code source but error happens', (done) => { - // setup - inquirer.prompt.rejects(TEST_ERROR); - // call - ui.getCodeSrcForRegion(TEST_REGION, (err, response) => { - // verify - validateInquirerConfig(inquirer.prompt.args[0][0][0], { - message: `Lambda code path for ${TEST_REGION} region (leave empty to not deploy Lambda): `, - type: 'input', - default: './lambda', - }); - expect(err.name).equal(TEST_ERROR); - expect(response).equal(undefined); - done(); - }); + it("| ask for code source but error happens", (done) => { + // setup + inquirer.prompt.rejects(TEST_ERROR); + // call + ui.getCodeSrcForRegion(TEST_REGION, (err, response) => { + // verify + validateInquirerConfig(inquirer.prompt.args[0][0][0], { + message: `Lambda code path for ${TEST_REGION} region (leave empty to not deploy Lambda): `, + type: "input", + default: "./lambda", }); + expect(err.name).equal(TEST_ERROR); + expect(response).equal(undefined); + done(); + }); + }); - it('| ask for code source and succeeds', (done) => { - // setup - sinon.stub(fs, 'existsSync').returns(true); - inquirer.prompt.resolves({ skillCodeSrc: 'src' }); - // call - ui.getCodeSrcForRegion(TEST_REGION, (err, response) => { - // verify - expect(inquirer.prompt.args[0][0][0].validate('src')).equal(true); - expect(err).equal(null); - expect(response).equal('src'); - done(); - }); - }); + it("| ask for code source and succeeds", (done) => { + // setup + sinon.stub(fs, "existsSync").returns(true); + inquirer.prompt.resolves({skillCodeSrc: "src"}); + // call + ui.getCodeSrcForRegion(TEST_REGION, (err, response) => { + // verify + expect(inquirer.prompt.args[0][0][0].validate("src")).equal(true); + expect(err).equal(null); + expect(response).equal("src"); + done(); + }); + }); - it('| ask for code source and file path not exists', (done) => { - // setup - sinon.stub(fs, 'existsSync').returns(false); - inquirer.prompt.resolves({ skillCodeSrc: 'src' }); - // call - ui.getCodeSrcForRegion(TEST_REGION, () => { - // verify - expect(inquirer.prompt.args[0][0][0].validate('path')) - .equal('File path does not exist.'); - done(); - }); - }); + it("| ask for code source and file path not exists", (done) => { + // setup + sinon.stub(fs, "existsSync").returns(false); + inquirer.prompt.resolves({skillCodeSrc: "src"}); + // call + ui.getCodeSrcForRegion(TEST_REGION, () => { + // verify + expect(inquirer.prompt.args[0][0][0].validate("path")).equal("File path does not exist."); + done(); + }); }); + }); - describe('# validate ui.getSkillInfra', () => { - beforeEach(() => { - sinon.stub(inquirer, 'prompt'); - }); + describe("# validate ui.getSkillInfra", () => { + beforeEach(() => { + sinon.stub(inquirer, "prompt"); + }); - afterEach(() => { - sinon.restore(); - }); + afterEach(() => { + sinon.restore(); + }); - it('| get skillInfra but error happens', (done) => { - // setup - inquirer.prompt.rejects(TEST_ERROR); - // call - ui.getSkillInfra((err, response) => { - // verify - validateInquirerConfig(inquirer.prompt.args[0][0][0], { - message: 'Use AWS CloudFormation to deploy Lambda? ', - type: 'confirm', - default: true, - }); - validateInquirerConfig(inquirer.prompt.args[0][0][1], { - message: 'Lambda runtime: ', - type: 'input', - default: 'nodejs12.x', - }); - validateInquirerConfig(inquirer.prompt.args[0][0][2], { - message: 'Lambda handler: ', - type: 'input', - default: 'index.handler', - }); - expect(err.name).equal(TEST_ERROR); - expect(response).equal(undefined); - done(); - }); + it("| get skillInfra but error happens", (done) => { + // setup + inquirer.prompt.rejects(TEST_ERROR); + // call + ui.getSkillInfra((err, response) => { + // verify + validateInquirerConfig(inquirer.prompt.args[0][0][0], { + message: "Use AWS CloudFormation to deploy Lambda? ", + type: "confirm", + default: true, }); - - it('| get skillInfra with user input succeeds', (done) => { - // setup - const TEST_ANSWER = { - isUsingCfn: true, - runtime: 'runtime', - handler: 'handler' - }; - inquirer.prompt.resolves(TEST_ANSWER); - // call - ui.getSkillInfra((err, response) => { - // verify - expect(err).equal(null); - expect(response).deep.equal(TEST_ANSWER); - done(); - }); + validateInquirerConfig(inquirer.prompt.args[0][0][1], { + message: "Lambda runtime: ", + type: "input", + default: "nodejs12.x", + }); + validateInquirerConfig(inquirer.prompt.args[0][0][2], { + message: "Lambda handler: ", + type: "input", + default: "index.handler", }); + expect(err.name).equal(TEST_ERROR); + expect(response).equal(undefined); + done(); + }); }); - describe('# validate ui.showPreviewAndConfirm', () => { - const TEST_ROOT_PATH = 'root'; - const TEST_ASK_RESOURCES_JSON = 'resources json'; - const TEST_ASK_STATES_JSON = 'states json'; - const TEST_ASK_RESOURCES = 'resources'; - const TEST_ASK_STATES = 'states'; - const TEST_RESOURCES_COFNIG = { - askResources: TEST_ASK_RESOURCES, - askStates: TEST_ASK_STATES - }; - - beforeEach(() => { - infoStub = sinon.stub(); - sinon.stub(Messenger, 'getInstance').returns({ - info: infoStub - }); - sinon.stub(inquirer, 'prompt'); - sinon.stub(JsonView, 'toString'); - JsonView.toString.withArgs(TEST_ASK_RESOURCES).returns(TEST_ASK_RESOURCES_JSON); - JsonView.toString.withArgs(TEST_ASK_STATES).returns(TEST_ASK_STATES_JSON); - }); + it("| get skillInfra with user input succeeds", (done) => { + // setup + const TEST_ANSWER = { + isUsingCfn: true, + runtime: "runtime", + handler: "handler", + }; + inquirer.prompt.resolves(TEST_ANSWER); + // call + ui.getSkillInfra((err, response) => { + // verify + expect(err).equal(null); + expect(response).deep.equal(TEST_ANSWER); + done(); + }); + }); + }); + + describe("# validate ui.showPreviewAndConfirm", () => { + const TEST_ROOT_PATH = "root"; + const TEST_ASK_RESOURCES_JSON = "resources json"; + const TEST_ASK_STATES_JSON = "states json"; + const TEST_ASK_RESOURCES = "resources"; + const TEST_ASK_STATES = "states"; + const TEST_RESOURCES_COFNIG = { + askResources: TEST_ASK_RESOURCES, + askStates: TEST_ASK_STATES, + }; + + beforeEach(() => { + infoStub = sinon.stub(); + sinon.stub(Messenger, "getInstance").returns({ + info: infoStub, + }); + sinon.stub(inquirer, "prompt"); + sinon.stub(JsonView, "toString"); + JsonView.toString.withArgs(TEST_ASK_RESOURCES).returns(TEST_ASK_RESOURCES_JSON); + JsonView.toString.withArgs(TEST_ASK_STATES).returns(TEST_ASK_STATES_JSON); + }); - afterEach(() => { - sinon.restore(); - }); + afterEach(() => { + sinon.restore(); + }); - it('| show preview and ask for confirm but error happens', (done) => { - // setup - inquirer.prompt.rejects(TEST_ERROR); - // call - ui.showPreviewAndConfirm(TEST_ROOT_PATH, TEST_RESOURCES_COFNIG, (err, response) => { - // verify - validateInquirerConfig(inquirer.prompt.args[0][0][0], { - message: 'Does this look correct? ', - type: 'confirm', - default: true, - }); - expect(infoStub.args[0][0]).equal(` + it("| show preview and ask for confirm but error happens", (done) => { + // setup + inquirer.prompt.rejects(TEST_ERROR); + // call + ui.showPreviewAndConfirm(TEST_ROOT_PATH, TEST_RESOURCES_COFNIG, (err, response) => { + // verify + validateInquirerConfig(inquirer.prompt.args[0][0][0], { + message: "Does this look correct? ", + type: "confirm", + default: true, + }); + expect(infoStub.args[0][0]).equal(` Writing to ${path.join(TEST_ROOT_PATH, CONSTANTS.FILE_PATH.ASK_RESOURCES_JSON_CONFIG)}: ${TEST_ASK_RESOURCES_JSON} Writing to ${path.join(TEST_ROOT_PATH, CONSTANTS.FILE_PATH.HIDDEN_ASK_FOLDER, CONSTANTS.FILE_PATH.ASK_STATES_JSON_CONFIG)}: ${TEST_ASK_STATES_JSON} `); - expect(err.name).equal(TEST_ERROR); - expect(response).equal(undefined); - done(); - }); - }); + expect(err.name).equal(TEST_ERROR); + expect(response).equal(undefined); + done(); + }); + }); - it('| show preview and ask for confirm with user input succeeds', (done) => { - // setup - inquirer.prompt.resolves({ confirmPreview: true }); - // call - ui.showPreviewAndConfirm(TEST_ROOT_PATH, TEST_RESOURCES_COFNIG, (err, response) => { - // verify - expect(err).equal(null); - expect(response).equal(true); - done(); - }); - }); + it("| show preview and ask for confirm with user input succeeds", (done) => { + // setup + inquirer.prompt.resolves({confirmPreview: true}); + // call + ui.showPreviewAndConfirm(TEST_ROOT_PATH, TEST_RESOURCES_COFNIG, (err, response) => { + // verify + expect(err).equal(null); + expect(response).equal(true); + done(); + }); }); + }); }); diff --git a/test/unit/commands/new/helper-test.js b/test/unit/commands/new/helper-test.js deleted file mode 100644 index cf53a5c7..00000000 --- a/test/unit/commands/new/helper-test.js +++ /dev/null @@ -1,288 +0,0 @@ -const { expect } = require('chai'); -const fs = require('fs-extra'); -const path = require('path'); -const sinon = require('sinon'); - -const GitClient = require('@src/clients/git-client'); -const SkillInfrastructureController = require('@src/controllers/skill-infrastructure-controller'); -const helper = require('@src/commands/new/helper'); -const ResourcesConfig = require('@src/model/resources-config'); -const Manifest = require('@src/model/manifest'); -const stringUtils = require('@src/utils/string-utils'); -const CONSTANTS = require('@src/utils/constants'); - -describe('Commands new test - helper test', () => { - const FIXTURE_RESOURCES_CONFIG_FILE_PATH = path.join(process.cwd(), 'test', 'unit', 'fixture', 'model', 'regular-proj', 'ask-resources.json'); - const FIXTURE_MANIFEST_FILE_PATH = path.join(process.cwd(), 'test', 'unit', 'fixture', 'model', 'manifest.json'); - - const TEST_PROFILE = 'default'; - const TEST_DO_DEBUG = false; - const TEST_INFRA_PATH = 'infraPath'; - const TEST_DEPLOYMENT_TYPE = 'deployer'; - const TEST_TEMPLATE_URL = 'value'; - const TEST_SKILL_FOLDER_NAME = 'skillFolderName'; - const TEST_SKILL_NAME = 'skillName'; - const TEST_USER_INPUT = { - skillName: 'testName', - projectFolderName: 'projectName', - templateInfo: { - templateUrl: TEST_TEMPLATE_URL - } - }; - - describe('# test helper method - initializeDeployDelegate', () => { - beforeEach(() => { - new ResourcesConfig(FIXTURE_RESOURCES_CONFIG_FILE_PATH); - }); - - afterEach(() => { - ResourcesConfig.dispose(); - sinon.restore(); - }); - - it('| ui select deploy delegate pass and selection is opt-out, expect quit process', (done) => { - // setup - // call - helper.initializeDeployDelegate(null, TEST_INFRA_PATH, TEST_PROFILE, TEST_DO_DEBUG, (err, res) => { - // verify - expect(res).equal(undefined); - expect(err).equal(undefined); - done(); - }); - }); - - it('| deployer is set in the template and same as what user wants, expect skip bootstrap', (done) => { - // setup - ResourcesConfig.getInstance().setSkillInfraType(TEST_PROFILE, TEST_DEPLOYMENT_TYPE); - // call - helper.initializeDeployDelegate(TEST_DEPLOYMENT_TYPE, TEST_INFRA_PATH, TEST_PROFILE, TEST_DO_DEBUG, (err, res) => { - // verify - expect(res).equal(TEST_DEPLOYMENT_TYPE); - expect(err).equal(null); - done(); - }); - }); - - it('| bootstrap fails, expect throw error', (done) => { - // setup - const TEST_SELECTED_TYPE = '@ask-cli/test!!!@ '; - ResourcesConfig.getInstance().setSkillInfraType(TEST_PROFILE, ''); - sinon.stub(fs, 'ensureDirSync'); - sinon.stub(SkillInfrastructureController.prototype, 'bootstrapInfrastructures').callsArgWith(1, 'error'); - // call - helper.initializeDeployDelegate(TEST_SELECTED_TYPE, TEST_INFRA_PATH, TEST_PROFILE, TEST_DO_DEBUG, (err, res) => { - // verify - expect(fs.ensureDirSync.args[0][0]).equal(path.join(TEST_INFRA_PATH, 'infrastructure/test')); - expect(res).equal(undefined); - expect(err).equal('error'); - done(); - }); - }); - - it('| bootstrap pass, expect return deployType', (done) => { - // setup - const TEST_SELECTED_TYPE = ' !!!test^^^ '; - ResourcesConfig.getInstance().setSkillInfraType(TEST_PROFILE, ''); - sinon.stub(fs, 'ensureDirSync'); - sinon.stub(SkillInfrastructureController.prototype, 'bootstrapInfrastructures').callsArgWith(1); - // call - helper.initializeDeployDelegate(TEST_SELECTED_TYPE, TEST_INFRA_PATH, TEST_PROFILE, TEST_DO_DEBUG, (err, res) => { - // verify - expect(fs.ensureDirSync.args[0][0]).equal(path.join(TEST_INFRA_PATH, 'infrastructure/test')); - expect(res).equal(TEST_SELECTED_TYPE); - expect(err).equal(null); - done(); - }); - }); - }); - - describe('# test helper method - downloadTemplateFromGit', () => { - afterEach(() => { - sinon.restore(); - }); - - it('| git clone pass, expect return folder path', (done) => { - // setup - const TEST_FOLDER_PATH = 'TEST_FOLDER_PATH'; - sinon.stub(path, 'join').returns(TEST_FOLDER_PATH); - sinon.stub(GitClient.prototype, 'clone'); - // call - helper.downloadTemplateFromGit(TEST_USER_INPUT, TEST_DO_DEBUG, (err, res) => { - // verify - expect(GitClient.prototype.clone.args[0][0]).equal(TEST_TEMPLATE_URL); - expect(res).equal(TEST_FOLDER_PATH); - expect(err).equal(null); - done(); - }); - }); - it('| git clone with custom branch, expect return folder path', (done) => { - // setup - const TEST_FOLDER_PATH = 'TEST_FOLDER_PATH'; - const TEST_TEMPLATE_BRANCH = 'test-branch'; - TEST_USER_INPUT.templateInfo.templateBranch = TEST_TEMPLATE_BRANCH; - sinon.stub(path, 'join').returns(TEST_FOLDER_PATH); - sinon.stub(GitClient.prototype, 'clone'); - // call - helper.downloadTemplateFromGit(TEST_USER_INPUT, TEST_DO_DEBUG, (err, res) => { - // verify - expect(GitClient.prototype.clone.args[0][0]).equal(TEST_TEMPLATE_URL); - expect(GitClient.prototype.clone.args[0][1]).equal(TEST_TEMPLATE_BRANCH); - expect(res).equal(TEST_FOLDER_PATH); - expect(err).equal(null); - done(); - }); - }); - }); - - describe('# test helper method - loadSkillProjectModel', () => { - const TEST_SKILLMETA_SRC = './skillPackage'; - - beforeEach(() => { - sinon.stub(path, 'join').withArgs( - TEST_SKILL_FOLDER_NAME, CONSTANTS.FILE_PATH.ASK_RESOURCES_JSON_CONFIG - ).returns(FIXTURE_RESOURCES_CONFIG_FILE_PATH); - path.join.withArgs(TEST_SKILL_FOLDER_NAME, TEST_SKILLMETA_SRC).returns(TEST_SKILLMETA_SRC); - path.join.withArgs(TEST_SKILLMETA_SRC, 'skill.json').returns(FIXTURE_MANIFEST_FILE_PATH); - path.join.callThrough(); - }); - - afterEach(() => { - sinon.restore(); - }); - - it('| new resources config fails, expect throw error', () => { - // setup - sinon.stub(fs, 'existsSync').withArgs(FIXTURE_RESOURCES_CONFIG_FILE_PATH).returns(false); - fs.existsSync.callThrough(); - // call - try { - helper.loadSkillProjectModel(TEST_SKILL_FOLDER_NAME, TEST_PROFILE); - } catch (e) { - // verify - expect(e.message).includes(`File ${FIXTURE_RESOURCES_CONFIG_FILE_PATH} not exists.`); - expect(e.message).includes('please run \'ask util upgrade-project\''); - } - }); - - it('| skill metadata src does not exist, expect throw error', () => { - // setup - sinon.stub(stringUtils, 'isNonBlankString').returns(false); - // call - try { - helper.loadSkillProjectModel(TEST_SKILL_FOLDER_NAME, TEST_PROFILE); - } catch (e) { - // verify - expect(e.message).equal('[Error]: Invalid skill project structure. Please set the "src" field in skillMetada resource.'); - } - }); - - it('| skill meta src is absolue & skill package src does not exist, expect throw error', () => { - // setup - sinon.stub(stringUtils, 'isNonBlankString').returns(true); - sinon.stub(path, 'isAbsolute').returns(true); - sinon.stub(fs, 'existsSync').withArgs(TEST_SKILLMETA_SRC).returns(false); - fs.existsSync.callThrough(); - // call - try { - helper.loadSkillProjectModel(TEST_SKILL_FOLDER_NAME, TEST_PROFILE); - } catch (e) { - // verify - expect(e.message).equal(`[Error]: Invalid skill package src. Attempt to get the skill package but doesn't exist: \ -${ResourcesConfig.getInstance().getSkillMetaSrc(TEST_PROFILE)}.`); - } - }); - - it('| skill meta src is not absolue & skill package src does not exist, expect throw error', () => { - // setup - sinon.stub(stringUtils, 'isNonBlankString').returns(true); - sinon.stub(path, 'isAbsolute').returns(false); - sinon.stub(fs, 'existsSync').withArgs(TEST_SKILLMETA_SRC).returns(false); - fs.existsSync.callThrough(); - // call - try { - helper.loadSkillProjectModel(TEST_SKILL_FOLDER_NAME, TEST_PROFILE); - } catch (e) { - // verify - expect(e.message).equal(`[Error]: Invalid skill package src. Attempt to get the skill package but doesn't exist: \ -${TEST_SKILLMETA_SRC}.`); - } - }); - - it('| skill package manifest file does not exist, expect throw error', () => { - // setup - sinon.stub(fs, 'existsSync'); - sinon.stub(stringUtils, 'isNonBlankString').returns(true); - sinon.stub(path, 'isAbsolute').returns(true); - fs.existsSync.withArgs(TEST_SKILLMETA_SRC).returns(true); - fs.existsSync.withArgs(FIXTURE_MANIFEST_FILE_PATH).returns(false); - fs.existsSync.callThrough(); - // call - try { - helper.loadSkillProjectModel(TEST_SKILL_FOLDER_NAME, TEST_PROFILE); - } catch (e) { - // verify FIXTURE_MANIFEST_FILE_PATH - expect(e.message).equal(`[Error]: Invalid skill project structure. Please make sure skill.json exists in ${TEST_SKILLMETA_SRC}.`); - } - }); - - it('| new manifest file fails, expect throw error', () => { - // setup - sinon.stub(fs, 'existsSync'); - sinon.stub(stringUtils, 'isNonBlankString').returns(true); - sinon.stub(path, 'isAbsolute').returns(true); - path.join.withArgs(TEST_SKILLMETA_SRC, 'skill.json').returns('invalidPath'); - fs.existsSync.withArgs(TEST_SKILLMETA_SRC).returns(true); - fs.existsSync.withArgs('invalidPath').returns(true); - fs.existsSync.callThrough(); - // call - try { - helper.loadSkillProjectModel(TEST_SKILL_FOLDER_NAME, TEST_PROFILE); - } catch (e) { - // verify - expect(e.message).equal('No access to read/write file invalidPath.'); - } - }); - - it('| skill package structure passes the validation, expect no error', () => { - // setup - sinon.stub(fs, 'existsSync'); - path.join.withArgs(TEST_SKILL_FOLDER_NAME, 'ask-resources.json').returns(FIXTURE_RESOURCES_CONFIG_FILE_PATH); - sinon.stub(stringUtils, 'isNonBlankString').returns(true); - sinon.stub(path, 'isAbsolute').returns(true); - fs.existsSync.withArgs(TEST_SKILLMETA_SRC).returns(true); - fs.existsSync.withArgs(FIXTURE_MANIFEST_FILE_PATH).returns(true); - fs.existsSync.callThrough(); - // call - try { - helper.loadSkillProjectModel(TEST_SKILL_FOLDER_NAME, TEST_PROFILE); - } catch (e) { - // verify - expect(e).equal(undefined); - } - }); - }); - - describe('# test helper method - updateSkillProjectWithUserSettings', () => { - beforeEach(() => { - new ResourcesConfig(FIXTURE_RESOURCES_CONFIG_FILE_PATH); - new Manifest(FIXTURE_MANIFEST_FILE_PATH); - }); - - afterEach(() => { - Manifest.dispose(); - ResourcesConfig.dispose(); - sinon.restore(); - }); - - it('| expect refresh skill project to update skill name and remove .git folder', () => { - // setup - sinon.stub(fs, 'removeSync'); - // call - helper.updateSkillProjectWithUserSettings(TEST_SKILL_NAME, TEST_SKILL_FOLDER_NAME, TEST_PROFILE); - // verify - expect(Manifest.getInstance().getSkillName()).equal(TEST_SKILL_NAME); - expect(ResourcesConfig.getInstance().getProfile(TEST_PROFILE)).not.equal(null); - expect(fs.removeSync.args[0][0]).equal(path.join(TEST_SKILL_FOLDER_NAME, '.git')); - }); - }); -}); diff --git a/test/unit/commands/new/helper-test.ts b/test/unit/commands/new/helper-test.ts new file mode 100644 index 00000000..c32957e9 --- /dev/null +++ b/test/unit/commands/new/helper-test.ts @@ -0,0 +1,318 @@ +import {expect} from "chai"; +import fs from "fs-extra"; +import path from "path"; +import sinon, { SinonStub } from "sinon"; + +import GitClient from "../../../../lib/clients/git-client"; +import SkillInfrastructureController from "../../../../lib/controllers/skill-infrastructure-controller"; +import * as helper from "../../../../lib/commands/new/helper"; +import ResourcesConfig from "../../../../lib/model/resources-config"; +import Manifest from "../../../../lib/model/manifest"; +import stringUtils from "../../../../lib/utils/string-utils"; +import {FILE_PATH, DEPLOYER_TYPE} from "../../../../lib/utils/constants"; + +describe("Commands new test - helper test", () => { + const FIXTURE_RESOURCES_CONFIG_FILE_PATH = path.join( + process.cwd(), + "test", + "unit", + "fixture", + "model", + "regular-proj", + "ask-resources.json", + ); + const FIXTURE_MANIFEST_FILE_PATH = path.join(process.cwd(), "test", "unit", "fixture", "model", "manifest.json"); + const TEST_PROFILE = "default"; + const TEST_DO_DEBUG = false; + const TEST_INFRA_PATH = "infraPath"; + const TEST_DEPLOYMENT_TYPE = "deployer"; + const TEST_TEMPLATE_URL = "value"; + const TEST_SKILL_FOLDER_NAME = "skillFolderName"; + const TEST_SKILL_NAME = "skillName"; + const TEST_USER_INPUT: {projectFolderName: string; templateInfo: {templateBranch?: string; templateUrl: string}} = { + projectFolderName: "projectName", + templateInfo: { + templateUrl: TEST_TEMPLATE_URL, + }, + }; + + describe("# test helper method - initializeDeployDelegate", () => { + beforeEach(() => { + new ResourcesConfig(FIXTURE_RESOURCES_CONFIG_FILE_PATH); + }); + + afterEach(() => { + ResourcesConfig.dispose(); + sinon.restore(); + }); + + it("| ui select deploy delegate pass and selection is opt-out, expect quit process", (done) => { + // setup + // call + helper.initializeDeployDelegate(undefined, TEST_INFRA_PATH, TEST_PROFILE, TEST_DO_DEBUG, (err, res) => { + // verify + expect(res).equal(undefined); + expect(err).equal(null); + done(); + }); + }); + + it("| ui select Self hosted deploy delegate, expect quit process", (done) => { + // setup + // call + helper.initializeDeployDelegate(DEPLOYER_TYPE.SELF_HOSTED.NAME, TEST_INFRA_PATH, TEST_PROFILE, TEST_DO_DEBUG, (err, res) => { + // verify + expect(res).equal(undefined); + expect(err).equal(null); + done(); + }); + }); + + it("| deployer is set in the template and same as what user wants, expect skip bootstrap", (done) => { + // setup + ResourcesConfig.getInstance().setSkillInfraType(TEST_PROFILE, TEST_DEPLOYMENT_TYPE); + // call + helper.initializeDeployDelegate(TEST_DEPLOYMENT_TYPE, TEST_INFRA_PATH, TEST_PROFILE, TEST_DO_DEBUG, (err, res) => { + // verify + expect(res).equal(TEST_DEPLOYMENT_TYPE); + expect(err).equal(null); + done(); + }); + }); + + it("| bootstrap fails, expect throw error", (done) => { + // setup + const TEST_SELECTED_TYPE = "@ask-cli/test!!!@ "; + ResourcesConfig.getInstance().setSkillInfraType(TEST_PROFILE, ""); + const fsEnsureDirSyncStub = sinon.stub(fs, "ensureDirSync"); + sinon.stub(SkillInfrastructureController.prototype, "bootstrapInfrastructures").callsArgWith(1, "error"); + // call + helper.initializeDeployDelegate(TEST_SELECTED_TYPE, TEST_INFRA_PATH, TEST_PROFILE, TEST_DO_DEBUG, (err, res) => { + // verify + expect(fsEnsureDirSyncStub.args[0][0]).equal(path.join(TEST_INFRA_PATH, "infrastructure/test")); + expect(res).equal(undefined); + expect(err).equal("error"); + done(); + }); + }); + + it("| bootstrap pass, expect return deployType", (done) => { + // setup + const TEST_SELECTED_TYPE = " !!!test^^^ "; + ResourcesConfig.getInstance().setSkillInfraType(TEST_PROFILE, ""); + const fsEnsureDirSyncStub = sinon.stub(fs, "ensureDirSync"); + sinon.stub(SkillInfrastructureController.prototype, "bootstrapInfrastructures").callsArgWith(1); + // call + helper.initializeDeployDelegate(TEST_SELECTED_TYPE, TEST_INFRA_PATH, TEST_PROFILE, TEST_DO_DEBUG, (err, res) => { + // verify + expect(fsEnsureDirSyncStub.args[0][0]).equal(path.join(TEST_INFRA_PATH, "infrastructure/test")); + expect(res).equal(TEST_SELECTED_TYPE); + expect(err).equal(null); + done(); + }); + }); + }); + + describe("# test helper method - downloadTemplateFromGit", () => { + afterEach(() => { + sinon.restore(); + }); + + it("| git clone pass, expect return folder path", (done) => { + // setup + const TEST_FOLDER_PATH = "TEST_FOLDER_PATH"; + sinon.stub(path, "join").returns(TEST_FOLDER_PATH); + const cloneStub = sinon.stub(GitClient.prototype, "clone"); + // call + helper.downloadTemplateFromGit(TEST_USER_INPUT, TEST_DO_DEBUG, (err, res) => { + // verify + expect(cloneStub.args[0][0]).equal(TEST_TEMPLATE_URL); + expect(res).equal(TEST_FOLDER_PATH); + expect(err).equal(null); + done(); + }); + }); + it("| git clone with custom branch, expect return folder path", (done) => { + // setup + const TEST_FOLDER_PATH = "TEST_FOLDER_PATH"; + const TEST_TEMPLATE_BRANCH = "test-branch"; + TEST_USER_INPUT.templateInfo.templateBranch = TEST_TEMPLATE_BRANCH; + sinon.stub(path, "join").returns(TEST_FOLDER_PATH); + const cloneStub = sinon.stub(GitClient.prototype, "clone"); + // call + helper.downloadTemplateFromGit(TEST_USER_INPUT, TEST_DO_DEBUG, (err, res) => { + // verify + expect(cloneStub.args[0][0]).equal(TEST_TEMPLATE_URL); + expect(cloneStub.args[0][1]).equal(TEST_TEMPLATE_BRANCH); + expect(res).equal(TEST_FOLDER_PATH); + expect(err).equal(null); + done(); + }); + }); + }); + + describe("# test helper method - loadSkillProjectModel", () => { + const TEST_SKILLMETA_SRC = "./skillPackage"; + let pathJoinStub: SinonStub; + + beforeEach(() => { + pathJoinStub = sinon + .stub(path, "join"); + pathJoinStub.withArgs(TEST_SKILL_FOLDER_NAME, FILE_PATH.ASK_RESOURCES_JSON_CONFIG) + .returns(FIXTURE_RESOURCES_CONFIG_FILE_PATH); + pathJoinStub.withArgs(TEST_SKILL_FOLDER_NAME, TEST_SKILLMETA_SRC) + .returns(TEST_SKILLMETA_SRC); + pathJoinStub.withArgs(TEST_SKILLMETA_SRC, "skill.json") + .returns(FIXTURE_MANIFEST_FILE_PATH); + pathJoinStub.callThrough(); + }); + + afterEach(() => { + sinon.restore(); + }); + + it("| new resources config fails, expect throw error", (done) => { + // setup + const fsExistsSyncStub = sinon.stub(fs, "existsSync"); + fsExistsSyncStub.withArgs(FIXTURE_RESOURCES_CONFIG_FILE_PATH).returns(false); + fsExistsSyncStub.callThrough(); + // call + try { + helper.loadSkillProjectModel(TEST_SKILL_FOLDER_NAME, TEST_PROFILE); + } catch (e: any) { + // verify + expect(e?.message).includes(`File ${FIXTURE_RESOURCES_CONFIG_FILE_PATH} not exists.`); + expect(e?.message).includes("please run 'ask util upgrade-project'"); + done(); + } + }); + + it("| skill metadata src does not exist, expect throw error", (done) => { + // setup + sinon.stub(stringUtils, "isNonBlankString").returns(false); + // call + try { + helper.loadSkillProjectModel(TEST_SKILL_FOLDER_NAME, TEST_PROFILE); + } catch (e: any) { + // verify + expect(e?.message).equal('[Error]: Invalid skill project structure. Please set the "src" field in skillMetadata resource.'); + done(); + } + }); + + it("| skill meta src is absolue & skill package src does not exist, expect throw error", (done) => { + // setup + sinon.stub(stringUtils, "isNonBlankString").returns(true); + sinon.stub(path, "isAbsolute").returns(true); + const fsExistsSyncStub = sinon.stub(fs, "existsSync"); + fsExistsSyncStub.withArgs(TEST_SKILLMETA_SRC).returns(false); + fsExistsSyncStub.callThrough(); + // call + try { + helper.loadSkillProjectModel(TEST_SKILL_FOLDER_NAME, TEST_PROFILE); + } catch (e: any) { + // verify + expect(e?.message).equal(`[Error]: Invalid skill package src. Attempt to get the skill package but doesn't exist: \ +${ResourcesConfig.getInstance().getSkillMetaSrc(TEST_PROFILE)}.`); + done(); + } + }); + + it("| skill meta src is not absolue & skill package src does not exist, expect throw error", (done) => { + // setup + sinon.stub(stringUtils, "isNonBlankString").returns(true); + sinon.stub(path, "isAbsolute").returns(false); + const fsExistsSyncStub = sinon.stub(fs, "existsSync") + fsExistsSyncStub.withArgs(TEST_SKILLMETA_SRC).returns(false); + fsExistsSyncStub.callThrough(); + // call + try { + helper.loadSkillProjectModel(TEST_SKILL_FOLDER_NAME, TEST_PROFILE); + } catch (e: any) { + // verify + expect(e?.message).equal(`[Error]: Invalid skill package src. Attempt to get the skill package but doesn't exist: \ +${TEST_SKILLMETA_SRC}.`); + done(); + } + }); + + it("| skill package manifest file does not exist, expect throw error", (done) => { + // setup + const fsExistsSyncStub = sinon.stub(fs, "existsSync"); + sinon.stub(stringUtils, "isNonBlankString").returns(true); + sinon.stub(path, "isAbsolute").returns(true); + fsExistsSyncStub.withArgs(TEST_SKILLMETA_SRC).returns(true); + fsExistsSyncStub.withArgs(FIXTURE_MANIFEST_FILE_PATH).returns(false); + fsExistsSyncStub.callThrough(); + // call + try { + helper.loadSkillProjectModel(TEST_SKILL_FOLDER_NAME, TEST_PROFILE); + } catch (e: any) { + // verify FIXTURE_MANIFEST_FILE_PATH + expect(e?.message).equal(`[Error]: Invalid skill project structure. Please make sure skill.json exists in ${TEST_SKILLMETA_SRC}.`); + done(); + } + }); + + it("| new manifest file fails, expect throw error", (done) => { + // setup + const fsExistsSyncStub = sinon.stub(fs, "existsSync"); + sinon.stub(stringUtils, "isNonBlankString").returns(true); + sinon.stub(path, "isAbsolute").returns(true); + pathJoinStub.withArgs(TEST_SKILLMETA_SRC, "skill.json").returns("invalidPath"); + fsExistsSyncStub.withArgs(TEST_SKILLMETA_SRC).returns(true); + fsExistsSyncStub.withArgs("invalidPath").returns(true); + fsExistsSyncStub.callThrough(); + // call + try { + helper.loadSkillProjectModel(TEST_SKILL_FOLDER_NAME, TEST_PROFILE); + } catch (e: any) { + // verify + expect(e?.message).equal("No access to read/write file invalidPath."); + done(); + } + }); + + it("| skill package structure passes the validation, expect no error", () => { + // setup + const fsExistsSyncStub = sinon.stub(fs, "existsSync"); + pathJoinStub.withArgs(TEST_SKILL_FOLDER_NAME, "ask-resources.json").returns(FIXTURE_RESOURCES_CONFIG_FILE_PATH); + sinon.stub(stringUtils, "isNonBlankString").returns(true); + sinon.stub(path, "isAbsolute").returns(true); + fsExistsSyncStub.withArgs(TEST_SKILLMETA_SRC).returns(true); + fsExistsSyncStub.withArgs(FIXTURE_MANIFEST_FILE_PATH).returns(true); + fsExistsSyncStub.callThrough(); + // call + try { + helper.loadSkillProjectModel(TEST_SKILL_FOLDER_NAME, TEST_PROFILE); + } catch (e: any) { + // verify + expect(e).equal(undefined); + } + }); + }); + + describe("# test helper method - updateSkillProjectWithUserSettings", () => { + beforeEach(() => { + new ResourcesConfig(FIXTURE_RESOURCES_CONFIG_FILE_PATH); + new Manifest(FIXTURE_MANIFEST_FILE_PATH); + }); + + afterEach(() => { + Manifest.dispose(); + ResourcesConfig.dispose(); + sinon.restore(); + }); + + it("| expect refresh skill project to update skill name and remove .git folder", () => { + // setup + const fsExistsSyncStub = sinon.stub(fs, "removeSync"); + // call + helper.updateSkillProjectWithUserSettings(TEST_SKILL_NAME, TEST_SKILL_FOLDER_NAME, TEST_PROFILE); + // verify + expect(Manifest.getInstance().getSkillName()).equal(TEST_SKILL_NAME); + expect(ResourcesConfig.getInstance().getProfile(TEST_PROFILE)).not.equal(null); + expect(fsExistsSyncStub.args[0][0]).equal(path.join(TEST_SKILL_FOLDER_NAME, ".git")); + }); + }); +}); diff --git a/test/unit/commands/new/hosted-skill-helper-test.js b/test/unit/commands/new/hosted-skill-helper-test.js deleted file mode 100644 index 18950b43..00000000 --- a/test/unit/commands/new/hosted-skill-helper-test.js +++ /dev/null @@ -1,484 +0,0 @@ -const { expect } = require('chai'); -const fs = require('fs'); -const path = require('path'); -const portScanner = require('portscanner'); -const proxyquire = require('proxyquire'); -const sinon = require('sinon'); -const { URL, URLSearchParams } = require('url'); - -const hostedSkillHelper = require('@src/commands/new/hosted-skill-helper'); -const HostedSkillController = require('@src/controllers/hosted-skill-controller'); -const CONSTANTS = require('@src/utils/constants'); -const LocalHostServer = require('@src/utils/local-host-server'); -const Messenger = require('@src/view/messenger'); -const SpinnerView = require('@src/view/spinner-view'); -const SkillMetadataController = require('@src/controllers/skill-metadata-controller'); - -describe('Commands new test - hosted skill helper test', () => { - const TEST_ERROR = 'TEST_ERROR'; - const TEST_VENDOR_ID = 'TEST_VENDOR_ID'; - const TEST_SKILL_ID = 'TEST_SKILL_ID'; - const TEST_SKILL_NAME = 'TEST_SKILL_NAME'; - const TEST_FOLDER_NAME = 'TEST_FOLDER_NAME'; - const TEST_LANGUAGE = 'TEST_LANGUAGE'; - const TEST_ACTION_URL = 'TEST_ACTION_URL'; - const TEST_ASK_LWA_AUTHORIZE_HOST = 'https://amazon.com'; - const TEST_PORT_STATUS_CLOSED = 'closed'; - const TEST_PERMISSION_REGISTRATION_REQUIRED = { - status: CONSTANTS.HOSTED_SKILL.PERMISSION_CHECK_RESULT.NEW_USER_REGISTRATION_REQUIRED, - actionUrl: TEST_ACTION_URL - }; - const TEST_PERMISSION_ALLOWED = { - status: CONSTANTS.HOSTED_SKILL.PERMISSION_CHECK_RESULT.ALLOWED - }; - - describe('# test hosted skill helper method - validateUserQualification', () => { - let infoStub; - let proxyHelper; - let endStub; - let response; - let loginUrl; - let urlSearchParams; - - beforeEach(() => { - infoStub = sinon.stub(); - sinon.stub(Messenger, 'getInstance').returns({ - info: infoStub - }); - const openStub = sinon.stub(); - proxyHelper = proxyquire('@src/commands/new/hosted-skill-helper', { - open: openStub - }); - endStub = sinon.stub(); - response = { - on: sinon.stub().callsArgWith(1), - end: endStub - }; - loginUrl = new URL(CONSTANTS.LWA.SIGNIN_URL); - urlSearchParams = new URLSearchParams(); - }); - - afterEach(() => { - delete process.env.ASK_LWA_AUTHORIZE_HOST; - sinon.restore(); - }); - - it('| get hosted skill permission fails, expect error thrown', (done) => { - // setup - sinon.stub(HostedSkillController.prototype, 'getHostedSkillPermission').callsArgWith(2, TEST_ERROR); - // call - hostedSkillHelper.validateUserQualification(TEST_VENDOR_ID, HostedSkillController.prototype, (err, res) => { - // verify - expect(res).equal(undefined); - expect(err).equal(TEST_ERROR); - done(); - }); - }); - - it('| get hosted skill permission response resource limit exceeded, expect no error return', (done) => { - // setup - const TEST_RESPONSE = { - status: CONSTANTS.HOSTED_SKILL.PERMISSION_CHECK_RESULT.RESOURCE_LIMIT_EXCEEDED - }; - sinon.stub(HostedSkillController.prototype, 'getHostedSkillPermission').callsArgWith(2, null, TEST_RESPONSE); - // call - hostedSkillHelper.validateUserQualification(TEST_VENDOR_ID, HostedSkillController.prototype, (err, res) => { - // verify - expect(res).equal(undefined); - expect(err).equal('Your hosted skills account is limited to a certain number of new hosted skills per minute. ' - + 'Please try again later.'); - done(); - }); - }); - - it('| new user registration required to solve captcha, check Port status fails, expect error thrown', (done) => { - // setup - sinon.stub(HostedSkillController.prototype, 'getHostedSkillPermission').callsArgWith(2, null, TEST_PERMISSION_REGISTRATION_REQUIRED); - sinon.stub(portScanner, 'checkPortStatus').callsArgWith(1, TEST_ERROR); - // call - hostedSkillHelper.validateUserQualification(TEST_VENDOR_ID, HostedSkillController.prototype, (err) => { - // verify - expect(err).equal(TEST_ERROR); - expect(infoStub.args[0][0]).equal('CAPTCHA validation is required for a new hosted skill user.'); - expect(infoStub.args[1][0]).equal('Go to the CAPTCHA page, confirm that you are signed into the correct developer account, ' - + 'and solve the CAPTCHA.\n' - + 'If your browser does not open the page, quit this process, paste the following url into your browser, ' - + `and complete the CAPTCHA.\n${TEST_ACTION_URL}`); - done(); - }); - }); - - it('| new user registration required to solve captcha, check Port status not closed, expect error thrown', (done) => { - // setup - const TEST_PORT_STATUS = ''; - sinon.stub(HostedSkillController.prototype, 'getHostedSkillPermission').callsArgWith(2, null, TEST_PERMISSION_REGISTRATION_REQUIRED); - sinon.stub(portScanner, 'checkPortStatus').callsArgWith(1, null, TEST_PORT_STATUS); - // call - hostedSkillHelper.validateUserQualification(TEST_VENDOR_ID, HostedSkillController.prototype, (err) => { - // verify - expect(err).equal(`${CONSTANTS.LOCALHOST_PORT} port on localhost has been occupied, ` - + 'ask-cli cannot start a local server for receiving authorization code.\n' - + `Please either abort any processes running on port ${CONSTANTS.LOCALHOST_PORT} ` - + 'or add `--no-browser` flag to the command as an alternative approach.'); - done(); - }); - }); - - it('| new user required to solve captcha, open login url with redirect url, expect local host server is listening', () => { - // setup - sinon.stub(HostedSkillController.prototype, 'getHostedSkillPermission').callsArgWith(2, null, TEST_PERMISSION_REGISTRATION_REQUIRED); - sinon.stub(portScanner, 'checkPortStatus').callsArgWith(1, null, TEST_PORT_STATUS_CLOSED); - sinon.stub(process, 'env'); - const socket = { - unref: () => {} - }; - const createStub = sinon.stub(LocalHostServer.prototype, 'create'); - const listenStub = sinon.stub(LocalHostServer.prototype, 'listen').callsArgWith(0); - const spinnerStartStub = sinon.stub(SpinnerView.prototype, 'start'); - const registerEventStub = sinon.stub(LocalHostServer.prototype, 'registerEvent').callsArgWith(1, socket); - // call - proxyHelper.validateUserQualification(TEST_VENDOR_ID, HostedSkillController.prototype, () => {}); - // verify - expect(registerEventStub.callCount).eq(1); - expect(spinnerStartStub.args[0][0]).eq(` Listening on http://localhost:${CONSTANTS.LOCALHOST_PORT}...`); - expect(spinnerStartStub.callCount).eq(1); - expect(listenStub.callCount).eq(1); - expect(createStub.callCount).eq(1); - }); - - it('| new user required to solve captcha, listen response from captcha server error, expect error thrown', (done) => { - // setup - sinon.stub(HostedSkillController.prototype, 'getHostedSkillPermission').callsArgWith(2, null, TEST_PERMISSION_REGISTRATION_REQUIRED); - sinon.stub(portScanner, 'checkPortStatus').callsArgWith(1, null, TEST_PORT_STATUS_CLOSED); - sinon.stub(process, 'env'); - - sinon.stub(LocalHostServer.prototype, 'listen'); - sinon.stub(LocalHostServer.prototype, 'registerEvent'); - const requestDestroyStub = sinon.stub(); - const request = { - url: '/captcha?error', - socket: { - destroy: requestDestroyStub - } - }; - const spinnerTerminateStub = sinon.stub(SpinnerView.prototype, 'terminate'); - const serverDestroyStub = sinon.stub(LocalHostServer.prototype, 'destroy'); - sinon.stub(LocalHostServer.prototype, 'create').callsArgWith(0, request, response); - const TEST_CAPTCHA_ERROR = 'Failed to validate the CAPTCHA with internal service error. Please try again later.'; - // call - proxyHelper.validateUserQualification(TEST_VENDOR_ID, HostedSkillController.prototype, (err) => { - // verify - expect(spinnerTerminateStub.callCount).eq(1); - expect(serverDestroyStub.callCount).eq(1); - expect(endStub.callCount).eq(1); - expect(endStub.args[0][0]).eq(TEST_CAPTCHA_ERROR); - expect(err).eq(TEST_CAPTCHA_ERROR); - done(); - }); - }); - - it('| new user required to solve captcha, listen response from captcha server vendorId, expect error thrown', (done) => { - // setup - sinon.stub(HostedSkillController.prototype, 'getHostedSkillPermission').callsArgWith(2, null, TEST_PERMISSION_REGISTRATION_REQUIRED); - sinon.stub(portScanner, 'checkPortStatus').callsArgWith(1, null, TEST_PORT_STATUS_CLOSED); - sinon.stub(process, 'env'); - - sinon.stub(LocalHostServer.prototype, 'listen'); - sinon.stub(LocalHostServer.prototype, 'registerEvent'); - const requestDestroyStub = sinon.stub(); - const request = { - url: '/captcha?vendorId', - socket: { - destroy: requestDestroyStub - } - }; - sinon.stub(SpinnerView.prototype, 'terminate'); - sinon.stub(LocalHostServer.prototype, 'destroy'); - sinon.stub(LocalHostServer.prototype, 'create').callsArgWith(0, request, response); - const TEST_CAPTCHA_ERROR = 'The Vendor ID in the browser session does not match the one associated with your CLI profile. \n' - + 'Please sign into the correct developer account in your browser before completing the CAPTCHA.'; - // call - proxyHelper.validateUserQualification(TEST_VENDOR_ID, HostedSkillController.prototype, (err) => { - // verify - expect(endStub.callCount).eq(1); - expect(endStub.args[0][0]).eq(TEST_CAPTCHA_ERROR); - expect(err).eq(TEST_CAPTCHA_ERROR); - done(); - }); - }); - - it('| new user required to solve captcha, listen response from captcha server other errors, expect error thrown', (done) => { - // setup - sinon.stub(HostedSkillController.prototype, 'getHostedSkillPermission').callsArgWith(2, null, TEST_PERMISSION_REGISTRATION_REQUIRED); - sinon.stub(portScanner, 'checkPortStatus').callsArgWith(1, null, TEST_PORT_STATUS_CLOSED); - sinon.stub(process, 'env'); - - sinon.stub(LocalHostServer.prototype, 'listen'); - sinon.stub(LocalHostServer.prototype, 'registerEvent'); - const requestDestroyStub = sinon.stub(); - const request = { - url: '', - socket: { - destroy: requestDestroyStub - } - }; - sinon.stub(SpinnerView.prototype, 'terminate'); - sinon.stub(LocalHostServer.prototype, 'destroy'); - sinon.stub(LocalHostServer.prototype, 'create').callsArgWith(0, request, response); - const TEST_CAPTCHA_ERROR = 'Failed to validate the CAPTCHA. Please try again.'; - // call - proxyHelper.validateUserQualification(TEST_VENDOR_ID, HostedSkillController.prototype, (err) => { - // verify - expect(endStub.callCount).eq(1); - expect(endStub.args[0][0]).eq(TEST_CAPTCHA_ERROR); - expect(err).eq(TEST_CAPTCHA_ERROR); - done(); - }); - }); - - it('| new user required to solve captcha, listen response from captcha server to look for "favicon.ico" file, ' - + 'expect ignore the request', () => { - // setup - sinon.stub(HostedSkillController.prototype, 'getHostedSkillPermission').callsArgWith(2, null, TEST_PERMISSION_REGISTRATION_REQUIRED); - sinon.stub(portScanner, 'checkPortStatus').callsArgWith(1, null, TEST_PORT_STATUS_CLOSED); - sinon.stub(process, 'env'); - process.env.ASK_LWA_AUTHORIZE_HOST = TEST_ASK_LWA_AUTHORIZE_HOST; - - sinon.stub(LocalHostServer.prototype, 'listen'); - sinon.stub(LocalHostServer.prototype, 'registerEvent'); - const requestDestroyStub = sinon.stub(); - const request = { - url: '/favicon.ico', - socket: { - destroy: requestDestroyStub - } - }; - sinon.stub(SpinnerView.prototype, 'terminate'); - sinon.stub(LocalHostServer.prototype, 'destroy'); - sinon.stub(LocalHostServer.prototype, 'create').callsArgWith(0, request, response); - // call - proxyHelper.validateUserQualification(TEST_VENDOR_ID, HostedSkillController.prototype, () => {}); - // verify - expect(endStub.callCount).eq(1); - }); - - it('| new user required to solve captcha, listen response from captcha server success, check permission again fails, ' - + 'expect error thrown', (done) => { - // setup - const hostedSkillPermissionStub = sinon.stub(HostedSkillController.prototype, 'getHostedSkillPermission'); - hostedSkillPermissionStub.onCall(0).callsArgWith(2, null, TEST_PERMISSION_REGISTRATION_REQUIRED); - sinon.stub(portScanner, 'checkPortStatus').callsArgWith(1, null, TEST_PORT_STATUS_CLOSED); - sinon.stub(process, 'env'); - process.env.ASK_LWA_AUTHORIZE_HOST = TEST_ASK_LWA_AUTHORIZE_HOST; - - sinon.stub(LocalHostServer.prototype, 'listen'); - sinon.stub(LocalHostServer.prototype, 'registerEvent'); - const requestDestroyStub = sinon.stub(); - const request = { - url: '/captcha?success', - socket: { - destroy: requestDestroyStub - } - }; - sinon.stub(SpinnerView.prototype, 'terminate'); - sinon.stub(LocalHostServer.prototype, 'destroy'); - sinon.stub(LocalHostServer.prototype, 'create').callsArgWith(0, request, response); - const TEST_CAPTCHA_SUCCESS = 'CAPTCHA validation was successful. Please close the browser and return to the command line interface.'; - hostedSkillPermissionStub.onCall(1).callsArgWith(2, TEST_ERROR); - // call - proxyHelper.validateUserQualification(TEST_VENDOR_ID, HostedSkillController.prototype, (err) => { - // verify - expect(endStub.callCount).eq(1); - expect(endStub.args[0][0]).eq(TEST_CAPTCHA_SUCCESS); - expect(err).eq(TEST_ERROR); - done(); - }); - }); - - it('| new user required to solve captcha success, check permission again success, expect no error return', (done) => { - // setup - const hostedSkillPermissionStub = sinon.stub(HostedSkillController.prototype, 'getHostedSkillPermission'); - hostedSkillPermissionStub.onCall(0).callsArgWith(2, null, TEST_PERMISSION_REGISTRATION_REQUIRED); - sinon.stub(portScanner, 'checkPortStatus').callsArgWith(1, null, TEST_PORT_STATUS_CLOSED); - sinon.stub(process, 'env'); - process.env.ASK_LWA_AUTHORIZE_HOST = TEST_ASK_LWA_AUTHORIZE_HOST; - - sinon.stub(LocalHostServer.prototype, 'listen'); - sinon.stub(LocalHostServer.prototype, 'registerEvent'); - const requestDestroyStub = sinon.stub(); - const request = { - url: '/captcha?success', - socket: { - destroy: requestDestroyStub - } - }; - sinon.stub(SpinnerView.prototype, 'terminate'); - sinon.stub(LocalHostServer.prototype, 'destroy'); - sinon.stub(LocalHostServer.prototype, 'create').callsArgWith(0, request, response); - const TEST_CAPTCHA_SUCCESS = 'CAPTCHA validation was successful. Please close the browser and return to the command line interface.'; - hostedSkillPermissionStub.onCall(1).callsArgWith(2, null, TEST_PERMISSION_ALLOWED); - // call - proxyHelper.validateUserQualification(TEST_VENDOR_ID, HostedSkillController.prototype, (err) => { - // verify - expect(endStub.callCount).eq(1); - expect(endStub.args[0][0]).eq(TEST_CAPTCHA_SUCCESS); - expect(infoStub.args[2][0]).equal('CAPTCHA validation was successfully completed. You are able to create a Alexa hosted skill.'); - expect(err).eq(undefined); - done(); - }); - }); - - it('| not new user check permission success, expect no error return', (done) => { - // setup - const hostedSkillPermissionStub = sinon.stub(HostedSkillController.prototype, 'getHostedSkillPermission'); - hostedSkillPermissionStub.callsArgWith(2, null, TEST_PERMISSION_ALLOWED); - // call - proxyHelper.validateUserQualification(TEST_VENDOR_ID, HostedSkillController.prototype, (err) => { - // verify - expect(err).eq(undefined); - done(); - }); - }); - }); - - describe('# test hosted skill helper method - createHostedSkill', () => { - const TEST_USER_INPUT = { - projectFolderName: TEST_FOLDER_NAME, - skillName: TEST_SKILL_NAME, - language: TEST_LANGUAGE - }; - - beforeEach(() => { - }); - - afterEach(() => { - sinon.restore(); - }); - - it('| hostedSkillController project already exists, expect error thrown', (done) => { - // setup - const TEST_PROJECT_PATH = 'TEST_PROJECT_PATH'; - sinon.stub(path, 'join').returns(TEST_PROJECT_PATH); - sinon.stub(fs, 'existsSync').returns(true); - // call - hostedSkillHelper.createHostedSkill(HostedSkillController.prototype, TEST_USER_INPUT, TEST_VENDOR_ID, (err, res) => { - // verify - expect(res).equal(undefined); - expect(err).equal(`${TEST_PROJECT_PATH} directory already exists.`); - done(); - }); - }); - - it('| hostedSkillController create skill fails, expect error thrown', (done) => { - // setup - sinon.stub(HostedSkillController.prototype, 'createSkill').callsArgWith(1, TEST_ERROR); - const spinnerStartStub = sinon.stub(SpinnerView.prototype, 'start'); - // call - hostedSkillHelper.createHostedSkill(HostedSkillController.prototype, TEST_USER_INPUT, TEST_VENDOR_ID, (err, res) => { - // verify - expect(spinnerStartStub.callCount).eq(1); - expect(spinnerStartStub.args[0][0]).eq('Creating your Alexa hosted skill. It will take about a minute.'); - expect(res).equal(undefined); - expect(err).equal(TEST_ERROR); - done(); - }); - }); - - it('| hostedSkillController create skill response with skillId, expect error thrown', (done) => { - // setup - sinon.stub(HostedSkillController.prototype, 'createSkill').callsArgWith(1, TEST_ERROR, TEST_SKILL_ID); - sinon.stub(SpinnerView.prototype, 'start'); - sinon.stub(HostedSkillController.prototype, 'deleteSkill').callsArgWith(1, undefined); - // call - hostedSkillHelper.createHostedSkill(HostedSkillController.prototype, TEST_USER_INPUT, TEST_VENDOR_ID, (err, res) => { - // verify - expect(res).equal(undefined); - expect(err).equal(TEST_ERROR); - done(); - }); - }); - - it('| hostedSkillController create skill succeed, updateAskSystemScripts fails, expect error thrown', (done) => { - // setup - sinon.stub(HostedSkillController.prototype, 'createSkill').callsArgWith(1, null, TEST_SKILL_ID); - sinon.stub(SpinnerView.prototype, 'start'); - sinon.stub(HostedSkillController.prototype, 'updateAskSystemScripts').callsArgWith(0, TEST_ERROR); - // call - hostedSkillHelper.createHostedSkill(HostedSkillController.prototype, TEST_USER_INPUT, TEST_VENDOR_ID, (err, res) => { - // verify - expect(res).equal(undefined); - expect(err).equal(TEST_ERROR); - done(); - }); - }); - - it('| hostedSkillController updateAskSystemScripts succeed, clone fails, expect error thrown', (done) => { - // setup - sinon.stub(HostedSkillController.prototype, 'createSkill').callsArgWith(1, null, TEST_SKILL_ID); - sinon.stub(SpinnerView.prototype, 'start'); - sinon.stub(HostedSkillController.prototype, 'updateAskSystemScripts').callsArgWith(0, null); - sinon.stub(process, 'cwd').returns('root/'); - sinon.stub(HostedSkillController.prototype, 'clone').callsArgWith(3, TEST_ERROR); - // call - hostedSkillHelper.createHostedSkill(HostedSkillController.prototype, TEST_USER_INPUT, TEST_VENDOR_ID, (err, res) => { - // verify - expect(res).equal(undefined); - expect(err).equal(TEST_ERROR); - done(); - }); - }); - - it('| hostedSkillController clone succeed, enableSkill fails, expect error thrown', (done) => { - // setup - sinon.stub(HostedSkillController.prototype, 'createSkill').callsArgWith(1, null, TEST_SKILL_ID); - sinon.stub(SpinnerView.prototype, 'start'); - sinon.stub(HostedSkillController.prototype, 'updateAskSystemScripts').callsArgWith(0, null); - sinon.stub(process, 'cwd').returns('root/'); - sinon.stub(HostedSkillController.prototype, 'clone').callsArgWith(3, null); - sinon.stub(SkillMetadataController.prototype, 'enableSkill').yields(TEST_ERROR); - // call - hostedSkillHelper.createHostedSkill(HostedSkillController.prototype, TEST_USER_INPUT, TEST_VENDOR_ID, (err, res) => { - // verify - expect(res).equal(undefined); - expect(err).equal(TEST_ERROR); - done(); - }); - }); - - it('| hostedSkillController clone succeed, updateSkillPrePushScript fails, expect error thrown', (done) => { - // setup - sinon.stub(HostedSkillController.prototype, 'createSkill').callsArgWith(1, null, TEST_SKILL_ID); - sinon.stub(SpinnerView.prototype, 'start'); - sinon.stub(HostedSkillController.prototype, 'updateAskSystemScripts').callsArgWith(0, null); - sinon.stub(process, 'cwd').returns('root/'); - sinon.stub(HostedSkillController.prototype, 'clone').callsArgWith(3, null); - sinon.stub(SkillMetadataController.prototype, 'enableSkill').yields(); - sinon.stub(HostedSkillController.prototype, 'updateSkillPrePushScript').callsArgWith(1, TEST_ERROR); - // call - hostedSkillHelper.createHostedSkill(HostedSkillController.prototype, TEST_USER_INPUT, TEST_VENDOR_ID, (err, res) => { - // verify - expect(res).equal(undefined); - expect(err).equal(TEST_ERROR); - done(); - }); - }); - - it('| hostedSkillController create skill succeed, clone succeed, expect skillId return', (done) => { - // setup - sinon.stub(HostedSkillController.prototype, 'createSkill').callsArgWith(1, null, TEST_SKILL_ID); - sinon.stub(SpinnerView.prototype, 'start'); - sinon.stub(HostedSkillController.prototype, 'updateAskSystemScripts').callsArgWith(0, null); - sinon.stub(process, 'cwd').returns('root/'); - sinon.stub(HostedSkillController.prototype, 'clone').callsArgWith(3, null); - sinon.stub(SkillMetadataController.prototype, 'enableSkill').yields(); - sinon.stub(HostedSkillController.prototype, 'updateSkillPrePushScript').callsArgWith(1, null); - // call - hostedSkillHelper.createHostedSkill(HostedSkillController.prototype, TEST_USER_INPUT, TEST_VENDOR_ID, (err, res) => { - // verify - expect(res).equal(TEST_SKILL_ID); - expect(err).equal(null); - done(); - }); - }); - }); -}); diff --git a/test/unit/commands/new/hosted-skill-helper-test.ts b/test/unit/commands/new/hosted-skill-helper-test.ts new file mode 100644 index 00000000..981832d1 --- /dev/null +++ b/test/unit/commands/new/hosted-skill-helper-test.ts @@ -0,0 +1,497 @@ +import { expect } from "chai"; +import fs from "fs"; +import path from "path"; +import portScanner from "portscanner"; +import sinon from "sinon"; +import * as hostedSkillHelper from "../../../../lib/commands/new/hosted-skill-helper"; +import HostedSkillController from "../../../../lib/controllers/hosted-skill-controller"; +import {HOSTED_SKILL, LOCALHOST_PORT} from "../../../../lib/utils/constants"; +import LocalHostServer from "../../../../lib/utils/local-host-server"; +import Messenger from "../../../../lib/view/messenger"; +import SpinnerView from "../../../../lib/view/spinner-view"; +import SkillMetadataController from "../../../../lib/controllers/skill-metadata-controller"; +import proxyquire from "proxyquire"; +import { NewSkillUserInput } from "../../../../lib/commands/new"; + +describe("Commands new test - hosted skill helper test", () => { + const TEST_ERROR = "TEST_ERROR"; + const TEST_VENDOR_ID = "TEST_VENDOR_ID"; + const TEST_SKILL_ID = "TEST_SKILL_ID"; + const TEST_SKILL_NAME = "TEST_SKILL_NAME"; + const TEST_FOLDER_NAME = "TEST_FOLDER_NAME"; + const TEST_LANGUAGE = "Python"; + const TEST_ACTION_URL = "TEST_ACTION_URL"; + const TEST_ASK_LWA_AUTHORIZE_HOST = "https://amazon.com"; + const TEST_PORT_STATUS_CLOSED = "closed"; + const TEST_PERMISSION_REGISTRATION_REQUIRED = { + status: HOSTED_SKILL.PERMISSION_CHECK_RESULT.NEW_USER_REGISTRATION_REQUIRED, + actionUrl: TEST_ACTION_URL, + }; + const TEST_PERMISSION_ALLOWED = { + status: HOSTED_SKILL.PERMISSION_CHECK_RESULT.ALLOWED, + }; + + describe("# test hosted skill helper method - validateUserQualification", () => { + let infoStub: sinon.SinonStub; + let endStub: sinon.SinonStub; + let proxyHelper: any; + let response: { on: sinon.SinonStub; end: sinon.SinonStub; }; + + beforeEach(() => { + infoStub = sinon.stub(); + sinon.stub(Messenger, "getInstance").returns({ + info: infoStub, + }); + const openStub = sinon.stub(); + proxyHelper = proxyquire("../../../../lib/commands/new/hosted-skill-helper", { + open: openStub, + }); + endStub = sinon.stub(); + response = { + on: sinon.stub().callsArgWith(1), + end: endStub, + }; + }); + + afterEach(() => { + delete process.env.ASK_LWA_AUTHORIZE_HOST; + sinon.restore(); + }); + + it("| get hosted skill permission fails, expect error thrown", (done) => { + // setup + sinon.stub(HostedSkillController.prototype, "getHostedSkillPermission").callsArgWith(2, TEST_ERROR); + // call + hostedSkillHelper.validateUserQualification(TEST_VENDOR_ID, HostedSkillController.prototype, (err, res) => { + // verify + expect(res).equal(undefined); + expect(err).equal(TEST_ERROR); + done(); + }); + }); + + it("| get hosted skill permission response resource limit exceeded, expect no error return", (done) => { + // setup + const TEST_RESPONSE = { + status: HOSTED_SKILL.PERMISSION_CHECK_RESULT.RESOURCE_LIMIT_EXCEEDED, + }; + sinon.stub(HostedSkillController.prototype, "getHostedSkillPermission").callsArgWith(2, null, TEST_RESPONSE); + // call + hostedSkillHelper.validateUserQualification(TEST_VENDOR_ID, HostedSkillController.prototype, (err, res) => { + // verify + expect(res).equal(undefined); + expect(err?.message).equal( + "Your hosted skills account is limited to a certain number of new hosted skills per minute. Please try again later.", + ); + done(); + }); + }); + + it("| new user registration required to solve captcha, check Port status fails, expect error thrown", (done) => { + // setup + sinon.stub(HostedSkillController.prototype, "getHostedSkillPermission").callsArgWith(2, null, TEST_PERMISSION_REGISTRATION_REQUIRED); + sinon.stub(portScanner, "checkPortStatus").callsArgWith(1, TEST_ERROR); + // call + hostedSkillHelper.validateUserQualification(TEST_VENDOR_ID, HostedSkillController.prototype, (err) => { + // verify + expect(err).equal(TEST_ERROR); + expect(infoStub.args[0][0]).equal("CAPTCHA validation is required for a new hosted skill user."); + expect(infoStub.args[1][0]).equal( + "Go to the CAPTCHA page, confirm that you are signed into the correct developer account, " + + "and solve the CAPTCHA.\n" + + "If your browser does not open the page, quit this process, paste the following url into your browser, " + + `and complete the CAPTCHA.\n${TEST_ACTION_URL}`, + ); + done(); + }); + }); + + it("| new user registration required to solve captcha, check Port status not closed, expect error thrown", (done) => { + // setup + const TEST_PORT_STATUS_OPEN = "open"; + const getHostedSkillPermissionStub = sinon.stub(HostedSkillController.prototype, "getHostedSkillPermission"); + getHostedSkillPermissionStub.callsArgWith(2, null, TEST_PERMISSION_REGISTRATION_REQUIRED); + const checkPortStatusStub = sinon.stub(portScanner, "checkPortStatus"); + checkPortStatusStub.callsArgWith(1, null, TEST_PORT_STATUS_OPEN); + // call + hostedSkillHelper.validateUserQualification(TEST_VENDOR_ID, HostedSkillController.prototype, (err) => { + // verify + expect(err?.message).equal( + `${LOCALHOST_PORT} port on localhost has been occupied, ` + + "ask-cli cannot start a local server for receiving authorization code.\n" + + `Please either abort any processes running on port ${LOCALHOST_PORT} ` + + "or add `--no-browser` flag to the command as an alternative approach.", + ); + done(); + }); + }); + + it("| new user required to solve captcha, open login url with redirect url, expect local host server is listening", () => { + // setup + sinon.stub(HostedSkillController.prototype, "getHostedSkillPermission").callsArgWith(2, null, TEST_PERMISSION_REGISTRATION_REQUIRED); + sinon.stub(portScanner, "checkPortStatus").callsArgWith(1, null, TEST_PORT_STATUS_CLOSED); + sinon.stub(process, "env"); + const socket = { + unref: () => {}, + }; + const createStub = sinon.stub(LocalHostServer.prototype, "create"); + const listenStub = sinon.stub(LocalHostServer.prototype, "listen").callsArgWith(0); + const spinnerStartStub = sinon.stub(SpinnerView.prototype, "start"); + const registerEventStub = sinon.stub(LocalHostServer.prototype, "registerEvent").callsArgWith(1, socket); + // call + proxyHelper.validateUserQualification(TEST_VENDOR_ID, HostedSkillController.prototype, () => {}); + // verify + expect(registerEventStub.callCount).eq(1); + expect(spinnerStartStub.args[0][0]).eq(` Listening on http://localhost:${LOCALHOST_PORT}...`); + expect(spinnerStartStub.callCount).eq(1); + expect(listenStub.callCount).eq(1); + expect(createStub.callCount).eq(1); + }); + + it("| new user required to solve captcha, listen response from captcha server error, expect error thrown", (done) => { + // setup + sinon.stub(HostedSkillController.prototype, "getHostedSkillPermission").callsArgWith(2, null, TEST_PERMISSION_REGISTRATION_REQUIRED); + sinon.stub(portScanner, "checkPortStatus").callsArgWith(1, null, TEST_PORT_STATUS_CLOSED); + sinon.stub(process, "env"); + sinon.stub(LocalHostServer.prototype, "listen"); + sinon.stub(LocalHostServer.prototype, "registerEvent"); + const requestDestroyStub = sinon.stub(); + const request = { + url: "/captcha?error", + socket: { + destroy: requestDestroyStub, + }, + }; + const spinnerTerminateStub = sinon.stub(SpinnerView.prototype, "terminate"); + const serverDestroyStub = sinon.stub(LocalHostServer.prototype, "destroy"); + sinon.stub(LocalHostServer.prototype, "create").callsArgWith(0, request, response); + const TEST_CAPTCHA_ERROR = "Failed to validate the CAPTCHA with internal service error. Please try again later."; + // call + proxyHelper.validateUserQualification(TEST_VENDOR_ID, HostedSkillController.prototype, (err: Error | null) => { + // verify + expect(spinnerTerminateStub.callCount).eq(1); + expect(serverDestroyStub.callCount).eq(1); + expect(endStub.callCount).eq(1); + expect(endStub.args[0][0]).eq(TEST_CAPTCHA_ERROR); + expect(err?.message).eq(TEST_CAPTCHA_ERROR); + done(); + }); + }); + + it("| new user required to solve captcha, listen response from captcha server vendorId, expect error thrown", (done) => { + // setup + sinon.stub(HostedSkillController.prototype, "getHostedSkillPermission").callsArgWith(2, null, TEST_PERMISSION_REGISTRATION_REQUIRED); + sinon.stub(portScanner, "checkPortStatus").callsArgWith(1, null, TEST_PORT_STATUS_CLOSED); + sinon.stub(process, "env"); + sinon.stub(LocalHostServer.prototype, "listen"); + sinon.stub(LocalHostServer.prototype, "registerEvent"); + const requestDestroyStub = sinon.stub(); + const request = { + url: "/captcha?vendorId", + socket: { + destroy: requestDestroyStub, + }, + }; + sinon.stub(SpinnerView.prototype, "terminate"); + sinon.stub(LocalHostServer.prototype, "destroy"); + sinon.stub(LocalHostServer.prototype, "create").callsArgWith(0, request, response); + const TEST_CAPTCHA_ERROR = + "The Vendor ID in the browser session does not match the one associated with your CLI profile. \n" + + "Please sign into the correct developer account in your browser before completing the CAPTCHA."; + // call + proxyHelper.validateUserQualification(TEST_VENDOR_ID, HostedSkillController.prototype, (err: Error | null) => { + // verify + expect(endStub.callCount).eq(1); + expect(endStub.args[0][0]).eq(TEST_CAPTCHA_ERROR); + expect(err?.message).eq(TEST_CAPTCHA_ERROR); + done(); + }); + }); + + it("| new user required to solve captcha, listen response from captcha server other errors, expect error thrown", (done) => { + // setup + sinon.stub(HostedSkillController.prototype, "getHostedSkillPermission").callsArgWith(2, null, TEST_PERMISSION_REGISTRATION_REQUIRED); + sinon.stub(portScanner, "checkPortStatus").callsArgWith(1, null, TEST_PORT_STATUS_CLOSED); + sinon.stub(process, "env"); + sinon.stub(LocalHostServer.prototype, "listen"); + sinon.stub(LocalHostServer.prototype, "registerEvent"); + const requestDestroyStub = sinon.stub(); + const request = { + url: "", + socket: { + destroy: requestDestroyStub, + }, + }; + sinon.stub(SpinnerView.prototype, "terminate"); + sinon.stub(LocalHostServer.prototype, "destroy"); + sinon.stub(LocalHostServer.prototype, "create").callsArgWith(0, request, response); + const TEST_CAPTCHA_ERROR = "Failed to validate the CAPTCHA. Please try again."; + // call + proxyHelper.validateUserQualification(TEST_VENDOR_ID, HostedSkillController.prototype, (err: Error | null) => { + // verify + expect(endStub.callCount).eq(1); + expect(endStub.args[0][0]).eq(TEST_CAPTCHA_ERROR); + expect(err?.message).eq(TEST_CAPTCHA_ERROR); + done(); + }); + }); + + it( + '| new user required to solve captcha, listen response from captcha server to look for "favicon.ico" file, ' + + "expect ignore the request", + () => { + // setup + sinon + .stub(HostedSkillController.prototype, "getHostedSkillPermission") + .callsArgWith(2, null, TEST_PERMISSION_REGISTRATION_REQUIRED); + sinon.stub(portScanner, "checkPortStatus").callsArgWith(1, null, TEST_PORT_STATUS_CLOSED); + sinon.stub(process, "env"); + process.env.ASK_LWA_AUTHORIZE_HOST = TEST_ASK_LWA_AUTHORIZE_HOST; + + sinon.stub(LocalHostServer.prototype, "listen"); + sinon.stub(LocalHostServer.prototype, "registerEvent"); + const requestDestroyStub = sinon.stub(); + const request = { + url: "/favicon.ico", + socket: { + destroy: requestDestroyStub, + }, + }; + sinon.stub(SpinnerView.prototype, "terminate"); + sinon.stub(LocalHostServer.prototype, "destroy"); + sinon.stub(LocalHostServer.prototype, "create").callsArgWith(0, request, response); + // call + proxyHelper.validateUserQualification(TEST_VENDOR_ID, HostedSkillController.prototype, () => {}); + // verify + expect(endStub.callCount).eq(1); + }, + ); + + it( + "| new user required to solve captcha, listen response from captcha server success, check permission again fails, " + + "expect error thrown", + (done) => { + // setup + const hostedSkillPermissionStub = sinon.stub(HostedSkillController.prototype, "getHostedSkillPermission"); + hostedSkillPermissionStub.onCall(0).callsArgWith(2, null, TEST_PERMISSION_REGISTRATION_REQUIRED); + const checkPortStatusStub = sinon.stub(portScanner, "checkPortStatus"); + checkPortStatusStub.callsArgWith(1, null, TEST_PORT_STATUS_CLOSED); + sinon.stub(process, "env"); + process.env.ASK_LWA_AUTHORIZE_HOST = TEST_ASK_LWA_AUTHORIZE_HOST; + + sinon.stub(LocalHostServer.prototype, "listen"); + sinon.stub(LocalHostServer.prototype, "registerEvent"); + const requestDestroyStub = sinon.stub(); + const request = { + url: "/captcha?success", + socket: { + destroy: requestDestroyStub, + }, + }; + sinon.stub(SpinnerView.prototype, "terminate"); + sinon.stub(LocalHostServer.prototype, "destroy"); + const LocalHostServerCreateStub = sinon.stub(LocalHostServer.prototype, "create"); + LocalHostServerCreateStub.callsArgWith(0, request, response); + const TEST_CAPTCHA_SUCCESS = + "CAPTCHA validation was successful. Please close the browser and return to the command line interface."; + hostedSkillPermissionStub.onCall(1).callsArgWith(2, new Error(TEST_ERROR)); + // call + proxyHelper.validateUserQualification(TEST_VENDOR_ID, HostedSkillController.prototype, (err: Error | null) => { + // verify + expect(endStub.callCount).eq(1); + expect(endStub.args[0][0]).eq(TEST_CAPTCHA_SUCCESS); + expect(err?.message).eq(TEST_ERROR); + done(); + }); + }, + ); + + it("| new user required to solve captcha success, check permission again success, expect no error return", (done) => { + // setup + const hostedSkillPermissionStub = sinon.stub(HostedSkillController.prototype, "getHostedSkillPermission"); + hostedSkillPermissionStub.onCall(0).callsArgWith(2, null, TEST_PERMISSION_REGISTRATION_REQUIRED); + sinon.stub(portScanner, "checkPortStatus").callsArgWith(1, null, TEST_PORT_STATUS_CLOSED); + sinon.stub(process, "env"); + process.env.ASK_LWA_AUTHORIZE_HOST = TEST_ASK_LWA_AUTHORIZE_HOST; + sinon.stub(LocalHostServer.prototype, "listen"); + sinon.stub(LocalHostServer.prototype, "registerEvent"); + const requestDestroyStub = sinon.stub(); + const request = { + url: "/captcha?success", + socket: { + destroy: requestDestroyStub, + }, + }; + sinon.stub(SpinnerView.prototype, "terminate"); + sinon.stub(LocalHostServer.prototype, "destroy"); + sinon.stub(LocalHostServer.prototype, "create").callsArgWith(0, request, response); + const TEST_CAPTCHA_SUCCESS = "CAPTCHA validation was successful. Please close the browser and return to the command line interface."; + hostedSkillPermissionStub.onCall(1).callsArgWith(2, null, TEST_PERMISSION_ALLOWED); + // call + proxyHelper.validateUserQualification(TEST_VENDOR_ID, HostedSkillController.prototype, (err: Error | null) => { + // verify + expect(endStub.callCount).eq(1); + expect(endStub.args[0][0]).eq(TEST_CAPTCHA_SUCCESS); + expect(infoStub.args[2][0]).equal("CAPTCHA validation was successfully completed. You are able to create a Alexa hosted skill."); + expect(err).eq(null); + done(); + }); + }); + + it("| not new user check permission success, expect no error return", (done) => { + // setup + const hostedSkillPermissionStub = sinon.stub(HostedSkillController.prototype, "getHostedSkillPermission"); + hostedSkillPermissionStub.callsArgWith(2, null, TEST_PERMISSION_ALLOWED); + // call + proxyHelper.validateUserQualification(TEST_VENDOR_ID, HostedSkillController.prototype, (err: Error | null) => { + // verify + expect(err).eq(null); + done(); + }); + }); + }); + + describe("# test hosted skill helper method - createHostedSkill", () => { + const TEST_USER_INPUT: NewSkillUserInput = { + projectFolderName: TEST_FOLDER_NAME, + skillName: TEST_SKILL_NAME, + language: TEST_LANGUAGE, + }; + + beforeEach(() => {}); + + afterEach(() => { + sinon.restore(); + }); + + it("| hostedSkillController project already exists, expect error thrown", (done) => { + // setup + const TEST_PROJECT_PATH = "TEST_PROJECT_PATH"; + const pathJoinStub = sinon.stub(path, "join"); + pathJoinStub.returns(TEST_PROJECT_PATH); + const fsExistsSyncStub = sinon.stub(fs, "existsSync"); + fsExistsSyncStub.returns(true); + + // call + hostedSkillHelper.createHostedSkill(HostedSkillController.prototype, TEST_USER_INPUT, TEST_VENDOR_ID, (err, res) => { + + // verify + expect(res).equal(undefined); + expect(err?.message).equal(`${TEST_PROJECT_PATH} directory already exists.`); + done(); + }); + }); + + it("| hostedSkillController create skill fails, expect error thrown", (done) => { + // setup + sinon.stub(HostedSkillController.prototype, "createSkill").callsArgWith(1, TEST_ERROR); + const spinnerStartStub = sinon.stub(SpinnerView.prototype, "start"); + // call + hostedSkillHelper.createHostedSkill(HostedSkillController.prototype, TEST_USER_INPUT, TEST_VENDOR_ID, (err, res) => { + // verify + expect(spinnerStartStub.callCount).eq(1); + expect(spinnerStartStub.args[0][0]).eq("Creating your Alexa hosted skill. It will take about a minute."); + expect(res).equal(undefined); + expect(err).equal(TEST_ERROR); + done(); + }); + }); + + it("| hostedSkillController create skill response with skillId, expect error thrown", (done) => { + // setup + sinon.stub(HostedSkillController.prototype, "createSkill").callsArgWith(1, TEST_ERROR, TEST_SKILL_ID); + sinon.stub(SpinnerView.prototype, "start"); + sinon.stub(HostedSkillController.prototype, "deleteSkill").callsArgWith(1, undefined); + // call + hostedSkillHelper.createHostedSkill(HostedSkillController.prototype, TEST_USER_INPUT, TEST_VENDOR_ID, (err, res) => { + // verify + expect(res).equal(undefined); + expect(err).equal(TEST_ERROR); + done(); + }); + }); + + it("| hostedSkillController create skill succeed, updateAskSystemScripts fails, expect error thrown", (done) => { + // setup + sinon.stub(HostedSkillController.prototype, "createSkill").callsArgWith(1, null, TEST_SKILL_ID); + sinon.stub(SpinnerView.prototype, "start"); + sinon.stub(HostedSkillController.prototype, "updateAskSystemScripts").callsArgWith(0, TEST_ERROR); + // call + hostedSkillHelper.createHostedSkill(HostedSkillController.prototype, TEST_USER_INPUT, TEST_VENDOR_ID, (err, res) => { + // verify + expect(res).equal(undefined); + expect(err).equal(TEST_ERROR); + done(); + }); + }); + + it("| hostedSkillController updateAskSystemScripts succeed, clone fails, expect error thrown", (done) => { + // setup + sinon.stub(HostedSkillController.prototype, "createSkill").callsArgWith(1, null, TEST_SKILL_ID); + sinon.stub(SpinnerView.prototype, "start"); + sinon.stub(HostedSkillController.prototype, "updateAskSystemScripts").callsArgWith(0, null); + sinon.stub(process, "cwd").returns("root/"); + sinon.stub(HostedSkillController.prototype, "clone").callsArgWith(3, TEST_ERROR); + // call + hostedSkillHelper.createHostedSkill(HostedSkillController.prototype, TEST_USER_INPUT, TEST_VENDOR_ID, (err, res) => { + // verify + expect(res).equal(undefined); + expect(err).equal(TEST_ERROR); + done(); + }); + }); + + it("| hostedSkillController clone succeed, enableSkill fails, expect error thrown", (done) => { + // setup + sinon.stub(HostedSkillController.prototype, "createSkill").callsArgWith(1, null, TEST_SKILL_ID); + sinon.stub(SpinnerView.prototype, "start"); + sinon.stub(HostedSkillController.prototype, "updateAskSystemScripts").callsArgWith(0, null); + sinon.stub(process, "cwd").returns("root/"); + sinon.stub(HostedSkillController.prototype, "clone").callsArgWith(3, null); + sinon.stub(SkillMetadataController.prototype, "enableSkill").yields(TEST_ERROR); + // call + hostedSkillHelper.createHostedSkill(HostedSkillController.prototype, TEST_USER_INPUT, TEST_VENDOR_ID, (err, res) => { + // verify + expect(res).equal(undefined); + expect(err).equal(TEST_ERROR); + done(); + }); + }); + + it("| hostedSkillController clone succeed, updateSkillPrePushScript fails, expect error thrown", (done) => { + // setup + sinon.stub(HostedSkillController.prototype, "createSkill").callsArgWith(1, null, TEST_SKILL_ID); + sinon.stub(SpinnerView.prototype, "start"); + sinon.stub(HostedSkillController.prototype, "updateAskSystemScripts").callsArgWith(0, null); + sinon.stub(process, "cwd").returns("root/"); + sinon.stub(HostedSkillController.prototype, "clone").callsArgWith(3, null); + sinon.stub(SkillMetadataController.prototype, "enableSkill").yields(); + sinon.stub(HostedSkillController.prototype, "updateSkillPrePushScript").callsArgWith(1, TEST_ERROR); + // call + hostedSkillHelper.createHostedSkill(HostedSkillController.prototype, TEST_USER_INPUT, TEST_VENDOR_ID, (err, res) => { + // verify + expect(res).equal(undefined); + expect(err).equal(TEST_ERROR); + done(); + }); + }); + + it("| hostedSkillController create skill succeed, clone succeed, expect skillId return", (done) => { + // setup + sinon.stub(HostedSkillController.prototype, "createSkill").callsArgWith(1, null, TEST_SKILL_ID); + sinon.stub(SpinnerView.prototype, "start"); + sinon.stub(HostedSkillController.prototype, "updateAskSystemScripts").callsArgWith(0, null); + sinon.stub(process, "cwd").returns("root/"); + sinon.stub(HostedSkillController.prototype, "clone").callsArgWith(3, null); + sinon.stub(SkillMetadataController.prototype, "enableSkill").yields(); + sinon.stub(HostedSkillController.prototype, "updateSkillPrePushScript").callsArgWith(1, null); + // call + hostedSkillHelper.createHostedSkill(HostedSkillController.prototype, TEST_USER_INPUT, TEST_VENDOR_ID, (err, res) => { + // verify + expect(res).equal(TEST_SKILL_ID); + expect(err).equal(null); + done(); + }); + }); + }); +}); diff --git a/test/unit/commands/new/index-test.js b/test/unit/commands/new/index-test.js deleted file mode 100644 index 2790f929..00000000 --- a/test/unit/commands/new/index-test.js +++ /dev/null @@ -1,321 +0,0 @@ -const { expect } = require('chai'); -const sinon = require('sinon'); -const path = require('path'); - -const NewCommand = require('@src/commands/new'); -const helper = require('@src/commands/new/helper'); -const hostedHelper = require('@src/commands/new/hosted-skill-helper'); -const optionModel = require('@src/commands/option-model'); -const ResourcesConfig = require('@src/model/resources-config'); -const Manifest = require('@src/model/manifest'); -const Messenger = require('@src/view/messenger'); -const profileHelper = require('@src/utils/profile-helper'); -const wizardHelper = require('@src/commands/new/wizard-helper'); -const CONSTANTS = require('@src/utils/constants'); - -describe('Commands new test - command class test', () => { - const FIXTURE_BASE_PATH = path.join(process.cwd(), 'test', 'unit', 'fixture', 'model'); - const FIXTURE_RESOURCES_CONFIG_FILE_PATH = path.join(FIXTURE_BASE_PATH, 'regular-proj', 'ask-resources.json'); - const FIXTURE_MANIFEST_FILE_PATH = path.join(FIXTURE_BASE_PATH, 'manifest.json'); - const FIXTURE_HOSTED_RESOURCES_CONFIG_FILE_PATH = path.join(FIXTURE_BASE_PATH, 'hosted-proj', 'ask-resources.json'); - const TEST_PROFILE = 'default'; - const TEST_VENDOR_ID = 'vendorId'; - const TEST_SKILL_ID = 'TEST_SKILL_ID'; - const TEST_SKILL_NAME = 'skillName'; - const TEST_PROJECT_PATH = 'projectPath'; - const TEST_ERROR = 'TEST_ERROR'; - const TEST_DEPLOYMENT_TYPE = '@ask-cli/cfn-deployer'; - const TEST_HOSTED_DEPLOYMENT = '@ask-cli/hosted-skill-deployer'; - const TEST_CMD = { - profile: TEST_PROFILE - }; - - let infoStub; - let errorStub; - let warnStub; - - beforeEach(() => { - infoStub = sinon.stub(); - errorStub = sinon.stub(); - warnStub = sinon.stub(); - sinon.stub(Messenger, 'getInstance').returns({ - info: infoStub, - error: errorStub, - warn: warnStub - }); - }); - - afterEach(() => { - sinon.restore(); - }); - - it('| validate command information is set correctly', () => { - const instance = new NewCommand(optionModel); - expect(instance.name()).equal('new'); - expect(instance.description()).equal('create a new skill project from Alexa skill templates'); - expect(instance.requiredOptions()).deep.equal([]); - expect(instance.optionalOptions()).deep.equal(['templateUrl', 'templateBranch', 'profile', 'debug']); - }); - - describe('validate command handle', () => { - describe('command handle - collect user creation Project Info', () => { - let instance; - - beforeEach(() => { - instance = new NewCommand(optionModel); - sinon.stub(profileHelper, 'runtimeProfile').returns(TEST_PROFILE); - sinon.stub(profileHelper, 'resolveVendorId').returns(TEST_PROFILE); - sinon.stub(wizardHelper, 'collectUserCreationProjectInfo'); - sinon.stub(hostedHelper, 'validateUserQualification'); - }); - - afterEach(() => { - sinon.restore(); - }); - - it('| when profile is not correct, expect throw error', (done) => { - // setup - profileHelper.runtimeProfile.throws(new Error('error')); - // call - instance.handle(TEST_CMD, (err) => { - // verify - expect(err.message).equal('error'); - expect(errorStub.args[0][0].message).equal('error'); - expect(infoStub.callCount).equal(0); - expect(warnStub.callCount).equal(0); - done(); - }); - }); - - it('| wizard helper collectUserCreationProjectInfo fails, expect error thrown', (done) => { - // setup - wizardHelper.collectUserCreationProjectInfo.callsArgWith(1, TEST_ERROR); - // call - instance.handle(TEST_CMD, (err) => { - // verify - expect(err).equal(TEST_ERROR); - expect(errorStub.args[0][0]).equal(TEST_ERROR); - expect(infoStub.args[0][0]).equal('Please follow the wizard to start your Alexa skill project ->'); - expect(warnStub.callCount).equal(0); - done(); - }); - }); - - it('| wizard helper collectUserCreationProjectInfo without user input, expect error thrown', (done) => { - // setup - wizardHelper.collectUserCreationProjectInfo.callsArgWith(1, null, null); - // call - instance.handle(TEST_CMD, (err, res) => { - // verify - expect(err).equal(undefined); - expect(res).equal(undefined); - expect(warnStub.callCount).equal(0); - done(); - }); - }); - }); - - describe('command handle - create hosted skill', () => { - let instance; - - beforeEach(() => { - instance = new NewCommand(optionModel); - sinon.stub(profileHelper, 'runtimeProfile').returns(TEST_PROFILE); - sinon.stub(profileHelper, 'resolveVendorId').returns(TEST_PROFILE); - sinon.stub(wizardHelper, 'collectUserCreationProjectInfo'); - sinon.stub(hostedHelper, 'validateUserQualification'); - sinon.stub(hostedHelper, 'createHostedSkill'); - new ResourcesConfig(FIXTURE_HOSTED_RESOURCES_CONFIG_FILE_PATH); - }); - - afterEach(() => { - sinon.restore(); - ResourcesConfig.dispose(); - }); - - it('| hosted helper validate user qualification fails, expect error thrown', (done) => { - // setup - const TEST_USER_INPUT = { - deploymentType: TEST_HOSTED_DEPLOYMENT - }; - wizardHelper.collectUserCreationProjectInfo.callsArgWith(1, null, TEST_USER_INPUT); - hostedHelper.validateUserQualification.callsArgWith(2, TEST_ERROR); - // call - instance.handle(TEST_CMD, (err) => { - // verify - expect(err).equal(TEST_ERROR); - expect(errorStub.args[0][0]).equal(TEST_ERROR); - expect(warnStub.callCount).equal(0); - done(); - }); - }); - - it('| hosted helper create hosted skill fails, expect error thrown', (done) => { - // setup - const TEST_USER_INPUT = { - deploymentType: TEST_HOSTED_DEPLOYMENT - }; - wizardHelper.collectUserCreationProjectInfo.callsArgWith(1, null, TEST_USER_INPUT); - hostedHelper.validateUserQualification.callsArgWith(2, null); - hostedHelper.createHostedSkill.callsArgWith(3, TEST_ERROR); - // call - instance.handle(TEST_CMD, (err) => { - // verify - expect(err).equal(TEST_ERROR); - expect(errorStub.args[0][0]).equal(TEST_ERROR); - expect(warnStub.callCount).equal(0); - done(); - }); - }); - - it('| hosted helper create hosted skill succeed, expect correct response', (done) => { - // setup - const TEST_USER_INPUT = { - deploymentType: TEST_HOSTED_DEPLOYMENT - }; - const GIT_USAGE_HOSTED_SKILL_DOCUMENTATION = 'https://developer.amazon.com/en-US/docs/alexa/' - + 'hosted-skills/build-a-skill-end-to-end-using-an-alexa-hosted-skill.html#askcli'; - wizardHelper.collectUserCreationProjectInfo.callsArgWith(1, null, TEST_USER_INPUT); - hostedHelper.validateUserQualification.callsArgWith(2, null); - hostedHelper.createHostedSkill.callsArgWith(3, null, TEST_SKILL_ID); - // call - instance.handle(TEST_CMD, (err) => { - // verify - expect(err).equal(undefined); - expect(infoStub.args[0][0]).equal('Please follow the wizard to start your Alexa skill project ->'); - expect(infoStub.args[1][0]).equal(`Hosted skill provisioning finished. Skill-Id: ${TEST_SKILL_ID}`); - expect(infoStub.args[2][0]).equal(`Please follow the instructions at ${CONSTANTS.GIT_USAGE_HOSTED_SKILL_DOCUMENTATION}` - + ' to learn more about the usage of "git" for Hosted skill.'); - expect(warnStub.callCount).equal(0); - done(); - }); - }); - }); - - describe('command handle - create non hosted skill', () => { - let instance; - - beforeEach(() => { - instance = new NewCommand(optionModel); - sinon.stub(profileHelper, 'runtimeProfile').returns(TEST_PROFILE); - sinon.stub(profileHelper, 'resolveVendorId').returns(TEST_VENDOR_ID); - sinon.stub(helper, 'loadSkillProjectModel'); - sinon.stub(helper, 'downloadTemplateFromGit'); - sinon.stub(helper, 'initializeDeployDelegate'); - sinon.stub(wizardHelper, 'collectUserCreationProjectInfo'); - sinon.stub(helper, 'updateSkillProjectWithUserSettings'); - new ResourcesConfig(FIXTURE_RESOURCES_CONFIG_FILE_PATH); - new Manifest(FIXTURE_MANIFEST_FILE_PATH); - }); - - afterEach(() => { - sinon.restore(); - ResourcesConfig.dispose(); - Manifest.dispose(); - }); - - it('| download template From git fails, expect error thrown', (done) => { - // setup - const TEST_USER_INPUT = {}; - wizardHelper.collectUserCreationProjectInfo.callsArgWith(1, null, TEST_USER_INPUT); - helper.downloadTemplateFromGit.callsArgWith(2, TEST_ERROR); - // call - instance.handle(TEST_CMD, (err) => { - // verify - expect(err).equal(TEST_ERROR); - expect(errorStub.args[0][0]).equal(TEST_ERROR); - expect(warnStub.callCount).equal(0); - done(); - }); - }); - - it('| load skill project model fails, expect error thrown', (done) => { - // setup - const TEST_USER_INPUT = {}; - wizardHelper.collectUserCreationProjectInfo.callsArgWith(1, null, TEST_USER_INPUT); - helper.downloadTemplateFromGit.callsArgWith(2, null); - helper.loadSkillProjectModel.throws(new Error(TEST_ERROR)); - // call - instance.handle(TEST_CMD, (err) => { - // verify - expect(err.message).equal(TEST_ERROR); - expect(errorStub.args[0][0].message).equal(TEST_ERROR); - expect(warnStub.callCount).equal(0); - done(); - }); - }); - - it('| update skill project with user settings fails, expect error thrown', (done) => { - // setup - const TEST_USER_INPUT = {}; - wizardHelper.collectUserCreationProjectInfo.callsArgWith(1, null, TEST_USER_INPUT); - helper.downloadTemplateFromGit.callsArgWith(2, null); - helper.updateSkillProjectWithUserSettings.throws(new Error(TEST_ERROR)); - // call - instance.handle(TEST_CMD, (err) => { - // verify - expect(err.message).equal(TEST_ERROR); - expect(errorStub.args[0][0].message).equal(TEST_ERROR); - expect(warnStub.callCount).equal(0); - done(); - }); - }); - - it('| initialize Deploy Delegate fails, expect error thrown', (done) => { - // setup - const TEST_USER_INPUT = {}; - wizardHelper.collectUserCreationProjectInfo.callsArgWith(1, null, TEST_USER_INPUT); - helper.downloadTemplateFromGit.callsArgWith(2, null); - helper.initializeDeployDelegate.callsArgWith(4, TEST_ERROR); - // call - instance.handle(TEST_CMD, (err) => { - // verify - expect(err).equal(TEST_ERROR); - expect(errorStub.args[0][0]).equal(TEST_ERROR); - expect(warnStub.callCount).equal(0); - done(); - }); - }); - - it('| create Non Hosted Skill succeed, expect correct response', (done) => { - // setup - const TEST_USER_INPUT = { - skillName: TEST_SKILL_NAME - }; - wizardHelper.collectUserCreationProjectInfo.callsArgWith(1, null, TEST_USER_INPUT); - helper.downloadTemplateFromGit.callsArgWith(2, null, TEST_PROJECT_PATH); - helper.initializeDeployDelegate.callsArgWith(4, null, TEST_DEPLOYMENT_TYPE); - // call - instance.handle(TEST_CMD, (err) => { - // verify - expect(err).equal(undefined); - expect(infoStub.args[0][0]).equal('Please follow the wizard to start your Alexa skill project ->'); - expect(infoStub.args[1][0]).equal(`Project for skill "${TEST_SKILL_NAME}" is successfully created at ${TEST_PROJECT_PATH}\n`); - expect(infoStub.args[2][0]).equal(`Project initialized with deploy delegate "${TEST_DEPLOYMENT_TYPE}" successfully.`); - expect(warnStub.callCount).equal(0); - done(); - }); - }); - - it('| create Non Hosted Skill without deployment type succeed, expect correct response', (done) => { - // setup - const TEST_USER_INPUT = { - skillName: TEST_SKILL_NAME - }; - wizardHelper.collectUserCreationProjectInfo.callsArgWith(1, null, TEST_USER_INPUT); - helper.downloadTemplateFromGit.callsArgWith(2, null, TEST_PROJECT_PATH); - helper.initializeDeployDelegate.callsArgWith(4, null, null); - // call - instance.handle(TEST_CMD, (err) => { - // verify - expect(err).equal(undefined); - expect(infoStub.args[0][0]).equal('Please follow the wizard to start your Alexa skill project ->'); - expect(infoStub.args[1][0]).equal(`Project for skill "${TEST_SKILL_NAME}" is successfully created at ${TEST_PROJECT_PATH}\n`); - expect(infoStub.args[2][0]).equal('Project initialized successfully.'); - expect(warnStub.callCount).equal(0); - done(); - }); - }); - }); - }); -}); diff --git a/test/unit/commands/new/index-test.ts b/test/unit/commands/new/index-test.ts new file mode 100644 index 00000000..3a717eb8 --- /dev/null +++ b/test/unit/commands/new/index-test.ts @@ -0,0 +1,292 @@ +import {expect} from "chai"; +import sinon from "sinon"; +import path from "path"; +import NewCommand from "../../../../lib/commands/new"; +import * as helper from "../../../../lib/commands/new/helper"; +import * as hostedHelper from "../../../../lib/commands/new/hosted-skill-helper"; +import optionModel from "../../../../lib/commands/option-model.json"; +import ResourcesConfig from "../../../../lib/model/resources-config"; +import Manifest from "../../../../lib/model/manifest"; +import Messenger from "../../../../lib/view/messenger"; +import profileHelper from "../../../../lib/utils/profile-helper"; +import * as wizardHelper from "../../../../lib/commands/new/wizard-helper"; +import CONSTANTS from "../../../../lib/utils/constants"; +import {OptionModel} from "../../../../lib/commands/option-validator"; + +describe("Commands new test - command class test", () => { + const FIXTURE_BASE_PATH = path.join(process.cwd(), "test", "unit", "fixture", "model"); + const FIXTURE_RESOURCES_CONFIG_FILE_PATH = path.join(FIXTURE_BASE_PATH, "regular-proj", "ask-resources.json"); + const FIXTURE_MANIFEST_FILE_PATH = path.join(FIXTURE_BASE_PATH, "manifest.json"); + const FIXTURE_HOSTED_RESOURCES_CONFIG_FILE_PATH = path.join(FIXTURE_BASE_PATH, "hosted-proj", "ask-resources.json"); + const TEST_PROFILE = "default"; + const TEST_VENDOR_ID = "vendorId"; + const TEST_SKILL_ID = "TEST_SKILL_ID"; + const TEST_SKILL_NAME = "skillName"; + const TEST_PROJECT_PATH = "projectPath"; + const TEST_ERROR = Error("TEST_ERROR"); + const TEST_DEPLOYMENT_TYPE = "@ask-cli/cfn-deployer"; + const TEST_HOSTED_DEPLOYMENT = "@ask-cli/hosted-skill-deployer"; + const TEST_CMD = { + profile: TEST_PROFILE, + }; + + let infoStub: sinon.SinonStub; + let errorStub: sinon.SinonStub; + let warnStub: sinon.SinonStub; + + beforeEach(() => { + infoStub = sinon.stub(); + errorStub = sinon.stub(); + warnStub = sinon.stub(); + sinon.stub(Messenger, "getInstance").returns({ + info: infoStub, + error: errorStub, + warn: warnStub, + }); + }); + + afterEach(() => { + sinon.restore(); + }); + + it("| validate command information is set correctly", () => { + const instance = new NewCommand(optionModel as OptionModel); + expect(instance.name()).equal("new"); + expect(instance.description()).equal("create a new skill project from Alexa skill templates"); + expect(instance.requiredOptions()).deep.equal([]); + expect(instance.optionalOptions()).deep.equal(["templateUrl", "templateBranch", "profile", "debug"]); + }); + + describe("validate command handle", () => { + describe("command handle - collect user creation Project Info", () => { + let instance: NewCommand; + let profileRuntimeProfileStub: sinon.SinonStub; + let wizardHelperStub: sinon.SinonStub; + + beforeEach(() => { + instance = new NewCommand(optionModel as OptionModel); + profileRuntimeProfileStub = sinon.stub(profileHelper, "runtimeProfile").returns(TEST_PROFILE); + sinon.stub(profileHelper, "resolveVendorId").returns(TEST_PROFILE); + wizardHelperStub = sinon.stub(wizardHelper, "collectUserCreationProjectInfo"); + sinon.stub(hostedHelper, "validateUserQualification"); + }); + + afterEach(() => { + sinon.restore(); + }); + + it("| when profile is not correct, expect throw error", async () => { + // setup + profileRuntimeProfileStub.throws(TEST_ERROR); + // call + await expect(instance.handle(TEST_CMD)).rejectedWith(TEST_ERROR); + // verify + expect(errorStub).calledOnceWith(TEST_ERROR); + expect(infoStub).not.called; + expect(warnStub).not.called; + }); + + it("| wizard helper collectUserCreationProjectInfo fails, expect error thrown", async () => { + // setup + wizardHelperStub.callsArgWith(1, TEST_ERROR); + // call + await expect(instance.handle(TEST_CMD)).rejectedWith(TEST_ERROR); + // verify + expect(errorStub).calledOnceWith(TEST_ERROR); + expect(infoStub).calledOnceWith("Please follow the wizard to start your Alexa skill project ->"); + expect(warnStub).not.called; + }); + + it("| wizard helper collectUserCreationProjectInfo without user input, expect error thrown", async () => { + // setup + wizardHelperStub.callsArgWith(1, null, null); + // call + + await expect(instance.handle(TEST_CMD)).fulfilled; + // verify + expect(warnStub).not.called; + }); + }); + + describe("command handle - create hosted skill", () => { + let instance: NewCommand; + let wizardHelperStub: sinon.SinonStub; + let hostedHelperStub: sinon.SinonStub; + let hostedHelperCreateHostedStub: sinon.SinonStub; + + beforeEach(() => { + instance = new NewCommand(optionModel as OptionModel); + sinon.stub(profileHelper, "runtimeProfile").returns(TEST_PROFILE); + sinon.stub(profileHelper, "resolveVendorId").returns(TEST_PROFILE); + wizardHelperStub = sinon.stub(wizardHelper, "collectUserCreationProjectInfo"); + hostedHelperStub = sinon.stub(hostedHelper, "validateUserQualification"); + hostedHelperCreateHostedStub = sinon.stub(hostedHelper, "createHostedSkill"); + new ResourcesConfig(FIXTURE_HOSTED_RESOURCES_CONFIG_FILE_PATH); + }); + + afterEach(() => { + sinon.restore(); + ResourcesConfig.dispose(); + }); + + it("| hosted helper validate user qualification fails, expect error thrown", async () => { + // setup + const TEST_USER_INPUT = { + deploymentType: TEST_HOSTED_DEPLOYMENT, + }; + wizardHelperStub.callsArgWith(1, null, TEST_USER_INPUT); + hostedHelperStub.callsArgWith(2, TEST_ERROR); + // call + await expect(instance.handle(TEST_CMD)).rejectedWith(TEST_ERROR); + // verify + expect(errorStub).calledOnceWith(TEST_ERROR); + expect(warnStub).not.called; + }); + + it("| hosted helper create hosted skill fails, expect error thrown", async () => { + // setup + const TEST_USER_INPUT = { + deploymentType: TEST_HOSTED_DEPLOYMENT, + }; + wizardHelperStub.callsArgWith(1, null, TEST_USER_INPUT); + hostedHelperStub.callsArgWith(2, null); + hostedHelperCreateHostedStub.callsArgWith(3, TEST_ERROR); + // call + await expect(instance.handle(TEST_CMD)).rejectedWith(TEST_ERROR); + // verify + expect(errorStub).calledOnceWith(TEST_ERROR); + expect(warnStub).not.called; + }); + + it("| hosted helper create hosted skill succeed, expect correct response", async () => { + // setup + const TEST_USER_INPUT = { + deploymentType: TEST_HOSTED_DEPLOYMENT, + }; + wizardHelperStub.callsArgWith(1, null, TEST_USER_INPUT); + hostedHelperStub.callsArgWith(2, null); + hostedHelperCreateHostedStub.callsArgWith(3, null, TEST_SKILL_ID); + // call + await instance.handle(TEST_CMD); + // verify + expect(errorStub).not.called; + expect(infoStub.getCall(0)).calledWith("Please follow the wizard to start your Alexa skill project ->"); + expect(infoStub.getCall(1)).calledWith(`Hosted skill provisioning finished. Skill-Id: ${TEST_SKILL_ID}`); + expect(infoStub.getCall(2)).calledWith( + `Please follow the instructions at ${CONSTANTS.GIT_USAGE_HOSTED_SKILL_DOCUMENTATION}` + + ' to learn more about the usage of "git" for Hosted skill.', + ); + expect(warnStub).not.called; + }); + }); + + describe("command handle - create non hosted skill", () => { + let instance: NewCommand; + let wizardHelperStub: sinon.SinonStub; + let helperLoadSkillStub: sinon.SinonStub; + let helperDownloadSkillStub: sinon.SinonStub; + let helperUploadSkill: sinon.SinonStub; + let helperInitialize: sinon.SinonStub; + + beforeEach(() => { + instance = new NewCommand(optionModel as OptionModel); + sinon.stub(profileHelper, "runtimeProfile").returns(TEST_PROFILE); + sinon.stub(profileHelper, "resolveVendorId").returns(TEST_VENDOR_ID); + helperLoadSkillStub = sinon.stub(helper, "loadSkillProjectModel"); + helperDownloadSkillStub = sinon.stub(helper, "downloadTemplateFromGit"); + helperInitialize = sinon.stub(helper, "initializeDeployDelegate"); + wizardHelperStub = sinon.stub(wizardHelper, "collectUserCreationProjectInfo"); + helperUploadSkill = sinon.stub(helper, "updateSkillProjectWithUserSettings"); + new ResourcesConfig(FIXTURE_RESOURCES_CONFIG_FILE_PATH); + new Manifest(FIXTURE_MANIFEST_FILE_PATH); + }); + + afterEach(() => { + sinon.restore(); + ResourcesConfig.dispose(); + Manifest.dispose(); + }); + + it("| download template From git fails, expect error thrown", async () => { + // setup + const TEST_USER_INPUT = {}; + wizardHelperStub.callsArgWith(1, null, TEST_USER_INPUT); + helperDownloadSkillStub.callsArgWith(2, TEST_ERROR); + // call + await expect(instance.handle(TEST_CMD)).rejectedWith(TEST_ERROR); + expect(errorStub).calledOnceWith(TEST_ERROR); + expect(warnStub).not.called; + }); + + it("| load skill project model fails, expect error thrown", async () => { + // setup + const TEST_USER_INPUT = {}; + wizardHelperStub.callsArgWith(1, null, TEST_USER_INPUT); + helperDownloadSkillStub.callsArgWith(2, null); + helperLoadSkillStub.throws(TEST_ERROR); + // call + await expect(instance.handle(TEST_CMD)).rejectedWith(TEST_ERROR); + expect(errorStub).calledOnceWith(TEST_ERROR); + expect(warnStub).not.called; + }); + + it("| update skill project with user settings fails, expect error thrown", async () => { + // setup + const TEST_USER_INPUT = {}; + wizardHelperStub.callsArgWith(1, null, TEST_USER_INPUT); + helperDownloadSkillStub.callsArgWith(2, null); + helperUploadSkill.throws(TEST_ERROR); + // call + await expect(instance.handle(TEST_CMD)).rejectedWith(TEST_ERROR); + expect(errorStub).calledOnceWith(TEST_ERROR); + expect(warnStub).not.called; + }); + + it("| initialize Deploy Delegate fails, expect error thrown", async () => { + // setup + const TEST_USER_INPUT = {}; + wizardHelperStub.callsArgWith(1, null, TEST_USER_INPUT); + helperDownloadSkillStub.callsArgWith(2, null); + helperInitialize.callsArgWith(4, TEST_ERROR); + // call + await expect(instance.handle(TEST_CMD)).rejectedWith(TEST_ERROR); + expect(errorStub).calledOnceWith(TEST_ERROR); + expect(warnStub).not.called; + }); + + it("| create Non Hosted Skill succeed, expect correct response", async () => { + // setup + const TEST_USER_INPUT = { + skillName: TEST_SKILL_NAME, + }; + wizardHelperStub.callsArgWith(1, null, TEST_USER_INPUT); + helperDownloadSkillStub.callsArgWith(2, null, TEST_PROJECT_PATH); + helperInitialize.callsArgWith(4, null, TEST_DEPLOYMENT_TYPE); + // call + await instance.handle(TEST_CMD); + + expect(infoStub.getCall(0)).calledWith("Please follow the wizard to start your Alexa skill project ->"); + expect(infoStub.getCall(1)).calledWith(`Project for skill "${TEST_SKILL_NAME}" is successfully created at ${TEST_PROJECT_PATH}\n`); + expect(infoStub.getCall(2)).calledWith(`Project initialized with deploy delegate "${TEST_DEPLOYMENT_TYPE}" successfully.`); + expect(warnStub).not.called; + }); + + it("| create Non Hosted Skill without deployment type succeed, expect correct response", async () => { + // setup + const TEST_USER_INPUT = { + skillName: TEST_SKILL_NAME, + }; + wizardHelperStub.callsArgWith(1, null, TEST_USER_INPUT); + helperDownloadSkillStub.callsArgWith(2, null, TEST_PROJECT_PATH); + helperInitialize.callsArgWith(4, null, null); + // call + await instance.handle(TEST_CMD); + + expect(infoStub.getCall(0)).calledWith("Please follow the wizard to start your Alexa skill project ->"); + expect(infoStub.getCall(1)).calledWith(`Project for skill "${TEST_SKILL_NAME}" is successfully created at ${TEST_PROJECT_PATH}\n`); + expect(infoStub.getCall(2)).calledWith("Project initialized successfully."); + expect(warnStub).not.called; + }); + }); + }); +}); diff --git a/test/unit/commands/new/template-helper-test.ts b/test/unit/commands/new/template-helper-test.ts new file mode 100644 index 00000000..a4e80a93 --- /dev/null +++ b/test/unit/commands/new/template-helper-test.ts @@ -0,0 +1,153 @@ +import {expect, assert} from "chai"; +import {beforeEach} from "mocha"; +import sinon from "sinon"; +import httpClient from "../../../../lib/clients/http-client"; +import { + CODE_LANGUAGE_JAVA, + CODE_LANGUAGE_NODEJS, + CODE_LANGUAGE_PYTHON, + MODELING_STACK_AC, + MODELING_STACK_IM, +} from "../../../../lib/commands/new"; +import {getSampleTemplatesFromS3, convertUserInputToFilterValue} from "../../../../lib/commands/new/template-helper"; +import {SampleTemplate} from "../../../../lib/model/sample-template"; +import {DEPLOYER_TYPE} from "../../../../lib/utils/constants"; + +export const TEST_SKILL_MODEL_TYPE_IM = "im"; +export const TEST_SKILL_MODEL_TYPE_AC = "ac"; +export const TEST_DEPLOY_TYPE_HOSTED = "hosted"; +export const TEST_DEPLOY_TYPE_CFN = "cfn"; +export const TEST_DEPLOY_TYPE_LAMBDA = "lambda"; +export const TEST_LANGUAGE_TYPE_NODE = "node"; +export const TEST_LANGUAGE_TYPE_PYTHON = "python"; +export const TEST_LANGUAGE_TYPE_JAVA = "java"; +export const TEST_SAMPLE_NAME_1 = "foo"; +export const TEST_SAMPLE_NAME_2 = "bar"; +export const TEST_SAMPLE_DESCRIPTION_1 = `${TEST_SAMPLE_NAME_1} is not ${TEST_SAMPLE_NAME_2}`; +export const TEST_SAMPLE_DESCRIPTION_2 = `${TEST_SAMPLE_NAME_2} is not ${TEST_SAMPLE_NAME_1}`; +export const TEST_SAMPLE_1_IM_HOSTED_NODE: SampleTemplate = { + stack: TEST_SKILL_MODEL_TYPE_IM, + deploy: TEST_DEPLOY_TYPE_HOSTED, + lang: TEST_LANGUAGE_TYPE_NODE, + name: TEST_SAMPLE_NAME_1, + url: "https://github.com/alexa/foo.git", + desc: TEST_SAMPLE_DESCRIPTION_1, + branch: "branch1", +}; +export const TEST_SAMPLE_2_AC_CFN_PYTHON: SampleTemplate = { + stack: TEST_SKILL_MODEL_TYPE_AC, + deploy: TEST_DEPLOY_TYPE_CFN, + lang: TEST_LANGUAGE_TYPE_PYTHON, + name: TEST_SAMPLE_NAME_2, + url: "https://github.com/alexa/bar.git", + desc: TEST_SAMPLE_DESCRIPTION_2, +}; +export const TEST_SAMPLE_IM_LAMBDA_JAVA: SampleTemplate = { + stack: TEST_SKILL_MODEL_TYPE_IM, + deploy: TEST_DEPLOY_TYPE_LAMBDA, + lang: TEST_LANGUAGE_TYPE_JAVA, + name: TEST_SAMPLE_NAME_2, + url: "https://github.com/alexa/bar.git", + desc: TEST_SAMPLE_DESCRIPTION_2, +}; +const TEST_TEMPLATES = JSON.stringify({templates: [TEST_SAMPLE_1_IM_HOSTED_NODE, TEST_SAMPLE_2_AC_CFN_PYTHON]}); + +describe("Commands new test - template helper test", () => { + describe("getSampleTemplatesFromS3", () => { + const TEST_SAMPLE_TEMPLATE_S3_FILE_CONTENT = { + body: TEST_TEMPLATES, + statusCode: 200, + headers: {}, + }; + const TEST_HTTP_RESPONSE_400_ERROR = { + statusCode: 400, + headers: {}, + }; + + let httpRequestStub: sinon.SinonStub; + let doDebug: boolean; + + beforeEach(() => { + httpRequestStub = sinon.stub(httpClient, "request"); + doDebug = false; + }); + + afterEach(() => { + sinon.restore(); + }); + + it("| fetches the sample templates from S3", async () => { + httpRequestStub.callsArgWith(3, null, TEST_SAMPLE_TEMPLATE_S3_FILE_CONTENT); + await getSampleTemplatesFromS3(doDebug).then((samples) => { + expect(samples.length).to.equals(2); + const template1 = samples.find((s) => s.name === TEST_SAMPLE_NAME_1); + const template2 = samples.find((s) => s.name === TEST_SAMPLE_NAME_2); + expect(template1).to.deep.equals(TEST_SAMPLE_1_IM_HOSTED_NODE); + expect(template2).to.deep.equals(TEST_SAMPLE_2_AC_CFN_PYTHON); + }); + }); + + it("| returns simplified error when debug is enabled and http request fails", async () => { + httpRequestStub.callsArgWith(3, null, TEST_HTTP_RESPONSE_400_ERROR); + doDebug = true; + + await getSampleTemplatesFromS3(doDebug) + .then(() => assert.fail("http 400 errors should reject the promise while dodebug is true")) + .catch((e) => { + expect(e.message).to.equals("Failed to retrieve the skill sample templates."); + }); + }); + + it("| returns longer error message explaining to enable debug if debug is not enabled and http request fails", async () => { + httpRequestStub.callsArgWith(3, null, TEST_HTTP_RESPONSE_400_ERROR); + doDebug = false; + + await getSampleTemplatesFromS3(doDebug) + .then(() => assert.fail("http 400 errors should reject the promise while dodebug is false")) + .catch((e) => { + expect(e.message).to.equals("Failed to retrieve the skill sample templates. Please run again with --debug to see the details."); + }); + }); + + it("| returns the error message when http request returns an error", async () => { + httpRequestStub.callsArgWith(3, new Error("secret failures"), null); + + await getSampleTemplatesFromS3(doDebug) + .then(() => assert.fail("http errors should reject the promise")) + .catch((e) => { + expect(e.message).to.contain("Failed to retrieve the skill sample templates."); + expect(e.message).not.to.contain("secret failures"); + }); + }); + }); + + describe("convertUserInputToFilterValue", () => { + it("should convert values to correct mapping", () => { + expect(convertUserInputToFilterValue(MODELING_STACK_IM)).to.equal("im"); + expect(convertUserInputToFilterValue(MODELING_STACK_AC)).to.equal("ac"); + expect(convertUserInputToFilterValue(CODE_LANGUAGE_NODEJS)).to.equal("node"); + expect(convertUserInputToFilterValue(CODE_LANGUAGE_PYTHON)).to.equal("python"); + expect(convertUserInputToFilterValue(CODE_LANGUAGE_JAVA)).to.equal("java"); + expect(convertUserInputToFilterValue(DEPLOYER_TYPE.LAMBDA.NAME)).to.equal("lambda"); + expect(convertUserInputToFilterValue(DEPLOYER_TYPE.CFN.NAME)).to.equal("cfn"); + expect(convertUserInputToFilterValue(DEPLOYER_TYPE.HOSTED.NAME)).to.equal("hosted"); + expect(convertUserInputToFilterValue(DEPLOYER_TYPE.SELF_HOSTED.NAME)).to.equal("self"); + }); + + it("should be case insensitive", () => { + expect(convertUserInputToFilterValue(MODELING_STACK_IM)).to.equal("im"); + expect(convertUserInputToFilterValue(MODELING_STACK_IM.toLowerCase())).to.equal("im"); + expect(convertUserInputToFilterValue(MODELING_STACK_IM.toUpperCase())).to.equal("im"); + }); + + it("should fail fast and throw and error if not identified", (done) => { + const fakeValue = "foo"; + try { + convertUserInputToFilterValue(fakeValue); + } catch (error: any) { + expect(error?.message).to.equal(`Unable to convert userInput '${fakeValue}' to a sample template filter value.`); + done(); + } + }); + }); +}); diff --git a/test/unit/commands/new/ui-test.js b/test/unit/commands/new/ui-test.js deleted file mode 100644 index 1b5e8ee5..00000000 --- a/test/unit/commands/new/ui-test.js +++ /dev/null @@ -1,415 +0,0 @@ -const { expect } = require('chai'); -const sinon = require('sinon'); -const inquirer = require('inquirer'); -const chalk = require('chalk'); - -const CONSTANTS = require('@src/utils/constants'); -const ui = require('@src/commands/new/ui'); - -function validateInquirerConfig(stub, expectedConfig) { - const { message, type, defaultValue, choices } = expectedConfig; - expect(stub.message).equal(message); - expect(stub.type).equal(type); - if (defaultValue) { - expect(stub.default).equal(defaultValue); - } - if (choices) { - expect(stub.choices).deep.equal(choices); - } -} - -describe('Commands new - UI test', () => { - const TEST_SKILL_NAME = 'skillName'; - const TEST_LOCALE = 'en-US'; - const TEST_REPO_NAME = 'repo'; - const TEST_FOLDER_NAME = 'folderName'; - const TEST_URL = `https://${TEST_REPO_NAME}.git?data=1`; - const TEST_ERROR = 'error'; - const TEST_LANGUAGE = 'language'; - const TEST_TEMPLATE_NAME = 'templateName'; - const TEST_CONFIRMATION = 'confirmation'; - const TEST_DEPLOYMENT_OPTION_NAME = 'HOSTED_OPTION_NAME'; - const TEST_DEPLOYMENT_NAME = 'HOSTED_NAME'; - const TEST_TEMPLATES_MAP = { - template1: { - url: 'templateUrl1', - description: 'templateDescription1' - }, - template2: { - url: 'templateUrl2' - } - }; - const TEST_DEPLOYMENT_MAP = { - HOSTED: { - OPTION_NAME: TEST_DEPLOYMENT_OPTION_NAME, - NAME: TEST_DEPLOYMENT_NAME, - DESCRIPTION: 'HOSTED_DESCRIPTION' - }, - CFN: { - OPTION_NAME: 'CFN_OPTION_NAME', - NAME: 'CFN_NAME', - DESCRIPTION: 'CFN_DESCRIPTION' - } - }; - const TEST_TEMPLATE_CHOICES = [ - `template1\n ${chalk.gray('templateDescription1')}`, - `template2\n ${chalk.gray('')}` - ]; - const TEST_DEPLOYMENT_CHOICES_WITH_SEP = [ - `${TEST_DEPLOYMENT_OPTION_NAME}\n ${chalk.gray('HOSTED_DESCRIPTION')}`, - `CFN_OPTION_NAME\n ${chalk.gray('CFN_DESCRIPTION')}`, - new inquirer.Separator(), - ui.SKIP_DEPLOY_DELEGATE_SELECTION - ]; - - describe('# validate ui.getSkillName', () => { - beforeEach(() => { - sinon.stub(inquirer, 'prompt'); - }); - - afterEach(() => { - sinon.restore(); - }); - - it('| getSkillName is set by user and inquirer throws exception', (done) => { - // setup - inquirer.prompt.rejects(new Error(TEST_ERROR)); - // call - ui.getSkillName(TEST_URL, (err, response) => { - // verify - validateInquirerConfig(inquirer.prompt.args[0][0][0], { - message: 'Please type in your skill name: ', - type: 'input', - default: TEST_REPO_NAME, - }); - expect(err.message).equal(TEST_ERROR); - expect(response).equal(undefined); - done(); - }); - }); - - it('| set defaultName as the default hosted skill name and return correctly', (done) => { - // setup - inquirer.prompt.resolves({ skillName: CONSTANTS.HOSTED_SKILL.DEFAULT_SKILL_NAME }); - // call - ui.getSkillName(null, (err, response) => { - // verify - validateInquirerConfig(inquirer.prompt.args[0][0][0], { - message: 'Please type in your skill name: ', - type: 'input', - default: TEST_REPO_NAME, - }); - expect(err).equal(null); - expect(response).equal(CONSTANTS.HOSTED_SKILL.DEFAULT_SKILL_NAME); - done(); - }); - }); - - it('| getSkillName is set by user and return correctly', (done) => { - // setup - inquirer.prompt.resolves({ skillName: TEST_SKILL_NAME }); - // call - ui.getSkillName(TEST_URL, (err, response) => { - // verify - validateInquirerConfig(inquirer.prompt.args[0][0][0], { - message: 'Please type in your skill name: ', - type: 'input', - default: TEST_REPO_NAME, - }); - expect(err).equal(null); - expect(response).equal(TEST_SKILL_NAME); - done(); - }); - }); - - it('| check the validate logic from inquirer and returns true', (done) => { - // setup - inquirer.prompt.resolves({ skillName: TEST_SKILL_NAME }); - // call - ui.getSkillName(TEST_URL, () => { - // verify - expect(inquirer.prompt.args[0][0][0].validate(' ')).equal('Skill name can\'t be empty.'); - done(); - }); - }); - - it('| check the validate logic from inquirer and returns error', (done) => { - // setup - inquirer.prompt.resolves({ skillName: TEST_SKILL_NAME }); - // call - ui.getSkillName(TEST_URL, () => { - // verify - expect(inquirer.prompt.args[0][0][0].validate('input')).equal(true); - done(); - }); - }); - }); - - describe('# validate ui.getSkillLocale', () => { - beforeEach(() => { - sinon.stub(inquirer, 'prompt'); - }); - - afterEach(() => { - sinon.restore(); - }); - - it('| getSkillLocale is set by user and inquirer throws exception', (done) => { - // setup - inquirer.prompt.rejects(new Error(TEST_ERROR)); - // call - ui.getSkillLocale((err, response) => { - // verify - expect(err.message).equal(TEST_ERROR); - expect(response).equal(undefined); - done(); - }); - }); - - it('| getSkillLocale is set by user and return correctly', (done) => { - // setup - inquirer.prompt.resolves({ locale: TEST_LOCALE }); - // call - ui.getSkillLocale((err, response) => { - // verify - expect(err).equal(null); - expect(response).equal(TEST_LOCALE); - done(); - }); - }); - }); - - describe('# validate ui.getSkillDefaultRegion', () => { - beforeEach(() => { - sinon.stub(inquirer, 'prompt'); - }); - - afterEach(() => { - sinon.restore(); - }); - - it('| getSkillDefaultRegion is set by user and inquirer throws exception', (done) => { - // setup - inquirer.prompt.rejects(new Error(TEST_ERROR)); - // call - ui.getSkillDefaultRegion((err, response) => { - // verify - expect(err.message).equal(TEST_ERROR); - expect(response).equal(undefined); - done(); - }); - }); - - it('| getSkillDefaultRegion is set by user and return correctly', (done) => { - // setup - inquirer.prompt.resolves({ region: 'us-east-1' }); - // call - ui.getSkillDefaultRegion((err, response) => { - // verify - expect(err).equal(null); - expect(response).equal('US_EAST_1'); - done(); - }); - }); - }); - - describe('# validate ui.selectSkillCodeLanguage', () => { - beforeEach(() => { - sinon.stub(inquirer, 'prompt'); - }); - - afterEach(() => { - sinon.restore(); - }); - - it('| language is retrieved correctly', (done) => { - // setup - inquirer.prompt.resolves({ language: TEST_LANGUAGE }); - // call - ui.selectSkillCodeLanguage((err, response) => { - // verify - validateInquirerConfig(inquirer.prompt.args[0][0][0], { - message: 'Choose the programming language you will use to code your skill: ', - type: 'list', - choices: Object.keys(CONSTANTS.TEMPLATES.PROJECT_BY_CODE_LANGUAGE) - }); - expect(err).equal(null); - expect(response).equal(TEST_LANGUAGE); - done(); - }); - }); - - it('| get language throws error from inquirer', (done) => { - // setup - inquirer.prompt.rejects(new Error(TEST_ERROR)); - // call - ui.selectSkillCodeLanguage((err, response) => { - // verify - validateInquirerConfig(inquirer.prompt.args[0][0][0], { - message: 'Choose the programming language you will use to code your skill: ', - type: 'list', - choices: Object.keys(CONSTANTS.TEMPLATES.PROJECT_BY_CODE_LANGUAGE) - }); - expect(err.message).equal(TEST_ERROR); - expect(response).equal(undefined); - done(); - }); - }); - }); - - describe('# validate ui.getTargetTemplateName', () => { - beforeEach(() => { - sinon.stub(inquirer, 'prompt'); - }); - - afterEach(() => { - sinon.restore(); - }); - - it('| template name is retrieved correctly', (done) => { - // setup - inquirer.prompt.resolves({ templateName: TEST_TEMPLATE_NAME }); - // call - ui.getTargetTemplateName(TEST_TEMPLATES_MAP, (err, response) => { - // verify - validateInquirerConfig(inquirer.prompt.args[0][0][0], { - message: 'Choose a template to start with: ', - type: 'list', - choices: TEST_TEMPLATE_CHOICES, - pageSize: 30 - }); - expect(inquirer.prompt.args[0][0][0].filter('a\nb')).equal('a'); - expect(err).equal(null); - expect(response).equal(TEST_TEMPLATE_NAME); - done(); - }); - }); - - it('| get template name throws error from inquirer', (done) => { - // setup - inquirer.prompt.rejects(new Error(TEST_ERROR)); - // call - ui.getTargetTemplateName(TEST_TEMPLATES_MAP, (err, response) => { - // verify - validateInquirerConfig(inquirer.prompt.args[0][0][0], { - message: 'Choose a template to start with: ', - type: 'list', - choices: TEST_TEMPLATE_CHOICES, - pageSize: 30 - }); - expect(inquirer.prompt.args[0][0][0].filter('a\nb')).equal('a'); - expect(err.message).equal(TEST_ERROR); - expect(response).equal(undefined); - done(); - }); - }); - }); - - describe('# validate ui.confirmUsingUnofficialTemplate', () => { - beforeEach(() => { - sinon.stub(inquirer, 'prompt'); - }); - - afterEach(() => { - sinon.restore(); - }); - - it('| confirmation entered by user is retrieved correctly', (done) => { - // setup - inquirer.prompt.resolves({ confirmation: TEST_CONFIRMATION }); - // call - ui.confirmUsingUnofficialTemplate((err, response) => { - // verify - validateInquirerConfig(inquirer.prompt.args[0][0][0], { - message: 'Would you like to continue download the skill template? ', - type: 'confirm', - default: false - }); - expect(err).equal(null); - expect(response).equal(TEST_CONFIRMATION); - done(); - }); - }); - - it('| get confirmation meets inquirer throws exception', (done) => { - // setup - inquirer.prompt.rejects(new Error(TEST_ERROR)); - // call - ui.confirmUsingUnofficialTemplate((err, response) => { - // verify - validateInquirerConfig(inquirer.prompt.args[0][0][0], { - message: 'Would you like to continue download the skill template? ', - type: 'confirm', - default: false - }); - expect(err.message).equal(TEST_ERROR); - expect(response).equal(undefined); - done(); - }); - }); - }); - - describe('# validate ui.getDeploymentType', () => { - beforeEach(() => { - sinon.stub(inquirer, 'prompt'); - }); - - afterEach(() => { - sinon.restore(); - }); - - it('| confirmation entered by user is retrieved correctly', (done) => { - // setup - inquirer.prompt.resolves({ deployDelegate: TEST_DEPLOYMENT_OPTION_NAME }); - // call - ui.getDeploymentType(TEST_DEPLOYMENT_MAP, (err, response) => { - // verify - validateInquirerConfig(inquirer.prompt.args[0][0][0], { - message: 'Choose a method to host your skill\'s backend resources: ', - type: 'list', - choices: TEST_DEPLOYMENT_CHOICES_WITH_SEP - }); - expect(inquirer.prompt.args[0][0][0].filter('a \n \n b')).equal('a '); - expect(err).equal(null); - expect(response).equal(TEST_DEPLOYMENT_NAME); - done(); - }); - }); - - it('| self-hosted confirmation entered by user is retrieved correctly', (done) => { - // setup - inquirer.prompt.resolves({ deployDelegate: ui.SKIP_DEPLOY_DELEGATE_SELECTION }); - // call - ui.getDeploymentType(TEST_DEPLOYMENT_MAP, (err, response) => { - // verify - validateInquirerConfig(inquirer.prompt.args[0][0][0], { - message: 'Choose a method to host your skill\'s backend resources: ', - type: 'list', - choices: TEST_DEPLOYMENT_CHOICES_WITH_SEP - }); - expect(inquirer.prompt.args[0][0][0].filter('a \n \n b')).equal('a '); - expect(err).equal(undefined); - expect(response).equal(undefined); - done(); - }); - }); - - it('| get confirmation meets inquirer throws exception', (done) => { - // setup - inquirer.prompt.rejects(new Error(TEST_ERROR)); - // call - ui.getDeploymentType(TEST_DEPLOYMENT_MAP, (err, response) => { - // verify - validateInquirerConfig(inquirer.prompt.args[0][0][0], { - message: 'Choose a method to host your skill\'s backend resources: ', - type: 'list', - choices: TEST_DEPLOYMENT_CHOICES_WITH_SEP - }); - expect(inquirer.prompt.args[0][0][0].filter('a \n \n b')).equal('a '); - expect(err.message).equal(TEST_ERROR); - expect(response).equal(undefined); - done(); - }); - }); - }); -}); diff --git a/test/unit/commands/new/ui-test.ts b/test/unit/commands/new/ui-test.ts new file mode 100644 index 00000000..047d772b --- /dev/null +++ b/test/unit/commands/new/ui-test.ts @@ -0,0 +1,477 @@ +import {expect} from "chai"; +import sinon, { SinonStub } from "sinon"; +import inquirer from "inquirer"; +import chalk from "chalk"; +import {HOSTED_SKILL} from "../../../../lib/utils/constants"; +import { + getSkillName, + getSkillDefaultRegion, + getSkillLocale, + selectSkillCodeLanguage, + getTargetTemplateName, + confirmUsingUnofficialTemplate, + getDeploymentType, + getModelingStackType, +} from "../../../../lib/commands/new/ui"; +import {SampleTemplate} from "../../../../lib/model/sample-template"; +import { CODE_LANGUAGE_JAVA, CODE_LANGUAGE_NODEJS, CODE_LANGUAGE_PYTHON } from "../../../../lib/commands/new"; + + +function validateInquirerConfig(stub: any, expectedConfig: { + message: string, + type: string, + defaultName?: string, + choices?: string[], + pageSize?: number}) { + const {message, type, defaultName, choices} = expectedConfig; + expect(stub.message).equal(message); + expect(stub.type).equal(type); + if (defaultName) { + expect(stub.default).equal(defaultName); + } + if (choices) { + expect(stub.choices).deep.equal(choices); + } +} + +describe("Commands new - UI test", () => { + const TEST_SKILL_NAME = "skillName"; + const TEST_LOCALE = "en-US"; + const TEST_REPO_NAME = "repo"; + const TEST_URL = `https://${TEST_REPO_NAME}.git?data=1`; + const TEST_ERROR = "error"; + const TEST_LANGUAGE = "language"; + const TEST_TEMPLATE_NAME = "templateName"; + const TEST_TEMPLATE_NAME_2 = "templateName42"; + const TEST_TEMPLATE_DESC = "templateDescription1"; + const TEST_TEMPLATE_DESC_2 = ""; + const TEST_CONFIRMATION = "confirmation"; + const TEST_DEPLOYMENT_OPTION_NAME = "HOSTED_OPTION_NAME"; + const TEST_DEPLOYMENT_NAME = "HOSTED_NAME"; + const TEST_TEMPLATE_1: SampleTemplate = { + url: "templateUrl1", + desc: TEST_TEMPLATE_DESC, + stack: "im", + deploy: "lambda", + lang: "node", + name: TEST_TEMPLATE_NAME, + }; + const TEST_TEMPALTE_2: SampleTemplate = { + url: "templateUrl2", + desc: TEST_TEMPLATE_DESC_2, + stack: "ac", + deploy: "cfn", + lang: "python", + name: TEST_TEMPLATE_NAME_2, + }; + const TEST_TEMPLATES_MAP: SampleTemplate[] = [TEST_TEMPLATE_1, TEST_TEMPALTE_2]; + const TEST_DEPLOYMENT_MAP = [ + { + OPTION_NAME: TEST_DEPLOYMENT_OPTION_NAME, + NAME: TEST_DEPLOYMENT_NAME, + DESCRIPTION: "HOSTED_DESCRIPTION", + },{ + OPTION_NAME: "CFN_OPTION_NAME", + NAME: "CFN_NAME", + DESCRIPTION: "CFN_DESCRIPTION", + } + ]; + const TEST_TEMPLATE_CHOICES = [ + `${TEST_TEMPLATE_NAME}\n ${chalk.gray(TEST_TEMPLATE_DESC)}`, + `${TEST_TEMPLATE_NAME_2}\n ${chalk.gray(TEST_TEMPLATE_DESC_2)}`]; + const TEST_DEPLOYMENT_CHOICES_WITH_SEP = [ + `${TEST_DEPLOYMENT_OPTION_NAME}\n ${chalk.gray("HOSTED_DESCRIPTION")}`, + `CFN_OPTION_NAME\n ${chalk.gray("CFN_DESCRIPTION")}`, + ]; + + describe("# validate getSkillName", () => { + let inquirerPrompt: SinonStub; + beforeEach(() => { + inquirerPrompt = sinon.stub(inquirer, "prompt"); + }); + + afterEach(() => { + sinon.restore(); + }); + + it("| getSkillName is set by user and inquirer throws exception", (done) => { + // setup + inquirerPrompt.rejects(new Error(TEST_ERROR)); + // call + getSkillName(TEST_URL, (err, response) => { + // verify + validateInquirerConfig(inquirerPrompt.args[0][0][0], { + message: "Please type in your skill name: ", + type: "input", + defaultName: TEST_REPO_NAME, + }); + expect(err?.message).equal(TEST_ERROR); + expect(response).equal(undefined); + done(); + }); + }); + + it("| set defaultName as the default hosted skill name and return correctly", (done) => { + // setup + inquirerPrompt.resolves({skillName: HOSTED_SKILL.DEFAULT_SKILL_NAME}); + // call + getSkillName(null, (err, response) => { + if (err) { + console.log("unexpected failure in callback: err: " + err.message); + } + // verify + validateInquirerConfig(inquirerPrompt.args[0][0][0], { + message: "Please type in your skill name: ", + type: "input", + defaultName: HOSTED_SKILL.DEFAULT_SKILL_NAME, + }); + expect(err).equal(null); + expect(response).equal(HOSTED_SKILL.DEFAULT_SKILL_NAME); + done(); + }); + }); + + it("| getSkillName is set by user and return correctly", (done) => { + // setup + inquirerPrompt.resolves({skillName: TEST_SKILL_NAME}); + // call + getSkillName(TEST_URL, (err, response) => { + if (err) { + console.log("unexpected failure in callback: err: " + err.message); + } + // verify + validateInquirerConfig(inquirerPrompt.args[0][0][0], { + message: "Please type in your skill name: ", + type: "input", + defaultName: TEST_REPO_NAME, + }); + expect(err).equal(null); + expect(response).equal(TEST_SKILL_NAME); + done(); + }); + }); + + it("| check the validate logic from inquirer and returns true", (done) => { + // setup + inquirerPrompt.resolves({skillName: TEST_SKILL_NAME}); + // call + getSkillName(TEST_URL, () => { + // verify + expect(inquirerPrompt.args[0][0][0].validate(" ")).equal("Skill name can't be empty."); + done(); + }); + }); + + it("| check the validate logic from inquirer and returns error", (done) => { + // setup + inquirerPrompt.resolves({skillName: TEST_SKILL_NAME}); + // call + getSkillName(TEST_URL, () => { + // verify + expect(inquirerPrompt.args[0][0][0].validate("input")).equal(true); + done(); + }); + }); + }); + + describe("# validate getSkillLocale", () => { + let inquirerPrompt: SinonStub; + beforeEach(() => { + inquirerPrompt = sinon.stub(inquirer, "prompt"); + }); + + afterEach(() => { + sinon.restore(); + }); + + it("| getSkillLocale is set by user and inquirer throws exception", (done) => { + // setup + inquirerPrompt.rejects(new Error(TEST_ERROR)); + // call + getSkillLocale((err, response) => { + // verify + expect(err?.message).equal(TEST_ERROR); + expect(response).equal(undefined); + done(); + }); + }); + + it("| getSkillLocale is set by user and return correctly", (done) => { + // setup + inquirerPrompt.resolves({locale: TEST_LOCALE}); + // call + getSkillLocale((err, response) => { + // verify + expect(err).equal(null); + expect(response).equal(TEST_LOCALE); + done(); + }); + }); + }); + + describe("# validate getSkillDefaultRegion", () => { + let inquirerPrompt: SinonStub; + beforeEach(() => { + inquirerPrompt = sinon.stub(inquirer, "prompt"); + }); + + afterEach(() => { + sinon.restore(); + }); + + it("| getSkillDefaultRegion is set by user and inquirer throws exception", (done) => { + // setup + inquirerPrompt.rejects(new Error(TEST_ERROR)); + // call + getSkillDefaultRegion((err, response) => { + // verify + expect(err?.message).equal(TEST_ERROR); + expect(response).equal(undefined); + done(); + }); + }); + + it("| getSkillDefaultRegion is set by user and return correctly", (done) => { + // setup + inquirerPrompt.resolves({region: "us-east-1"}); + // call + getSkillDefaultRegion((err, response) => { + // verify + expect(err).equal(null); + expect(response).equal("US_EAST_1"); + done(); + }); + }); + }); + + describe("# validate selectSkillCodeLanguage", () => { + let inquirerPrompt: SinonStub; + beforeEach(() => { + inquirerPrompt = sinon.stub(inquirer, "prompt"); + }); + + afterEach(() => { + sinon.restore(); + }); + + it("| language is retrieved correctly", (done) => { + // setup + inquirerPrompt.resolves({language: TEST_LANGUAGE}); + // call + selectSkillCodeLanguage([CODE_LANGUAGE_NODEJS, CODE_LANGUAGE_PYTHON, CODE_LANGUAGE_JAVA], (err, response) => { + // verify + validateInquirerConfig(inquirerPrompt.args[0][0][0], { + message: "Choose the programming language you will use to code your skill: ", + type: "list", + choices: [CODE_LANGUAGE_NODEJS, CODE_LANGUAGE_PYTHON, CODE_LANGUAGE_JAVA], + }); + expect(err).equal(null); + expect(response).equal(TEST_LANGUAGE); + done(); + }); + }); + + it("| get language throws error from inquirer", (done) => { + // setup + inquirerPrompt.rejects(new Error(TEST_ERROR)); + // call + selectSkillCodeLanguage([CODE_LANGUAGE_NODEJS, CODE_LANGUAGE_PYTHON, CODE_LANGUAGE_JAVA], (err, response) => { + // verify + validateInquirerConfig(inquirerPrompt.args[0][0][0], { + message: "Choose the programming language you will use to code your skill: ", + type: "list", + choices: [CODE_LANGUAGE_NODEJS, CODE_LANGUAGE_PYTHON, CODE_LANGUAGE_JAVA], + }); + expect(err?.message).equal(TEST_ERROR); + expect(response).equal(undefined); + done(); + }); + }); + }); + + describe("# validate getTargetTemplateName", () => { + let inquirerPrompt: SinonStub; + + beforeEach(() => { + inquirerPrompt = sinon.stub(inquirer, "prompt"); + }); + + afterEach(() => { + sinon.restore(); + }); + + it("| sample template is retrieved correctly", (done) => { + // setup + inquirerPrompt.resolves({templateName: TEST_TEMPLATE_NAME}); + // call + getTargetTemplateName(TEST_TEMPLATES_MAP, (err, response) => { + // verify + validateInquirerConfig(inquirerPrompt.args[0][0][0], { + message: "Choose a template to start with: ", + type: "list", + choices: TEST_TEMPLATE_CHOICES, + pageSize: 30, + }); + expect(inquirerPrompt.args[0][0][0].filter("a\nb")).equal("a"); + expect(err).equal(null); + expect(response).equal(TEST_TEMPLATE_1); + done(); + }); + }); + + it("| get template name throws error from inquirer", (done) => { + // setup + inquirerPrompt.rejects(new Error(TEST_ERROR)); + // call + getTargetTemplateName(TEST_TEMPLATES_MAP, (err, response) => { + // verify + validateInquirerConfig(inquirerPrompt.args[0][0][0], { + message: "Choose a template to start with: ", + type: "list", + choices: TEST_TEMPLATE_CHOICES, + pageSize: 30, + }); + expect(inquirerPrompt.args[0][0][0].filter("a\nb")).equal("a"); + expect(err?.message).equal(TEST_ERROR); + expect(response).equal(undefined); + done(); + }); + }); + }); + + describe("# validate confirmUsingUnofficialTemplate", () => { + let inquirerPrompt: SinonStub; + + beforeEach(() => { + inquirerPrompt = sinon.stub(inquirer, "prompt"); + }); + + afterEach(() => { + sinon.restore(); + }); + + it("| confirmation entered by user is retrieved correctly", (done) => { + // setup + inquirerPrompt.resolves({confirmation: TEST_CONFIRMATION}); + // call + confirmUsingUnofficialTemplate((err, response) => { + // verify + validateInquirerConfig(inquirerPrompt.args[0][0][0], { + message: "Would you like to continue download the skill template? ", + type: "confirm", + }); + expect(err).equal(null); + expect(response).equal(TEST_CONFIRMATION); + done(); + }); + }); + + it("| get confirmation meets inquirer throws exception", (done) => { + // setup + inquirerPrompt.rejects(new Error(TEST_ERROR)); + // call + confirmUsingUnofficialTemplate((err, response) => { + // verify + validateInquirerConfig(inquirerPrompt.args[0][0][0], { + message: "Would you like to continue download the skill template? ", + type: "confirm", + }); + expect(err?.message).equal(TEST_ERROR); + expect(response).equal(undefined); + done(); + }); + }); + }); + + describe("# validate getDeploymentType", () => { + let inquirerPrompt: SinonStub; + + beforeEach(() => { + inquirerPrompt = sinon.stub(inquirer, "prompt"); + }); + + afterEach(() => { + sinon.restore(); + }); + + it("| confirmation entered by user is retrieved correctly", (done) => { + // setup + inquirerPrompt.resolves({deployDelegate: TEST_DEPLOYMENT_OPTION_NAME}); + // call + getDeploymentType(TEST_DEPLOYMENT_MAP, (err, response) => { + // verify + validateInquirerConfig(inquirerPrompt.args[0][0][0], { + message: "Choose a method to host your skill's backend resources: ", + type: "list", + choices: TEST_DEPLOYMENT_CHOICES_WITH_SEP, + }); + expect(inquirerPrompt.args[0][0][0].filter("a \n \n b")).equal("a "); + expect(err).equal(null); + expect(response).equal(TEST_DEPLOYMENT_NAME); + done(); + }); + }); + + it("| get confirmation meets inquirer throws exception", (done) => { + // setup + inquirerPrompt.rejects(new Error(TEST_ERROR)); + // call + getDeploymentType(TEST_DEPLOYMENT_MAP, (err, response) => { + // verify + validateInquirerConfig(inquirerPrompt.args[0][0][0], { + message: "Choose a method to host your skill's backend resources: ", + type: "list", + choices: TEST_DEPLOYMENT_CHOICES_WITH_SEP, + }); + expect(inquirerPrompt.args[0][0][0].filter("a \n \n b")).equal("a "); + expect(err?.message).equal(TEST_ERROR); + expect(response).equal(undefined); + done(); + }); + }); + }); + + describe("| getModelingStackType", () => { + let inquirerPrompt: SinonStub; + + beforeEach(() => { + inquirerPrompt = sinon.stub(inquirer, "prompt"); + }); + + afterEach(() => { + sinon.restore(); + }); + + it("| getModelingStackType selected by user is retrieved correctly", (done) => { + // setup + inquirerPrompt.resolves({modelingStack: "Alexa Conversations"}); + // call + getModelingStackType((err, response) => { + // verify + validateInquirerConfig(inquirerPrompt.args[0][0][0], { + message: "Choose a modeling stack for your skill: ", + type: "list", + }); + expect(err).equal(null); + expect(response).equal("Alexa Conversations"); + done(); + }); + }); + + it("| getModelingStackType inquirer throws exception", (done) => { + // setup + inquirerPrompt.rejects(new Error(TEST_ERROR)); + // call + getModelingStackType((err, response) => { + // verify + validateInquirerConfig(inquirerPrompt.args[0][0][0], { + message: "Choose a modeling stack for your skill: ", + type: "list", + }); + expect(err?.message).equal(TEST_ERROR); + expect(response).equal(undefined); + done(); + }); + }); + }); +}); diff --git a/test/unit/commands/new/wizard-helper-test.js b/test/unit/commands/new/wizard-helper-test.js deleted file mode 100644 index 26c8b56c..00000000 --- a/test/unit/commands/new/wizard-helper-test.js +++ /dev/null @@ -1,283 +0,0 @@ -const { expect } = require('chai'); -const sinon = require('sinon'); - -const httpClient = require('@src/clients/http-client'); -const ui = require('@src/commands/new/ui'); -const urlUtils = require('@src/utils/url-utils'); -const wizardHelper = require('@src/commands/new/wizard-helper'); -const Messenger = require('@src/view/messenger'); - -describe('Commands new test - wizard helper test', () => { - const TEST_ERROR = 'TEST_ERROR'; - const TEST_OPTIONS = {}; - const TEST_LANGUAGE_RESPONSE = 'NodeJS'; - const TEST_DEPLOYMENT_TYPE = '@ask-cli/cfn-deployer'; - const TEST_HOSTED_DEPLOYMENT = '@ask-cli/hosted-skill-deployer'; - const TEST_TEMPLATE_URL = 'TEST_TEMPLATE_URL'; - const TEST_TEMPLATE_NAME = 'TEST_TEMPLATE_NAME'; - const TEST_SKILL_NAME = 'TEST_SKILL_NAME'; - const TEST_FOLDER_NAME = 'TEST_FOLDER_NAME'; - const TEST_TEMPLATE_MAP_STRING = `{"${TEST_TEMPLATE_NAME}":{"url":"${TEST_TEMPLATE_URL}"}}`; - const TEST_TEMPLATE_MAP = { - [TEST_TEMPLATE_NAME]: { - url: TEST_TEMPLATE_URL - } - }; - const TEST_OPTIONS_WITH_TEMPLATE = { - templateUrl: TEST_TEMPLATE_URL - }; - - let infoStub; - let errorStub; - let warnStub; - - beforeEach(() => { - infoStub = sinon.stub(); - errorStub = sinon.stub(); - warnStub = sinon.stub(); - sinon.stub(Messenger, 'getInstance').returns({ - info: infoStub, - error: errorStub, - warn: warnStub - }); - }); - - afterEach(() => { - sinon.restore(); - }); - describe('# test wizard helper method - collectUserCreationProjectInfo', () => { - beforeEach(() => { - sinon.stub(ui, 'selectSkillCodeLanguage'); - sinon.stub(ui, 'getDeploymentType'); - sinon.stub(ui, 'confirmUsingUnofficialTemplate'); - sinon.stub(urlUtils, 'isValidUrl'); - sinon.stub(urlUtils, 'isUrlOfficialTemplate'); - sinon.stub(httpClient, 'request'); - sinon.stub(ui, 'getTargetTemplateName'); - sinon.stub(ui, 'getSkillName'); - sinon.stub(ui, 'getProjectFolderName'); - sinon.stub(ui, 'getSkillDefaultRegion'); - sinon.stub(ui, 'getSkillLocale'); - ui.getSkillLocale.yields(null, 'en-US'); - ui.getSkillDefaultRegion.yields(0, null, 'US_EAST_1'); - }); - - afterEach(() => { - sinon.restore(); - }); - - it('| user input selectSkillCodeLanguage fails, expect throw error', (done) => { - // setup - ui.selectSkillCodeLanguage.callsArgWith(0, TEST_ERROR); - // call - wizardHelper.collectUserCreationProjectInfo(TEST_OPTIONS, (err) => { - // verify - expect(err).equal(TEST_ERROR); - done(); - }); - }); - - it('| user input getDeploymentType fails, expect throw error', (done) => { - // setup - ui.selectSkillCodeLanguage.callsArgWith(0, null, TEST_LANGUAGE_RESPONSE); - ui.getDeploymentType.callsArgWith(1, TEST_ERROR); - // call - wizardHelper.collectUserCreationProjectInfo(TEST_OPTIONS, (err) => { - // verify - expect(err).equal(TEST_ERROR); - done(); - }); - }); - - it.skip('| user input getSkillLocale fails, expect throw error', (done) => { - // setup - ui.selectSkillCodeLanguage.yields(null, TEST_LANGUAGE_RESPONSE); - ui.getDeploymentType.yields(null, TEST_HOSTED_DEPLOYMENT); - ui.getSkillLocale.yields(TEST_ERROR); - // call - wizardHelper.collectUserCreationProjectInfo(TEST_OPTIONS, (err) => { - // verify - expect(err).equal(TEST_ERROR); - done(); - }); - }); - - it('| user input getSkillDefaultRegion fails, expect throw error', (done) => { - // setup - ui.selectSkillCodeLanguage.yields(null, TEST_LANGUAGE_RESPONSE); - ui.getDeploymentType.yields(null, TEST_HOSTED_DEPLOYMENT); - ui.getSkillDefaultRegion.yields(TEST_ERROR); - // call - wizardHelper.collectUserCreationProjectInfo(TEST_OPTIONS, (err) => { - // verify - expect(err).equal(TEST_ERROR); - done(); - }); - }); - - it('| Hosted skills do not support Java, expect throw error', (done) => { - // setup - const TEST_HOSTED_ERROR = 'Alexa hosted skills don\'t support Java currently.'; - ui.selectSkillCodeLanguage.callsArgWith(0, null, 'Java'); - ui.getDeploymentType.callsArgWith(1, null, TEST_HOSTED_DEPLOYMENT); - // call - wizardHelper.collectUserCreationProjectInfo(TEST_OPTIONS, (err) => { - // verify - expect(err).equal(TEST_HOSTED_ERROR); - done(); - }); - }); - - it('| Hosted skills do not support custom template, expect throw error', (done) => { - // setup - const TEST_HOSTED_ERROR = 'No custom template allowed for an Alexa hosted skill.'; - ui.selectSkillCodeLanguage.callsArgWith(0, null, TEST_LANGUAGE_RESPONSE); - ui.getDeploymentType.callsArgWith(1, null, TEST_HOSTED_DEPLOYMENT); - // call - wizardHelper.collectUserCreationProjectInfo(TEST_OPTIONS_WITH_TEMPLATE, (err) => { - // verify - expect(err).equal(TEST_HOSTED_ERROR); - done(); - }); - }); - - it('| custom template should not valid url, expect throw error', (done) => { - // setup - const TEST_GIT_ERROR = `The provided template url ${TEST_TEMPLATE_URL} is not a valid url.`; - ui.selectSkillCodeLanguage.callsArgWith(0, null, TEST_LANGUAGE_RESPONSE); - ui.getDeploymentType.callsArgWith(1, null, TEST_DEPLOYMENT_TYPE); - urlUtils.isValidUrl.returns(false); - // call - wizardHelper.collectUserCreationProjectInfo(TEST_OPTIONS_WITH_TEMPLATE, (err) => { - // verify - expect(err).equal(TEST_GIT_ERROR); - done(); - }); - }); - - it('| user input confirmUsingUnofficialTemplate fails, expect throw error', (done) => { - // setup - ui.selectSkillCodeLanguage.callsArgWith(0, null, TEST_LANGUAGE_RESPONSE); - ui.getDeploymentType.callsArgWith(1, null, TEST_DEPLOYMENT_TYPE); - urlUtils.isValidUrl.returns(true); - urlUtils.isUrlOfficialTemplate.returns(false); - ui.confirmUsingUnofficialTemplate.callsArgWith(0, TEST_ERROR); - // call - wizardHelper.collectUserCreationProjectInfo(TEST_OPTIONS_WITH_TEMPLATE, (err) => { - // verify - expect(err).equal(TEST_ERROR); - expect(infoStub.callCount).equal(0); - expect(warnStub.callCount).equal(1); - done(); - }); - }); - - it('| users do not confirm using unofficial template, return without templateInfo, expect return directly', (done) => { - // setup - ui.selectSkillCodeLanguage.callsArgWith(0, null, TEST_LANGUAGE_RESPONSE); - ui.getDeploymentType.callsArgWith(1, null, TEST_DEPLOYMENT_TYPE); - urlUtils.isValidUrl.returns(true); - urlUtils.isUrlOfficialTemplate.returns(false); - ui.confirmUsingUnofficialTemplate.callsArgWith(0, null, false); - // call - wizardHelper.collectUserCreationProjectInfo(TEST_OPTIONS_WITH_TEMPLATE, (err, res) => { - // verify - expect(err).equal(undefined); - expect(res).equal(undefined); - expect(infoStub.callCount).equal(0); - expect(warnStub.callCount).equal(1); - done(); - }); - }); - - it('| new with official template, retrieve official template map fails, expect throw error', (done) => { - // setup - const TEST_HTTP_RESPONSE = { - statusCode: 300, - body: {} - }; - const TEST_HTTP_ERROR = `Failed to retrieve the template list, please see the details from the error response. -${JSON.stringify(TEST_HTTP_RESPONSE, null, 2)}`; - ui.selectSkillCodeLanguage.callsArgWith(0, null, TEST_LANGUAGE_RESPONSE); - ui.getDeploymentType.callsArgWith(1, null, TEST_DEPLOYMENT_TYPE); - httpClient.request.callsArgWith(3, null, TEST_HTTP_RESPONSE); - // call - wizardHelper.collectUserCreationProjectInfo(TEST_OPTIONS, (err) => { - // verify - expect(err).equal(TEST_HTTP_ERROR); - done(); - }); - }); - - it('| user input getTargetTemplateName fails, expect throw error', (done) => { - // setup - const TEST_HTTP_RESPONSE = { - statusCode: 200, - body: TEST_TEMPLATE_MAP_STRING - }; - ui.selectSkillCodeLanguage.callsArgWith(0, null, TEST_LANGUAGE_RESPONSE); - ui.getDeploymentType.callsArgWith(1, null, TEST_DEPLOYMENT_TYPE); - httpClient.request.callsArgWith(3, null, TEST_HTTP_RESPONSE); - ui.getTargetTemplateName.callsArgWith(1, TEST_ERROR); - // call - wizardHelper.collectUserCreationProjectInfo(TEST_OPTIONS, (err) => { - // verify - expect(err).equal(TEST_ERROR); - done(); - }); - }); - - it('| user input getSkillName fails, expect throw error', (done) => { - // setup - const TEST_HTTP_RESPONSE = { - statusCode: 200, - body: JSON.stringify(TEST_TEMPLATE_MAP) - }; - ui.selectSkillCodeLanguage.callsArgWith(0, null, TEST_LANGUAGE_RESPONSE); - ui.getDeploymentType.callsArgWith(1, null); - httpClient.request.callsArgWith(3, null, TEST_HTTP_RESPONSE); - ui.getTargetTemplateName.callsArgWith(1, null, TEST_TEMPLATE_NAME); - ui.getSkillName.callsArgWith(1, TEST_ERROR); - // call - wizardHelper.collectUserCreationProjectInfo(TEST_OPTIONS, (err) => { - // verify - expect(err).equal(TEST_ERROR); - done(); - }); - }); - - it('| user input getProjectFolderName fails, expect throw error', (done) => { - // setup - ui.selectSkillCodeLanguage.callsArgWith(0, null, TEST_LANGUAGE_RESPONSE); - ui.getDeploymentType.callsArgWith(1, null, TEST_DEPLOYMENT_TYPE); - urlUtils.isValidUrl.returns(true); - urlUtils.isUrlOfficialTemplate.returns(true); - ui.getSkillName.callsArgWith(1, null, TEST_SKILL_NAME); - ui.getProjectFolderName.callsArgWith(1, TEST_ERROR); - // call - wizardHelper.collectUserCreationProjectInfo(TEST_OPTIONS_WITH_TEMPLATE, (err) => { - // verify - expect(err).equal(TEST_ERROR); - done(); - }); - }); - - it('| collectUserCreationProjectInfo succeed, expect userInput return', (done) => { - // setup - ui.selectSkillCodeLanguage.callsArgWith(0, null, TEST_LANGUAGE_RESPONSE); - ui.getDeploymentType.callsArgWith(1, null, TEST_HOSTED_DEPLOYMENT); - ui.getSkillName.callsArgWith(1, null, TEST_SKILL_NAME); - ui.getProjectFolderName.callsArgWith(1, null, TEST_FOLDER_NAME); - // call - wizardHelper.collectUserCreationProjectInfo(TEST_OPTIONS, (err, res) => { - // verify - expect(err).equal(null); - expect(res.deploymentType).equal(TEST_HOSTED_DEPLOYMENT); - expect(res.language).equal(TEST_LANGUAGE_RESPONSE); - expect(res.projectFolderName).equal(TEST_FOLDER_NAME); - expect(res.skillName).equal(TEST_SKILL_NAME); - done(); - }); - }); - }); -}); diff --git a/test/unit/commands/new/wizard-helper-test.ts b/test/unit/commands/new/wizard-helper-test.ts new file mode 100644 index 00000000..22dc6186 --- /dev/null +++ b/test/unit/commands/new/wizard-helper-test.ts @@ -0,0 +1,294 @@ +import {expect} from "chai"; +import sinon, {SinonStub} from "sinon"; +import * as ui from "../../../../lib/commands/new/ui"; +import * as templateHelper from "../../../../lib/commands/new/template-helper"; +import * as view from "../../../../lib/view/prompt-view"; +import urlUtils from "../../../../lib/utils/url-utils"; +import * as wizardHelper from "../../../../lib/commands/new/wizard-helper"; +import Messenger from "../../../../lib/view/messenger"; +import {TEST_SAMPLE_1_IM_HOSTED_NODE, TEST_SAMPLE_2_AC_CFN_PYTHON} from "./template-helper-test"; +import { MODELING_STACK_IM } from "../../../../lib/commands/new"; + +describe("Commands new test - wizard helper test", () => { + const TEST_ERROR = "TEST_ERROR"; + const TEST_OPTIONS = {}; + const TEST_LANGUAGE_RESPONSE = "NodeJS"; + const TEST_DEPLOYMENT_TYPE = "@ask-cli/cfn-deployer"; + const TEST_HOSTED_DEPLOYMENT = "@ask-cli/hosted-skill-deployer"; + const TEST_TEMPLATE_URL = "TEST_TEMPLATE_URL"; + const TEST_SKILL_NAME = "TEST_SKILL_NAME"; + const TEST_FOLDER_NAME = "TEST_FOLDER_NAME"; + const TEST_REGION = "us-east-1"; + const TEST_TEMPLATE_SAMPLES = [TEST_SAMPLE_1_IM_HOSTED_NODE, TEST_SAMPLE_2_AC_CFN_PYTHON] + const TEST_OPTIONS_WITH_TEMPLATE = { + templateUrl: TEST_TEMPLATE_URL, + }; + + let infoStub: SinonStub; + let errorStub: SinonStub; + let warnStub: SinonStub; + let selectSkillCodeLanguageStub: SinonStub; + let getDeploymentTypeStub: SinonStub; + let confirmUsingUnofficialTemplateStub: SinonStub; + let isValidUrlStub: SinonStub; + let isUrlOfficialTemplateStub: SinonStub; + let getTargetTemplateNameStub: SinonStub; + let getSkillNameStub: SinonStub; + let getProjectFolderNameStub: SinonStub; + let getSkillDefaultRegionStub: SinonStub; + let getSkillLocaleStub: SinonStub; + let getInstanceStub: SinonStub; + let getModelingStackTypeStub: SinonStub; + let getSampleTemplatesFromS3Stub: SinonStub; + + beforeEach(() => { + infoStub = sinon.stub(); + errorStub = sinon.stub(); + warnStub = sinon.stub(); + getInstanceStub = sinon.stub(Messenger, "getInstance"); + getInstanceStub.returns({ + info: infoStub, + error: errorStub, + warn: warnStub, + }); + selectSkillCodeLanguageStub = sinon.stub(ui, "selectSkillCodeLanguage"); + getDeploymentTypeStub = sinon.stub(ui, "getDeploymentType"); + confirmUsingUnofficialTemplateStub = sinon.stub(ui, "confirmUsingUnofficialTemplate"); + isValidUrlStub = sinon.stub(urlUtils, "isValidUrl"); + isUrlOfficialTemplateStub = sinon.stub(urlUtils, "isUrlOfficialTemplate"); + getTargetTemplateNameStub = sinon.stub(ui, "getTargetTemplateName"); + getSkillNameStub = sinon.stub(ui, "getSkillName"); + getProjectFolderNameStub = sinon.stub(view, "getProjectFolderName"); + getSkillDefaultRegionStub = sinon.stub(ui, "getSkillDefaultRegion"); + getSkillLocaleStub = sinon.stub(ui, "getSkillLocale"); + getSkillLocaleStub.yields(null, "en-US"); + getSkillLocaleStub.yields(null, "us-east-1"); + getModelingStackTypeStub = sinon.stub(ui, "getModelingStackType"); + getModelingStackTypeStub.callsArgWith(0, null, MODELING_STACK_IM); + getSampleTemplatesFromS3Stub = sinon.stub(templateHelper, "getSampleTemplatesFromS3"); + getSampleTemplatesFromS3Stub.resolves(TEST_TEMPLATE_SAMPLES); + }); + + afterEach(() => { + sinon.restore(); + }); + describe("# test wizard helper method - collectUserCreationProjectInfo", () => { + it("| user input selectSkillCodeLanguage fails, expect throw error", (done) => { + // setup + selectSkillCodeLanguageStub.yields(null, TEST_LANGUAGE_RESPONSE); + getDeploymentTypeStub.yields(null, TEST_HOSTED_DEPLOYMENT); + selectSkillCodeLanguageStub.callsArgWith(1, TEST_ERROR); + // call + wizardHelper.collectUserCreationProjectInfo(TEST_OPTIONS, (err) => { + // verify + expect(err).equal(TEST_ERROR); + done(); + }); + }); + + it("| user input getDeploymentType fails, expect throw error", (done) => { + // setup + selectSkillCodeLanguageStub.yields(null, TEST_LANGUAGE_RESPONSE); + getDeploymentTypeStub.callsArgWith(1, TEST_ERROR); + // call + wizardHelper.collectUserCreationProjectInfo(TEST_OPTIONS, (err) => { + // verify + expect(err).equal(TEST_ERROR); + done(); + }); + }); + + it.skip("| user input getSkillLocale fails, expect throw error", (done) => { + // skipped because locale is hard coded until backend for hosted skills supports locales + // setup + selectSkillCodeLanguageStub.yields(null, TEST_LANGUAGE_RESPONSE); + getDeploymentTypeStub.yields(null, TEST_HOSTED_DEPLOYMENT); + getSkillLocaleStub.yields(TEST_ERROR); + // call + wizardHelper.collectUserCreationProjectInfo(TEST_OPTIONS, (err) => { + // verify + expect(err).equal(TEST_ERROR); + done(); + }); + }); + + it("| user input getSkillDefaultRegion fails, expect throw error", (done) => { + // setup + selectSkillCodeLanguageStub.yields(null, TEST_LANGUAGE_RESPONSE); + getDeploymentTypeStub.yields(null, TEST_HOSTED_DEPLOYMENT); + getSkillDefaultRegionStub.yields(TEST_ERROR); + // call + wizardHelper.collectUserCreationProjectInfo(TEST_OPTIONS, (err) => { + // verify + expect(err).equal(TEST_ERROR); + done(); + }); + }); + + it("| custom template should not valid url, expect throw error", (done) => { + // setup + const TEST_GIT_ERROR = `The provided template url ${TEST_TEMPLATE_URL} is not a valid url.`; + selectSkillCodeLanguageStub.callsArgWith(1, null, TEST_LANGUAGE_RESPONSE); + getDeploymentTypeStub.callsArgWith(1, null, TEST_DEPLOYMENT_TYPE); + isValidUrlStub.returns(false); + // call + wizardHelper.collectUserCreationProjectInfo(TEST_OPTIONS_WITH_TEMPLATE, (err) => { + // verify + expect(err?.message).equal(TEST_GIT_ERROR); + done(); + }); + }); + + it("| user input confirmUsingUnofficialTemplate fails, expect throw error", (done) => { + // setup + selectSkillCodeLanguageStub.callsArgWith(1, null, TEST_LANGUAGE_RESPONSE); + getDeploymentTypeStub.callsArgWith(1, null, TEST_DEPLOYMENT_TYPE); + isValidUrlStub.returns(true); + isUrlOfficialTemplateStub.returns(false); + confirmUsingUnofficialTemplateStub.callsArgWith(0, TEST_ERROR); + // call + wizardHelper.collectUserCreationProjectInfo(TEST_OPTIONS_WITH_TEMPLATE, (err) => { + // verify + expect(err).equal(TEST_ERROR); + expect(infoStub.callCount).equal(0); + expect(warnStub.callCount).equal(1); + done(); + }); + }); + + it("| users do not confirm using unofficial template, return without templateInfo, expect return directly", (done) => { + // setup + selectSkillCodeLanguageStub.callsArgWith(1, null, TEST_LANGUAGE_RESPONSE); + getDeploymentTypeStub.callsArgWith(1, null, TEST_DEPLOYMENT_TYPE); + isValidUrlStub.returns(true); + isUrlOfficialTemplateStub.returns(false); + confirmUsingUnofficialTemplateStub.callsArgWith(0, null, false); + // call + wizardHelper.collectUserCreationProjectInfo(TEST_OPTIONS_WITH_TEMPLATE, (err, res) => { + // verify + expect(err).equal(null); + expect(res).equal(undefined); + expect(infoStub.callCount).equal(0); + expect(warnStub.callCount).equal(1); + done(); + }); + }); + + // TODO: when host all templates at github and use http call to get template list, get following three tests back + // it('| new with official template, retrieve official template map fails, expect throw error', (done) => { + // // setup + // const TEST_HTTP_RESPONSE = { + // statusCode: 300, + // body: {} + // }; + // const TEST_HTTP_ERROR = `Failed to retrieve the template list, please see the details from the error response. + // ${JSON.stringify(TEST_HTTP_RESPONSE, null, 2)}`; + // selectSkillCodeLanguageStub.callsArgWith(1, null, TEST_LANGUAGE_RESPONSE); + // getDeploymentTypeStub.callsArgWith(1, null, TEST_DEPLOYMENT_TYPE); + // httpClient.request.callsArgWith(3, null, TEST_HTTP_RESPONSE); + // // call + // wizardHelper.collectUserCreationProjectInfo(TEST_OPTIONS, (err) => { + // // verify + // expect(err?.message).equal(TEST_HTTP_ERROR); + // done(); + // }); + // }); + + // it('| user input getTargetTemplateName fails, expect throw error', (done) => { + // // setup + // const TEST_HTTP_RESPONSE = { + // statusCode: 200, + // body: TEST_TEMPLATE_MAP_STRING + // }; + // selectSkillCodeLanguageStub.callsArgWith(1, null, TEST_LANGUAGE_RESPONSE); + // getDeploymentTypeStub.callsArgWith(1, null, TEST_DEPLOYMENT_TYPE); + // httpClient.request.callsArgWith(3, null, TEST_HTTP_RESPONSE); + // getTargetTemplateNameStub.callsArgWith(1, TEST_ERROR); + // // call + // wizardHelper.collectUserCreationProjectInfo(TEST_OPTIONS, (err) => { + // // verify + // expect(err?.message).equal(TEST_ERROR); + // done(); + // }); + // }); + + // it('| user input getSkillName fails, expect throw error', (done) => { + // // setup + // const TEST_HTTP_RESPONSE = { + // statusCode: 200, + // body: JSON.stringify(TEST_TEMPLATE_MAP) + // }; + // selectSkillCodeLanguageStub.callsArgWith(1, null, TEST_LANGUAGE_RESPONSE); + // getDeploymentTypeStub.callsArgWith(1, null); + // httpClient.request.callsArgWith(3, null, TEST_HTTP_RESPONSE); + // getTargetTemplateNameStub.callsArgWith(1, null, TEST_TEMPLATE_NAME); + // getSkillNameStub.callsArgWith(1, TEST_ERROR); + // // call + // wizardHelper.collectUserCreationProjectInfo(TEST_OPTIONS, (err) => { + // // verify + // expect(err?.message).equal(TEST_ERROR); + // done(); + // }); + // }); + + it("| user input getProjectFolderName fails, expect throw error", (done) => { + // setup + selectSkillCodeLanguageStub.callsArgWith(1, null, TEST_LANGUAGE_RESPONSE); + getDeploymentTypeStub.callsArgWith(1, null, TEST_DEPLOYMENT_TYPE); + isValidUrlStub.returns(true); + isUrlOfficialTemplateStub.returns(true); + getSkillNameStub.callsArgWith(1, null, TEST_SKILL_NAME); + getProjectFolderNameStub.callsArgWith(1, TEST_ERROR); + // call + wizardHelper.collectUserCreationProjectInfo(TEST_OPTIONS_WITH_TEMPLATE, (err) => { + // verify + expect(err).equal(TEST_ERROR); + done(); + }); + }); + + it("| collectUserCreationProjectInfo Hosted selections should not prompt for template sample selection", (done) => { + // setup + selectSkillCodeLanguageStub.callsArgWith(1, null, TEST_LANGUAGE_RESPONSE); + getDeploymentTypeStub.callsArgWith(1, null, TEST_HOSTED_DEPLOYMENT); + getSkillNameStub.callsArgWith(1, null, TEST_SKILL_NAME); + getProjectFolderNameStub.callsArgWith(1, null, TEST_FOLDER_NAME); + getSkillDefaultRegionStub.yields(null, TEST_REGION); + // call + wizardHelper.collectUserCreationProjectInfo(TEST_OPTIONS, (err, res) => { + // verify + expect(err).equal(null); + expect(res?.deploymentType).equal(TEST_HOSTED_DEPLOYMENT); + expect(getTargetTemplateNameStub).not.called; + expect(res?.language).equal(TEST_LANGUAGE_RESPONSE); + expect(res?.projectFolderName).equal(TEST_FOLDER_NAME); + expect(res?.skillName).equal(TEST_SKILL_NAME); + expect(res?.templateInfo).to.be.undefined; + done(); + }); + }); + + it("| collectUserCreationProjectInfo succeed, expect userInput return", (done) => { + // setup + selectSkillCodeLanguageStub.callsArgWith(1, null, TEST_LANGUAGE_RESPONSE); + getDeploymentTypeStub.callsArgWith(1, null, TEST_DEPLOYMENT_TYPE); + getSkillNameStub.callsArgWith(1, null, TEST_SKILL_NAME); + getProjectFolderNameStub.callsArgWith(1, null, TEST_FOLDER_NAME); + getSkillDefaultRegionStub.yields(null, TEST_REGION); + getTargetTemplateNameStub.yields(null, TEST_SAMPLE_1_IM_HOSTED_NODE); + // call + wizardHelper.collectUserCreationProjectInfo(TEST_OPTIONS, (err, res) => { + // verify + expect(err).equal(null); + expect(res?.deploymentType).equal(TEST_DEPLOYMENT_TYPE); + expect(res?.language).equal(TEST_LANGUAGE_RESPONSE); + expect(res?.projectFolderName).equal(TEST_FOLDER_NAME); + expect(res?.skillName).equal(TEST_SKILL_NAME); + expect(res?.templateInfo?.templateBranch).equal(TEST_SAMPLE_1_IM_HOSTED_NODE.branch); + expect(res?.templateInfo?.templateUrl).equal(TEST_SAMPLE_1_IM_HOSTED_NODE.url); + expect(res?.templateInfo?.templateName).equal(TEST_SAMPLE_1_IM_HOSTED_NODE.name); + done(); + }); + }); + }); +}); diff --git a/test/unit/commands/option-validator-test.js b/test/unit/commands/option-validator-test.js index 2adcf62e..f8997da0 100644 --- a/test/unit/commands/option-validator-test.js +++ b/test/unit/commands/option-validator-test.js @@ -1,207 +1,257 @@ -const { expect } = require('chai'); -const sinon = require('sinon'); -const fs = require('fs'); +const {expect} = require("chai"); +const sinon = require("sinon"); +const fs = require("fs"); -const optionValidator = require('@src/commands/option-validator'); -const Messenger = require('@src/view/messenger'); +const optionValidator = require("../../../lib/commands/option-validator"); +const Messenger = require("../../../lib/view/messenger"); -describe('Command test - Option validator test', () => { - it('| should validate required option value', () => { - expect(() => { optionValidator.validateRequiredOption({ foo: 'value' }, 'foo'); }).not.throw(); - expect(() => { optionValidator.validateRequiredOption({ foo: 'value' }, 'bar'); }).throw('Field is required and must be set.'); +describe("Command test - Option validator test", () => { + it("| should validate required option value", () => { + expect(() => { + optionValidator.validateRequiredOption({foo: "value"}, "foo"); + }).not.throw(); + expect(() => { + optionValidator.validateRequiredOption({foo: "value"}, "bar"); + }).throw("Field is required and must be set."); + }); + + it("| should validate string option value", () => { + expect(() => { + optionValidator.validateOptionString({foo: "value"}, "foo"); + }).not.throw(); + expect(() => { + optionValidator.validateOptionString({foo: 123}, "foo"); + }).throw("Must be a string."); + expect(() => { + optionValidator.validateOptionString({foo: " "}, "foo"); + }).throw("Value must not be empty."); + }); + + describe("# validate option rules", () => { + it("| should fallback to no-op if no rules are provided", () => { + expect(() => { + optionValidator.validateOptionRules({foo: "value"}, "foo", []); + }).not.throw(); + }); + + it("| should fallback to no-op if no rule validator is found for given rule type", () => { + expect(() => { + optionValidator.validateOptionRules({foo: "value"}, "foo", [{type: "nonExistentRule"}]); + }).not.throw(); + }); + + it("| should validate option rule model to have necessary metadata", (done) => { + const mockConsoleError = sinon.stub(console, "error"); + const mockProcessExit = sinon.stub(process, "exit"); + new Messenger({}); + + mockProcessExit.callsFake((code) => { + expect(code).eq(1); + expect(mockConsoleError.args[0][0]).include('[Fatal]: Option rule model of type "ENUM" requires field "values" to be set!'); + sinon.restore(); + done(); + }); + + optionValidator.validateOptionRules( + { + foo: "value", + }, + "foo", + [ + { + type: "ENUM", + }, + ], + ); }); - it('| should validate string option value', () => { - expect(() => { optionValidator.validateOptionString({ foo: 'value' }, 'foo'); }).not.throw(); - expect(() => { optionValidator.validateOptionString({ foo: 123 }, 'foo'); }).throw('Must be a string.'); - expect(() => { optionValidator.validateOptionString({ foo: ' ' }, 'foo'); }).throw('Value must not be empty.'); + it("| should validate enum value if rule ENUM is given", () => { + expect(() => { + optionValidator.validateOptionRules( + { + foo: "value-a", + }, + "foo", + [ + { + type: "ENUM", + values: ["value-a", "value-b"], + }, + ], + ); + }).not.throw(); + expect(() => { + optionValidator.validateOptionRules( + { + foo: "value", + }, + "foo", + [ + { + type: "ENUM", + values: ["value-a", "value-b"], + }, + ], + ); + }).throw("Value must be in (value-a, value-b)."); }); - describe('# validate option rules', () => { - it('| should fallback to no-op if no rules are provided', () => { - expect(() => { optionValidator.validateOptionRules({ foo: 'value' }, 'foo', []); }).not.throw(); - }); - - it('| should fallback to no-op if no rule validator is found for given rule type', () => { - expect(() => { optionValidator.validateOptionRules({ foo: 'value' }, 'foo', [{ type: 'nonExistentRule' }]); }).not.throw(); - }); - - it('| should validate option rule model to have necessary metadata', (done) => { - const mockConsoleError = sinon.stub(console, 'error'); - const mockProcessExit = sinon.stub(process, 'exit'); - new Messenger({}); - - mockProcessExit.callsFake((code) => { - expect(code).eq(1); - expect(mockConsoleError.args[0][0]).include('[Fatal]: Option rule model of type "ENUM" requires field "values" to be set!'); - sinon.restore(); - done(); - }); - - optionValidator.validateOptionRules( - { - foo: 'value', - }, - 'foo', - [ - { - type: 'ENUM', - } - ] - ); - }); - - it('| should validate enum value if rule ENUM is given', () => { - expect(() => { - optionValidator.validateOptionRules( - { - foo: 'value-a' - }, - 'foo', - [ - { - type: 'ENUM', - values: ['value-a', 'value-b'] - } - ] - ); - }).not.throw(); - expect(() => { - optionValidator.validateOptionRules( - { - foo: 'value' - }, - 'foo', - [ - { - type: 'ENUM', - values: ['value-a', 'value-b'] - } - ] - ); - }).throw('Value must be in (value-a, value-b).'); - }); - - it('| should validate regexp value if rule REGEX is given', () => { - expect(() => { - optionValidator.validateOptionRules( - { - foo: 'en-US' - }, - 'foo', - [ - { - type: 'REGEX', - regex: '^[a-z]{2}-[A-Z]{2}$' - } - ] - ); - }).not.throw(); - expect(() => { - optionValidator.validateOptionRules( - { - foo: 'value' - }, - 'foo', - [ - { - type: 'REGEX', - regex: '^[a-z]{2}-[A-Z]{2}$' - } - ] - ); - }).throw('Input value (value) doesn\'t match REGEX rule ^[a-z]{2}-[A-Z]{2}$.'); - }); - - it('| should validate number value if rule NUMBER is given', () => { - expect(() => { - optionValidator.validateOptionRules( - { - foo: '123' - }, - 'foo', - [ - { - type: 'NUMBER' - } - ] - ); - }).not.throw(); - expect(() => { - optionValidator.validateOptionRules( - { - foo: 'abc' - }, - 'foo', - [ - { - type: 'NUMBER' - } - ] - ); - }).throw('Input should be a number.'); - }); - - it('| should validate integer value if rule INTEGER is given', () => { - expect(() => { - optionValidator.validateOptionRules( - { - foo: '123' - }, - 'foo', - [ - { - type: 'INTEGER' - } - ] - ); - }).not.throw(); - expect(() => { - optionValidator.validateOptionRules( - { - foo: '123.1' - }, - 'foo', - [ - { - type: 'INTEGER' - } - ] - ); - }).throw('Input number should be an integer.'); - }); - - it('| should validate csv file extension if rule FILE_PATH is given', () => { - sinon.stub(fs, 'accessSync'); - - expect(() => { - optionValidator.validateOptionRules( - { - file: 'beta-testers.csv' - }, - 'file', - [ - { - type: 'FILE_PATH', - extension: ['.csv'] - } - ] - ); - }).not.throw(); - expect(() => { - optionValidator.validateOptionRules( - { - file: 'beta-testers.txt' - }, - 'file', - [ - { - type: 'FILE_PATH', - extension: ['.csv'] - } - ] - ); - }).throw('File extension is not of type .csv.'); - }); + it("| should validate regexp value if rule REGEX is given", () => { + const localeOptions = { + optionValid: "en-US", + optionInvalid: "Mars", + }; + + const localeRegex = [ + { + type: "REGEX", + regex: "^[a-z]{2}-[A-Z]{2}$", + }, + ]; + + const skillOptions = { + optionValid: "amzn1.ask.skill.1234abcd-12ab-abcd-1234-123456789012", + optionInvalid: "amzn1.ask.skill", + }; + + const skillRegex = [ + { + type: "REGEX", + regex: "^amzn\\d\\.ask\\.skill\\.\\w{8}-\\w{4}-\\w{4}-\\w{4}-\\w{12}$", + }, + ]; + + // valid regex expectations + expect(() => { + optionValidator.validateOptionRules(localeOptions, "optionValid", localeRegex); + }).not.throw(); + + expect(() => { + optionValidator.validateOptionRules(skillOptions, "optionValid", skillRegex); + }).not.throw(); + + // invalid regex expectations + expect(() => { + optionValidator.validateOptionRules(skillOptions, "optionInvalid", skillRegex); + }).throw(`Input value (${skillOptions.optionInvalid}) doesn't match REGEX rule ${skillRegex[0].regex}.`); + + expect(() => { + optionValidator.validateOptionRules(localeOptions, "optionInvalid", localeRegex); + }).throw(`Input value (${localeOptions.optionInvalid}) doesn't match REGEX rule ${localeRegex[0].regex}.`); + }); + + it("| should validate url value if rule URL is given", () => { + const urlOptions = { + optionValid: "https://example.com/example/example-skill.git", + optionInvalid: "example", + }; + + const urlRule = [ + { + type: "URL", + }, + ]; + + // valid URL expectations + expect(() => { + optionValidator.validateOptionRules(urlOptions, "optionValid", urlRule); + }).not.throw(); + + // invalid URL expectations + expect(() => { + optionValidator.validateOptionRules(urlOptions, "optionInvalid", urlRule); + }).throw("Input should be a URL."); + }); + + it("| should validate number value if rule NUMBER is given", () => { + expect(() => { + optionValidator.validateOptionRules( + { + foo: "123", + }, + "foo", + [ + { + type: "NUMBER", + }, + ], + ); + }).not.throw(); + expect(() => { + optionValidator.validateOptionRules( + { + foo: "abc", + }, + "foo", + [ + { + type: "NUMBER", + }, + ], + ); + }).throw("Input should be a number."); + }); + + it("| should validate integer value if rule INTEGER is given", () => { + expect(() => { + optionValidator.validateOptionRules( + { + foo: "123", + }, + "foo", + [ + { + type: "INTEGER", + }, + ], + ); + }).not.throw(); + expect(() => { + optionValidator.validateOptionRules( + { + foo: "123.1", + }, + "foo", + [ + { + type: "INTEGER", + }, + ], + ); + }).throw("Input number should be an integer."); + }); + + it("| should validate csv file extension if rule FILE_PATH is given", () => { + sinon.stub(fs, "accessSync"); + + expect(() => { + optionValidator.validateOptionRules( + { + file: "beta-testers.csv", + }, + "file", + [ + { + type: "FILE_PATH", + extension: [".csv"], + }, + ], + ); + }).not.throw(); + expect(() => { + optionValidator.validateOptionRules( + { + file: "beta-testers.txt", + }, + "file", + [ + { + type: "FILE_PATH", + extension: [".csv"], + }, + ], + ); + }).throw("File extension is not of type .csv."); }); + }); }); diff --git a/test/unit/commands/run/helper-test.js b/test/unit/commands/run/helper-test.js index df0d20dc..d9fee2fc 100644 --- a/test/unit/commands/run/helper-test.js +++ b/test/unit/commands/run/helper-test.js @@ -1,138 +1,173 @@ -const { expect } = require('chai'); -const fs = require('fs'); -const sinon = require('sinon'); -const helper = require('@src/commands/run/helper'); -const CONSTANTS = require('@src/utils/constants'); -const NodejsRunFlow = require('@src/commands/run/run-flow/nodejs-run'); -const PythonRunFlow = require('@src/commands/run/run-flow/python-run'); -const JavaRunFlow = require('@src/commands/run/run-flow/java-run'); -const ResourcesConfig = require('@src/model/resources-config'); +const {expect} = require("chai"); +const fs = require("fs"); +const sinon = require("sinon"); +const helper = require("../../../../lib/commands/run/helper"); +const CONSTANTS = require("../../../../lib/utils/constants"); +const NodejsRunFlow = require("../../../../lib/commands/run/run-flow/nodejs-run"); +const PythonRunFlow = require("../../../../lib/commands/run/run-flow/python-run"); +const JavaRunFlow = require("../../../../lib/commands/run/run-flow/java-run"); +const ResourcesConfig = require("../../../../lib/model/resources-config"); -describe('Commands Run - helper test', () => { - describe('getHostedSkillInvocationInfo test', () => { - it('| validate Node hosted skill invocation info', () => { - const hostedSkillInvocationInfo = helper.getHostedSkillInvocationInfo(CONSTANTS.RUNTIME.NODE); - expect(hostedSkillInvocationInfo.skillCodeFolderName).eq('lambda'); - expect(hostedSkillInvocationInfo.handlerName).eq('handler'); - expect(hostedSkillInvocationInfo.skillFileName).eq('index'); - }); +describe("Commands Run - helper test", () => { + describe("getHostedSkillInvocationInfo test", () => { + it("| validate Node hosted skill invocation info", () => { + const hostedSkillInvocationInfo = helper.getHostedSkillInvocationInfo(CONSTANTS.RUNTIME.NODE); + expect(hostedSkillInvocationInfo.skillCodeFolderName).eq("lambda"); + expect(hostedSkillInvocationInfo.handlerName).eq("handler"); + expect(hostedSkillInvocationInfo.skillFileName).eq("index"); + }); - it('| validate Python hosted skill invocation info', () => { - const hostedSkillInvocationInfo = helper.getHostedSkillInvocationInfo(CONSTANTS.RUNTIME.PYTHON); - expect(hostedSkillInvocationInfo.skillCodeFolderName).eq('lambda'); - expect(hostedSkillInvocationInfo.handlerName).eq('lambda_handler'); - expect(hostedSkillInvocationInfo.skillFileName).eq('lambda_function'); - }); + it("| validate Python hosted skill invocation info", () => { + const hostedSkillInvocationInfo = helper.getHostedSkillInvocationInfo(CONSTANTS.RUNTIME.PYTHON); + expect(hostedSkillInvocationInfo.skillCodeFolderName).eq("lambda"); + expect(hostedSkillInvocationInfo.handlerName).eq("lambda_handler"); + expect(hostedSkillInvocationInfo.skillFileName).eq("lambda_function"); + }); - it('| Invalid hosted skill runtime info', () => { - const hostedSkillInvocationInfo = helper.getHostedSkillInvocationInfo(CONSTANTS.RUNTIME.JAVA); - expect(hostedSkillInvocationInfo).eq(undefined); - }); + it("| Invalid hosted skill runtime info", () => { + const hostedSkillInvocationInfo = helper.getHostedSkillInvocationInfo(CONSTANTS.RUNTIME.JAVA); + expect(hostedSkillInvocationInfo).eq(undefined); }); + }); - describe('getNonHostedSkillInvocationInfo test', () => { - it('| validate Node non hosted skill invocation info', () => { - const nonHostedSkillInvocationInfo = helper - .getNonHostedSkillInvocationInfo(CONSTANTS.RUNTIME.NODE, 'fooFileName.fooHandler', 'fooSkillCodeFolderName'); - expect(nonHostedSkillInvocationInfo.handlerName).eq('fooHandler'); - expect(nonHostedSkillInvocationInfo.skillFileName).eq('fooFileName'); - expect(nonHostedSkillInvocationInfo.skillCodeFolderName).eq('fooSkillCodeFolderName'); - }); - it('| validate Python non hosted skill invocation info', () => { - const nonHostedSkillInvocationInfo = helper - .getNonHostedSkillInvocationInfo(CONSTANTS.RUNTIME.PYTHON, 'fooFileName.fooHandler', 'fooSkillCodeFolderName'); - expect(nonHostedSkillInvocationInfo.handlerName).eq('fooHandler'); - expect(nonHostedSkillInvocationInfo.skillFileName).eq('fooFileName'); - expect(nonHostedSkillInvocationInfo.skillCodeFolderName).eq('fooSkillCodeFolderName'); - }); - it('| validate Java non hosted skill invocation info', () => { - const nonHostedSkillInvocationInfo = helper - .getNonHostedSkillInvocationInfo(CONSTANTS.RUNTIME.JAVA, 'fooHandler', 'fooSkillCodeFolderName'); - expect(nonHostedSkillInvocationInfo.handlerName).eq('fooHandler'); - expect(nonHostedSkillInvocationInfo.skillCodeFolderName).eq('fooSkillCodeFolderName'); - }); - it('| empty runtime', () => { - expect(() => helper - .getNonHostedSkillInvocationInfo('', '', '')).to.throw('Missing runtime info in ' - + `resource file ${CONSTANTS.FILE_PATH.ASK_RESOURCES_JSON_CONFIG}.`); - }); - it('| empty handler', () => { - expect(() => helper - .getNonHostedSkillInvocationInfo(CONSTANTS.RUNTIME.JAVA, '', '')).to.throw('Missing handler info in ' - + `resource file ${CONSTANTS.FILE_PATH.ASK_RESOURCES_JSON_CONFIG}.`); - }); + describe("getNonHostedSkillInvocationInfo test", () => { + it("| validate Node non hosted skill invocation info", () => { + const nonHostedSkillInvocationInfo = helper.getNonHostedSkillInvocationInfo( + CONSTANTS.RUNTIME.NODE, + "fooFileName.fooHandler", + "fooSkillCodeFolderName", + ); + expect(nonHostedSkillInvocationInfo.handlerName).eq("fooHandler"); + expect(nonHostedSkillInvocationInfo.skillFileName).eq("fooFileName"); + expect(nonHostedSkillInvocationInfo.skillCodeFolderName).eq("fooSkillCodeFolderName"); + }); + it("| validate Python non hosted skill invocation info", () => { + const nonHostedSkillInvocationInfo = helper.getNonHostedSkillInvocationInfo( + CONSTANTS.RUNTIME.PYTHON, + "fooFileName.fooHandler", + "fooSkillCodeFolderName", + ); + expect(nonHostedSkillInvocationInfo.handlerName).eq("fooHandler"); + expect(nonHostedSkillInvocationInfo.skillFileName).eq("fooFileName"); + expect(nonHostedSkillInvocationInfo.skillCodeFolderName).eq("fooSkillCodeFolderName"); + }); + it("| validate Java non hosted skill invocation info", () => { + const nonHostedSkillInvocationInfo = helper.getNonHostedSkillInvocationInfo( + CONSTANTS.RUNTIME.JAVA, + "fooHandler", + "fooSkillCodeFolderName", + ); + expect(nonHostedSkillInvocationInfo.handlerName).eq("fooHandler"); + expect(nonHostedSkillInvocationInfo.skillCodeFolderName).eq("fooSkillCodeFolderName"); }); + it("| empty runtime", () => { + expect(() => helper.getNonHostedSkillInvocationInfo("", "", "")).to.throw( + "Missing runtime info in " + `resource file ${CONSTANTS.FILE_PATH.ASK_RESOURCES_JSON_CONFIG}.`, + ); + }); + it("| empty handler", () => { + expect(() => helper.getNonHostedSkillInvocationInfo(CONSTANTS.RUNTIME.JAVA, "", "")).to.throw( + "Missing handler info in " + `resource file ${CONSTANTS.FILE_PATH.ASK_RESOURCES_JSON_CONFIG}.`, + ); + }); + }); - describe('getNormalisedRuntime test', () => { - it('| normalised runtime for nodejs', () => { - expect(helper.getNormalisedRuntime('nodejs12.x')).eq(CONSTANTS.RUNTIME.NODE); - }); - it('| normalised runtime for python', () => { - expect(helper.getNormalisedRuntime('python3.8')).eq(CONSTANTS.RUNTIME.PYTHON); - }); - it('| normalised runtime for java', () => { - expect(helper.getNormalisedRuntime('java11')).eq(CONSTANTS.RUNTIME.JAVA); - }); - it('| unsupported runtime', () => { - expect(() => helper.getNormalisedRuntime('foo')).to.throw('Runtime - foo is not supported'); - }); + describe("getNormalisedRuntime test", () => { + it("| normalised runtime for nodejs", () => { + expect(helper.getNormalisedRuntime("nodejs12.x")).eq(CONSTANTS.RUNTIME.NODE); + }); + it("| normalised runtime for python", () => { + expect(helper.getNormalisedRuntime("python3.8")).eq(CONSTANTS.RUNTIME.PYTHON); + }); + it("| normalised runtime for java", () => { + expect(helper.getNormalisedRuntime("java11")).eq(CONSTANTS.RUNTIME.JAVA); }); + it("| unsupported runtime", () => { + expect(() => helper.getNormalisedRuntime("foo")).to.throw("Runtime - foo is not supported"); + }); + }); - describe('selectRunFlowClass test', () => { - it('| java run flow test', () => { - expect(helper.selectRunFlowClass(CONSTANTS.RUNTIME.JAVA)).eq(JavaRunFlow); - }); - it('| python run flow test', () => { - expect(helper.selectRunFlowClass(CONSTANTS.RUNTIME.PYTHON)).eq(PythonRunFlow); - }); - it('| nodejs run flow test', () => { - expect(helper.selectRunFlowClass(CONSTANTS.RUNTIME.NODE)).eq(NodejsRunFlow); - }); - it('| unsupported run flow test', () => { - expect(helper.selectRunFlowClass('foo')).eq(undefined); - }); + describe("selectRunFlowClass test", () => { + it("| java run flow test", () => { + expect(helper.selectRunFlowClass(CONSTANTS.RUNTIME.JAVA)).eq(JavaRunFlow); + }); + it("| python run flow test", () => { + expect(helper.selectRunFlowClass(CONSTANTS.RUNTIME.PYTHON)).eq(PythonRunFlow); + }); + it("| nodejs run flow test", () => { + expect(helper.selectRunFlowClass(CONSTANTS.RUNTIME.NODE)).eq(NodejsRunFlow); + }); + it("| unsupported run flow test", () => { + expect(helper.selectRunFlowClass("foo")).eq(undefined); }); + }); - describe('getSkillCodeFolderName test', () => { - afterEach(() => { - sinon.restore(); - }); + describe("getSkillCodeFolderName test", () => { + afterEach(() => { + sinon.restore(); + }); - it('| skill code folder value exists for user provided region in resources file', () => { - sinon.stub(ResourcesConfig.prototype, 'getCodeSrcByRegion').returns('fooFolder'); - sinon.stub(fs, 'existsSync').returns(true); - expect(helper.getSkillCodeFolderName('foo', CONSTANTS.ALEXA.REGION.NA)).eq('fooFolder'); - }); + it("| skill code folder value exists for user provided region in resources file", () => { + sinon.stub(ResourcesConfig, "getInstance").returns({ + getCodeSrcByRegion: sinon.stub().returns("fooFolder"), + }); + sinon.stub(fs, "existsSync").returns(true); + expect(helper.getSkillCodeFolderName("foo", CONSTANTS.ALEXA.REGION.NA)).eq("fooFolder"); + }); - it('| skill code folder value does not for user provided region, default exists in resources file', () => { - sinon.stub(ResourcesConfig.prototype, 'getCodeSrcByRegion').withArgs('foo', CONSTANTS.ALEXA.REGION.NA).returns('') - .withArgs('foo', CONSTANTS.ALEXA.REGION.DEFAULT) - .returns('fooFolder'); - sinon.stub(fs, 'existsSync').returns(true); - expect(helper.getSkillCodeFolderName('foo', CONSTANTS.ALEXA.REGION.NA)).eq('fooFolder'); - }); + it("| skill code folder value does not for user provided region, default exists in resources file", () => { + sinon.stub(ResourcesConfig, "getInstance").returns({ + getCodeSrcByRegion: sinon + .stub() + .withArgs("foo", CONSTANTS.ALEXA.REGION.NA) + .returns("") + .withArgs("foo", CONSTANTS.ALEXA.REGION.DEFAULT) + .returns("fooFolder"), + }); + sinon.stub(fs, "existsSync").returns(true); + expect(helper.getSkillCodeFolderName("foo", CONSTANTS.ALEXA.REGION.NA)).eq("fooFolder"); + }); - it('| skill code folder value does not exist for user provided region or default in resources file', () => { - sinon.stub(ResourcesConfig.prototype, 'getCodeSrcByRegion').returns(''); - sinon.stub(fs, 'existsSync').returns(true); - expect(() => helper.getSkillCodeFolderName('foo', CONSTANTS.ALEXA.REGION.NA)) - .to.throw('Invalid code setting in region NA. "src" must be set if you want to run the skill code with skill package.'); - }); + it("| skill code folder value does not exist for user provided region or default in resources file", () => { + sinon.stub(ResourcesConfig, "getInstance").returns({ + getCodeSrcByRegion: sinon.stub().returns(""), + }); + sinon.stub(fs, "existsSync").returns(true); + expect(() => helper.getSkillCodeFolderName("foo", CONSTANTS.ALEXA.REGION.NA)).to.throw( + 'Invalid code setting in region NA. "src" must be set if you want to run the skill code with skill package.', + ); + }); - it('| skill code folder does not exist', () => { - sinon.stub(ResourcesConfig.prototype, 'getCodeSrcByRegion').returns('fooFolder'); - sinon.stub(fs, 'existsSync').returns(false); - expect(() => helper.getSkillCodeFolderName('foo', CONSTANTS.ALEXA.REGION.NA)) - .to.throw('Invalid code setting in region NA. File doesn\'t exist for code src: fooFolder.'); - }); + it("| skill code folder does not exist", () => { + sinon.stub(ResourcesConfig, "getInstance").returns({ + getCodeSrcByRegion: sinon.stub().returns("fooFolder"), + }); + sinon.stub(fs, "existsSync").returns(false); + expect(() => helper.getSkillCodeFolderName("foo", CONSTANTS.ALEXA.REGION.NA)).to.throw( + "Invalid code setting in region NA. File doesn't exist for code src: fooFolder.", + ); }); + }); - describe('getSkillFlowInstance test', () => { - it('| create skill flow instance test, error case', () => { - expect(() => helper.getSkillFlowInstance(CONSTANTS.RUNTIME.NODE, { skillCodeFolderName: 'fooSkillCodeFolderName' }, - true, CONSTANTS.RUN.DEFAULT_DEBUG_PORT, 'fooToken', - 'fooSkillId', CONSTANTS.ALEXA.REGION.NA, false).to.throw('ask-sdk-local-debug cannot be found. Please install ' - + 'ask-sdk-local-debug to your skill code project. Refer https://www.npmjs.com/package/ask-sdk-local-debug for more info')); - }); + describe("getSkillFlowInstance test", () => { + it("| create skill flow instance test, error case", () => { + expect(() => + helper + .getSkillFlowInstance( + CONSTANTS.RUNTIME.NODE, + {skillCodeFolderName: "fooSkillCodeFolderName"}, + true, + CONSTANTS.RUN.DEFAULT_DEBUG_PORT, + "fooToken", + "fooSkillId", + CONSTANTS.ALEXA.REGION.NA, + false, + ) + .to.throw( + "ask-sdk-local-debug cannot be found. Please install " + + "ask-sdk-local-debug to your skill code project. Refer https://www.npmjs.com/package/ask-sdk-local-debug for more info", + ), + ); }); + }); }); diff --git a/test/unit/commands/run/index-test.js b/test/unit/commands/run/index-test.js deleted file mode 100644 index c2910548..00000000 --- a/test/unit/commands/run/index-test.js +++ /dev/null @@ -1,261 +0,0 @@ -const { expect } = require('chai'); -const path = require('path'); -const sinon = require('sinon'); -const AuthorizationController = require('@src/controllers/authorization-controller'); -const RunCommand = require('@src/commands/run'); -const optionModel = require('@src/commands/option-model'); -const Messenger = require('@src/view/messenger'); -const ResourcesConfig = require('@src/model/resources-config'); -const profileHelper = require('@src/utils/profile-helper'); -const CONSTANTS = require('@src/utils/constants'); -const helper = require('@src/commands/run/helper'); -const SmapiClient = require('@src/clients/smapi-client'); - -const TEST_PROFILE = 'default'; -const TEST_CMD = { - profile: TEST_PROFILE -}; -const RESOURCE_CONFIG_FIXTURE_PATH = path.join(process.cwd(), 'test', 'unit', 'fixture', 'model', 'regular-proj'); -const INVALID_RESOURCES_CONFIG_JSON_PATH = path.join(RESOURCE_CONFIG_FIXTURE_PATH, 'random-json-config.json'); -const VALID_RESOURCES_CONFIG_JSON_PATH = path.join(RESOURCE_CONFIG_FIXTURE_PATH, 'ask-resources.json'); - -describe('Commands Run test - command class test', () => { - const TEST_ERROR = 'error'; - let errorStub; - let infoStub; - beforeEach(() => { - errorStub = sinon.stub(); - infoStub = sinon.stub(); - sinon.stub(Messenger, 'getInstance').returns({ - error: errorStub, - info: infoStub - }); - sinon.stub(AuthorizationController.prototype, 'tokenRefreshAndRead').yields(); - }); - - afterEach(() => { - sinon.restore(); - }); - - it('| validate command information is set correctly', () => { - const instance = new RunCommand(optionModel); - expect(instance.name()).eq('run'); - expect(instance.description()).eq('Starts a local instance of your project as the skill endpoint.' - + ' Automatically re-routes development requests and responses between the Alexa service and your local instance.'); - expect(instance.requiredOptions()).deep.eq([]); - expect(instance.optionalOptions()) - .deep.eq(['debug-port', 'wait-for-attach', 'watch', 'region', 'profile', 'debug']); - }); - describe('# validate command handle', () => { - let instance; - - beforeEach(() => { - instance = new RunCommand(optionModel); - }); - - afterEach(() => { - sinon.restore(); - }); - - it('| no resources config file found', (done) => { - // setup - const TEST_CMD_WITH_VALUES = {}; - sinon.stub(profileHelper, 'runtimeProfile').returns(TEST_PROFILE); - sinon.stub(path, 'join').returns('fooPath'); - // call - instance.handle(TEST_CMD_WITH_VALUES, (err) => { - // verify - expect(err.message) - .equal('File fooPath not exists. If this is a skill project managed by v1 ask-cli, ' - + 'please run \'ask util upgrade-project\' then try the command again.'); - done(); - }); - }); - - it('| unable to fetch skillId from resources config file', (done) => { - // setup - const TEST_CMD_WITH_VALUES = {}; - sinon.stub(profileHelper, 'runtimeProfile').returns(TEST_PROFILE); - sinon.stub(path, 'join').returns(INVALID_RESOURCES_CONFIG_JSON_PATH); - // call - instance.handle(TEST_CMD_WITH_VALUES, (err) => { - // verify - expect(err.message) - .equal(`Failed to obtain skill-id for the given profile - ${TEST_PROFILE}. Please deploy you skill project first.`); - done(); - }); - }); - - it('| error while getting access token', (done) => { - // setup - sinon.stub(profileHelper, 'runtimeProfile').returns(TEST_PROFILE); - sinon.stub(path, 'join').returns(VALID_RESOURCES_CONFIG_JSON_PATH); - sinon.stub(ResourcesConfig.prototype, 'getSkillId').returns('TestSkillId'); - sinon.stub(RunCommand.prototype, '_getAccessTokenForProfile').yields(new Error(TEST_ERROR)); - - // call - instance.handle(TEST_CMD, (err) => { - // verify - expect(errorStub.args[0][0].message).eq(TEST_ERROR); - expect(err.message).eq(TEST_ERROR); - done(); - }); - }); - - it('| error while getting debug flow', (done) => { - // setup - sinon.stub(profileHelper, 'runtimeProfile').returns(TEST_PROFILE); - sinon.stub(path, 'join').returns(VALID_RESOURCES_CONFIG_JSON_PATH); - sinon.stub(ResourcesConfig.prototype, 'getSkillId').returns('TestSkillId'); - sinon.stub(RunCommand.prototype, '_getAccessTokenForProfile').yields(null, {}); - sinon.stub(RunCommand.prototype, '_getSkillRunFlow').yields(new Error(TEST_ERROR)); - // call - instance.handle(TEST_CMD, (err) => { - // verify - expect(errorStub.args[0][0].message).eq(TEST_ERROR); - expect(err.message).eq(TEST_ERROR); - done(); - }); - }); - }); - describe('_getSkillRunFlow test', () => { - let instance; - - beforeEach(() => { - instance = new RunCommand(optionModel); - }); - - afterEach(() => { - sinon.restore(); - }); - - describe('run flow for non-hosted skill', () => { - beforeEach(() => { - sinon.stub(ResourcesConfig.prototype, 'getSkillInfraType').returns(CONSTANTS.DEPLOYER_TYPE.CFN.NAME); - }); - afterEach(() => { - sinon.restore(); - }); - it('| getSkillCodeFolderName error', (done) => { - sinon.stub(helper, 'getSkillCodeFolderName').throws(new Error(TEST_ERROR)); - - instance._getSkillRunFlow('fooSkillId', 'fooProfile', CONSTANTS.ALEXA.REGION.DEFAULT, false, false, - false, CONSTANTS.RUN.DEFAULT_DEBUG_PORT, 'fooToken', CONSTANTS.ALEXA.REGION.NA, (err) => { - // verify - expect(err.message).eq(TEST_ERROR); - done(); - }); - }); - - it('| no user config', (done) => { - sinon.stub(helper, 'getSkillCodeFolderName').returns('fooSkillFolderName'); - sinon.stub(ResourcesConfig.prototype, 'getSkillInfraUserConfig').returns(undefined); - - instance._getSkillRunFlow('fooSkillId', 'fooProfile', CONSTANTS.ALEXA.REGION.DEFAULT, false, false, - false, CONSTANTS.RUN.DEFAULT_DEBUG_PORT, 'fooToken', CONSTANTS.ALEXA.REGION.NA, (err) => { - // verify - expect(err.message).eq('Failed to obtain userConfig from project ' - + `resource file ${CONSTANTS.FILE_PATH.ASK_RESOURCES_JSON_CONFIG}`); - done(); - }); - }); - - it('| empty user config', (done) => { - sinon.stub(helper, 'getSkillCodeFolderName').returns('fooSkillFolderName'); - sinon.stub(ResourcesConfig.prototype, 'getSkillInfraUserConfig').returns({}); - - instance._getSkillRunFlow('fooSkillId', 'fooProfile', CONSTANTS.ALEXA.REGION.DEFAULT, false, false, - false, CONSTANTS.RUN.DEFAULT_DEBUG_PORT, 'fooToken', CONSTANTS.ALEXA.REGION.NA, (err) => { - // verify - expect(err.message).eq(`Failed to obtain runtime from userConfig in project resource file ${CONSTANTS.FILE_PATH.ASK_RESOURCES_JSON_CONFIG}`); - done(); - }); - }); - - it('| error in getting skill flow instance', (done) => { - sinon.stub(helper, 'getSkillCodeFolderName').returns('fooSkillFolderName'); - sinon.stub(ResourcesConfig.prototype, 'getSkillInfraUserConfig').returns({ runtime: CONSTANTS.RUNTIME.JAVA, handler: 'fooHandler' }); - sinon.stub(helper, 'getSkillFlowInstance').throws(new Error(TEST_ERROR)); - - instance._getSkillRunFlow('fooSkillId', 'fooProfile', CONSTANTS.ALEXA.REGION.DEFAULT, false, false, - false, CONSTANTS.RUN.DEFAULT_DEBUG_PORT, 'fooToken', CONSTANTS.ALEXA.REGION.NA, (err) => { - // verify - expect(err.message).eq(TEST_ERROR); - done(); - }); - }); - }); - describe('run flow for hosted skill', () => { - beforeEach(() => { - sinon.stub(ResourcesConfig.prototype, 'getSkillInfraType').returns(CONSTANTS.DEPLOYER_TYPE.HOSTED.NAME); - }); - - it('| error in getting hosted skill runtime', (done) => { - sinon.stub(RunCommand.prototype, '_getHostedSkillRuntime').yields(new Error(TEST_ERROR)); - - instance._getSkillRunFlow('fooSkillId', 'fooProfile', CONSTANTS.ALEXA.REGION.DEFAULT, false, false, - false, CONSTANTS.RUN.DEFAULT_DEBUG_PORT, 'fooToken', CONSTANTS.ALEXA.REGION.NA, (err) => { - // verify - expect(err.message).eq(TEST_ERROR); - done(); - }); - }); - - it('| error in getting skill flow instance', (done) => { - sinon.stub(RunCommand.prototype, '_getHostedSkillRuntime').yields(null, 'fooRuntime'); - sinon.stub(helper, 'getSkillFlowInstance').throws(new Error(TEST_ERROR)); - - instance._getSkillRunFlow('fooSkillId', 'fooProfile', CONSTANTS.ALEXA.REGION.DEFAULT, false, false, - false, CONSTANTS.RUN.DEFAULT_DEBUG_PORT, 'fooToken', CONSTANTS.ALEXA.REGION.NA, (err) => { - // verify - expect(err.message).eq(TEST_ERROR); - done(); - }); - }); - }); - }); - - describe('_getHostedSkillRuntime test', () => { - let instance; - - beforeEach(() => { - instance = new RunCommand(optionModel); - }); - afterEach(() => { - sinon.restore(); - }); - const smapiClient = new SmapiClient({ - TEST_PROFILE, - doDebug: false - }); - it('| getAlexaHostedSkillMetadata error', (done) => { - sinon.stub(smapiClient.skill.alexaHosted, 'getAlexaHostedSkillMetadata').yields(new Error(TEST_ERROR)); - instance._getHostedSkillRuntime(smapiClient, 'fooSkillId', (err) => { - expect(err.message).eq(TEST_ERROR); - done(); - }); - }); - - it('| getAlexaHostedSkillMetadata empty response', (done) => { - sinon.stub(smapiClient.skill.alexaHosted, 'getAlexaHostedSkillMetadata').yields(null, {}); - instance._getHostedSkillRuntime(smapiClient, 'fooSkillId', (err) => { - expect(err.message).eq('Received an empty response body from getAlexaHostedSkillMetadata'); - done(); - }); - }); - - it('| getAlexaHostedSkillMetadata empty runtime value', (done) => { - sinon.stub(smapiClient.skill.alexaHosted, 'getAlexaHostedSkillMetadata').yields(null, { - body: { - alexaHosted: { - runtime: '' - } - } - }); - instance._getHostedSkillRuntime(smapiClient, 'fooSkillId', (err) => { - expect(err.message).eq('Unable to determine runtime of the hosted skill - fooSkillId'); - done(); - }); - }); - }); -}); diff --git a/test/unit/commands/run/index-test.ts b/test/unit/commands/run/index-test.ts new file mode 100644 index 00000000..e70070f9 --- /dev/null +++ b/test/unit/commands/run/index-test.ts @@ -0,0 +1,287 @@ +import {expect} from "chai"; +import path from "path"; +import sinon from "sinon"; +import AuthorizationController from "../../../../lib/controllers/authorization-controller"; +import RunCommand from "../../../../lib/commands/run"; +import optionModel from "../../../../lib/commands/option-model.json"; +import Messenger from "../../../../lib/view/messenger"; +import ResourcesConfig from "../../../../lib/model/resources-config"; +import profileHelper from "../../../../lib/utils/profile-helper"; +import CONSTANTS from "../../../../lib/utils/constants"; +import helper from "../../../../lib/commands/run/helper"; +import SmapiClient from "../../../../lib/clients/smapi-client"; +import {OptionModel} from "../../../../lib/commands/option-validator"; + +const TEST_PROFILE = "default"; +const TEST_CMD = { + profile: TEST_PROFILE, +}; +const RESOURCE_CONFIG_FIXTURE_PATH = path.join(process.cwd(), "test", "unit", "fixture", "model", "regular-proj"); +const INVALID_RESOURCES_CONFIG_JSON_PATH = path.join(RESOURCE_CONFIG_FIXTURE_PATH, "random-json-config.json"); +const VALID_RESOURCES_CONFIG_JSON_PATH = path.join(RESOURCE_CONFIG_FIXTURE_PATH, "ask-resources.json"); + +describe("Commands Run test - command class test", () => { + const TEST_ERROR = "error"; + let errorStub: sinon.SinonStub; + let infoStub: sinon.SinonStub; + beforeEach(() => { + errorStub = sinon.stub(); + infoStub = sinon.stub(); + sinon.stub(Messenger, "getInstance").returns({ + error: errorStub, + info: infoStub, + }); + sinon.stub(AuthorizationController.prototype, "tokenRefreshAndRead").yields(); + }); + + afterEach(() => { + sinon.restore(); + }); + + it("| validate command information is set correctly", () => { + const instance = new RunCommand(optionModel as OptionModel); + expect(instance.name()).eq("run"); + expect(instance.description()).eq( + "Starts a local instance of your project as the skill endpoint." + + " Automatically re-routes development requests and responses between the Alexa service and your local instance.", + ); + expect(instance.requiredOptions()).deep.eq([]); + expect(instance.optionalOptions()).deep.eq(["debug-port", "wait-for-attach", "watch", "region", "profile", "debug"]); + }); + describe("# validate command handle", () => { + let instance: RunCommand; + + beforeEach(() => { + instance = new RunCommand(optionModel as OptionModel); + }); + + afterEach(() => { + sinon.restore(); + }); + + it("| no resources config file found", async () => { + // setup + const TEST_CMD_WITH_VALUES = {}; + sinon.stub(profileHelper, "runtimeProfile").returns(TEST_PROFILE); + sinon.stub(path, "join").returns("fooPath"); + // call + await expect(instance.handle(TEST_CMD_WITH_VALUES)).rejectedWith( + "File fooPath not exists. If this is a skill project managed by v1 ask-cli, " + + "please run 'ask util upgrade-project' then try the command again.", + ); + }); + + it("| unable to fetch skillId from resources config file", async () => { + // setup + const TEST_CMD_WITH_VALUES = {}; + sinon.stub(profileHelper, "runtimeProfile").returns(TEST_PROFILE); + sinon.stub(path, "join").returns(INVALID_RESOURCES_CONFIG_JSON_PATH); + // call + await expect(instance.handle(TEST_CMD_WITH_VALUES)).rejectedWith( + `Failed to obtain skill-id for the given profile - ${TEST_PROFILE}. Please deploy you skill project first.`, + ); + }); + + it("| error while getting access token", async () => { + // setup + sinon.stub(profileHelper, "runtimeProfile").returns(TEST_PROFILE); + sinon.stub(path, "join").returns(VALID_RESOURCES_CONFIG_JSON_PATH); + sinon.stub(ResourcesConfig.prototype, "getSkillId").returns("TestSkillId"); + sinon.stub(RunCommand.prototype, "_getAccessTokenForProfile").rejects(new Error(TEST_ERROR)); + + // call + await expect(instance.handle(TEST_CMD)).rejectedWith(TEST_ERROR); + + // verify + expect(errorStub.args[0][0].message).eq(TEST_ERROR); + }); + + it("| error while getting debug flow", async () => { + // setup + sinon.stub(profileHelper, "runtimeProfile").returns(TEST_PROFILE); + sinon.stub(path, "join").returns(VALID_RESOURCES_CONFIG_JSON_PATH); + sinon.stub(ResourcesConfig.prototype, "getSkillId").returns("TestSkillId"); + sinon.stub(RunCommand.prototype, "_getAccessTokenForProfile").resolves(""); + sinon.stub(RunCommand.prototype, "_getSkillRunFlow").rejects(new Error(TEST_ERROR)); + // call + await expect(instance.handle(TEST_CMD)).rejectedWith(TEST_ERROR); + expect(errorStub.args[0][0].message).eq(TEST_ERROR); + }); + }); + describe("_getSkillRunFlow test", () => { + let instance: RunCommand; + + beforeEach(() => { + instance = new RunCommand(optionModel as OptionModel); + }); + + afterEach(() => { + sinon.restore(); + }); + + describe("run flow for non-hosted skill", () => { + beforeEach(() => { + sinon.stub(ResourcesConfig.prototype, "getSkillInfraType").returns(CONSTANTS.DEPLOYER_TYPE.CFN.NAME); + }); + afterEach(() => { + sinon.restore(); + }); + it("| getSkillCodeFolderName error", async () => { + sinon.stub(helper, "getSkillCodeFolderName").throws(new Error(TEST_ERROR)); + + await expect( + instance._getSkillRunFlow( + "fooSkillId", + "fooProfile", + CONSTANTS.ALEXA.REGION.DEFAULT, + false, + false, + false, + CONSTANTS.RUN.DEFAULT_DEBUG_PORT, + "fooToken", + CONSTANTS.ALEXA.REGION.NA, + ), + ).rejectedWith(TEST_ERROR); + }); + + it("| no user config", async () => { + sinon.stub(helper, "getSkillCodeFolderName").returns("fooSkillFolderName"); + sinon.stub(ResourcesConfig.prototype, "getSkillInfraUserConfig").returns(undefined); + + await expect( + instance._getSkillRunFlow( + "fooSkillId", + "fooProfile", + CONSTANTS.ALEXA.REGION.DEFAULT, + false, + false, + false, + CONSTANTS.RUN.DEFAULT_DEBUG_PORT, + "fooToken", + CONSTANTS.ALEXA.REGION.NA, + ), + ).rejectedWith("Failed to obtain userConfig from project " + `resource file ${CONSTANTS.FILE_PATH.ASK_RESOURCES_JSON_CONFIG}`); + }); + + it("| empty user config", async () => { + sinon.stub(helper, "getSkillCodeFolderName").returns("fooSkillFolderName"); + sinon.stub(ResourcesConfig.prototype, "getSkillInfraUserConfig").returns({}); + + await expect( + instance._getSkillRunFlow( + "fooSkillId", + "fooProfile", + CONSTANTS.ALEXA.REGION.DEFAULT, + false, + false, + false, + CONSTANTS.RUN.DEFAULT_DEBUG_PORT, + "fooToken", + CONSTANTS.ALEXA.REGION.NA, + ), + ).rejectedWith(`Failed to obtain runtime from userConfig in project resource file ${CONSTANTS.FILE_PATH.ASK_RESOURCES_JSON_CONFIG}`); + }); + + it("| error in getting skill flow instance", async () => { + sinon.stub(helper, "getSkillCodeFolderName").returns("fooSkillFolderName"); + sinon.stub(ResourcesConfig.prototype, "getSkillInfraUserConfig").returns({runtime: CONSTANTS.RUNTIME.JAVA, handler: "fooHandler"}); + sinon.stub(helper, "getSkillFlowInstance").throws(new Error(TEST_ERROR)); + + await expect( + instance._getSkillRunFlow( + "fooSkillId", + "fooProfile", + CONSTANTS.ALEXA.REGION.DEFAULT, + false, + false, + false, + CONSTANTS.RUN.DEFAULT_DEBUG_PORT, + "fooToken", + CONSTANTS.ALEXA.REGION.NA, + ), + ).rejectedWith(TEST_ERROR); + }); + }); + describe("run flow for hosted skill", () => { + beforeEach(() => { + sinon.stub(ResourcesConfig.prototype, "getSkillInfraType").returns(CONSTANTS.DEPLOYER_TYPE.HOSTED.NAME); + }); + + it("| error in getting hosted skill runtime", async () => { + sinon.stub(RunCommand.prototype, "_getHostedSkillRuntime").rejects(new Error(TEST_ERROR)); + + await expect( + instance._getSkillRunFlow( + "fooSkillId", + "fooProfile", + CONSTANTS.ALEXA.REGION.DEFAULT, + false, + false, + false, + CONSTANTS.RUN.DEFAULT_DEBUG_PORT, + "fooToken", + CONSTANTS.ALEXA.REGION.NA, + ), + ).rejectedWith(TEST_ERROR); + }); + + it("| error in getting skill flow instance", async () => { + sinon.stub(RunCommand.prototype, "_getHostedSkillRuntime").resolves("fooRuntime"); + sinon.stub(helper, "getSkillFlowInstance").throws(new Error(TEST_ERROR)); + + await expect( + instance._getSkillRunFlow( + "fooSkillId", + "fooProfile", + CONSTANTS.ALEXA.REGION.DEFAULT, + false, + false, + false, + CONSTANTS.RUN.DEFAULT_DEBUG_PORT, + "fooToken", + CONSTANTS.ALEXA.REGION.NA, + ), + ).rejectedWith(TEST_ERROR); + }); + }); + }); + + describe("_getHostedSkillRuntime test", () => { + let instance: RunCommand; + + beforeEach(() => { + instance = new RunCommand(optionModel as OptionModel); + }); + afterEach(() => { + sinon.restore(); + }); + const smapiClient = new SmapiClient({ + profile: TEST_PROFILE, + doDebug: false, + }); + it("| getAlexaHostedSkillMetadata error", async () => { + sinon.stub(smapiClient.skill.alexaHosted, "getAlexaHostedSkillMetadata").yields(new Error(TEST_ERROR)); + await expect(instance._getHostedSkillRuntime(smapiClient, "fooSkillId")).rejectedWith(TEST_ERROR); + }); + + it("| getAlexaHostedSkillMetadata empty response", async () => { + sinon.stub(smapiClient.skill.alexaHosted, "getAlexaHostedSkillMetadata").yields(null, {}); + await expect(instance._getHostedSkillRuntime(smapiClient, "fooSkillId")).rejectedWith( + "Received an empty response body from getAlexaHostedSkillMetadata", + ); + }); + + it("| getAlexaHostedSkillMetadata empty runtime value", async () => { + sinon.stub(smapiClient.skill.alexaHosted, "getAlexaHostedSkillMetadata").yields(null, { + body: { + alexaHosted: { + runtime: "", + }, + }, + }); + await expect(instance._getHostedSkillRuntime(smapiClient, "fooSkillId")).rejectedWith( + "Unable to determine runtime of the hosted skill - fooSkillId", + ); + }); + }); +}); diff --git a/test/unit/commands/run/run-flow/java-run-test.js b/test/unit/commands/run/run-flow/java-run-test.js index 956e2cec..275af808 100644 --- a/test/unit/commands/run/run-flow/java-run-test.js +++ b/test/unit/commands/run/run-flow/java-run-test.js @@ -1,43 +1,51 @@ -const { expect } = require('chai'); -const JavaRunFlow = require('@src/commands/run/run-flow/java-run'); -const CONSTANTS = require('@src/utils/constants'); +const {expect} = require("chai"); +const JavaRunFlow = require("../../../../../lib/commands/run/run-flow/java-run"); +const CONSTANTS = require("../../../../../lib/utils/constants"); -describe('Java run flow test', () => { - const skillInvocationInfo = { - skillCodeFolderName: 'fooFolder', - handlerName: 'fooHandler' - }; - it('| validate nodemon config, run mode', () => { - const runFlow = new JavaRunFlow({ skillInvocationInfo, - waitForAttach: false, - debugPort: CONSTANTS.RUN.DEFAULT_DEBUG_PORT, - token: 'fooToken', - skillId: 'fooSkill', - runRegion: CONSTANTS.ALEXA.REGION.NA, - watch: false }); - const nodemonConfig = runFlow.getExecConfig(); - expect(nodemonConfig.exec).eq('cd fooFolder;' - + ' mvn exec:exec -Dexec.executable=java ' - + '-Dexec.args="-classpath %classpath com.amazon.ask.localdebug.LocalDebuggerInvoker ' - + '--accessToken fooToken --skillId fooSkill --skillStreamHandlerClass fooHandler --region NA"'); - expect(nodemonConfig.ext).eq('java, xml'); - expect(nodemonConfig.watch).eq(false); +describe("Java run flow test", () => { + const skillInvocationInfo = { + skillCodeFolderName: "fooFolder", + handlerName: "fooHandler", + }; + it("| validate nodemon config, run mode", () => { + const runFlow = new JavaRunFlow({ + skillInvocationInfo, + waitForAttach: false, + debugPort: CONSTANTS.RUN.DEFAULT_DEBUG_PORT, + token: "fooToken", + skillId: "fooSkill", + runRegion: CONSTANTS.ALEXA.REGION.NA, + watch: false, }); - it('| validate nodemon config, debug mode, watch enabled', () => { - const runFlow = new JavaRunFlow({ skillInvocationInfo, - waitForAttach: true, - debugPort: CONSTANTS.RUN.DEFAULT_DEBUG_PORT, - token: 'fooToken', - skillId: 'fooSkill', - runRegion: CONSTANTS.ALEXA.REGION.NA, - watch: true }); - const nodemonConfig = runFlow.getExecConfig(); - expect(nodemonConfig.exec).eq('cd fooFolder; ' - + 'mvn exec:exec -Dexec.executable=java ' - + '-Dexec.args="-classpath %classpath -Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=5000 ' - + 'com.amazon.ask.localdebug.LocalDebuggerInvoker --accessToken fooToken --skillId fooSkill ' - + '--region NA --skillStreamHandlerClass fooHandler"'); - expect(nodemonConfig.ext).eq('java, xml'); - expect(nodemonConfig.watch).eq('fooFolder'); + const nodemonConfig = runFlow.getExecConfig(); + expect(nodemonConfig.exec).eq( + "cd fooFolder;" + + " mvn exec:exec -Dexec.executable=java " + + '-Dexec.args="-classpath %classpath com.amazon.ask.localdebug.LocalDebuggerInvoker ' + + '--accessToken fooToken --skillId fooSkill --skillStreamHandlerClass fooHandler --region NA"', + ); + expect(nodemonConfig.ext).eq("java, xml"); + expect(nodemonConfig.watch).eq(false); + }); + it("| validate nodemon config, debug mode, watch enabled", () => { + const runFlow = new JavaRunFlow({ + skillInvocationInfo, + waitForAttach: true, + debugPort: CONSTANTS.RUN.DEFAULT_DEBUG_PORT, + token: "fooToken", + skillId: "fooSkill", + runRegion: CONSTANTS.ALEXA.REGION.NA, + watch: true, }); + const nodemonConfig = runFlow.getExecConfig(); + expect(nodemonConfig.exec).eq( + "cd fooFolder; " + + "mvn exec:exec -Dexec.executable=java " + + '-Dexec.args="-classpath %classpath -Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=5000 ' + + "com.amazon.ask.localdebug.LocalDebuggerInvoker --accessToken fooToken --skillId fooSkill " + + '--region NA --skillStreamHandlerClass fooHandler"', + ); + expect(nodemonConfig.ext).eq("java, xml"); + expect(nodemonConfig.watch).eq("fooFolder"); + }); }); diff --git a/test/unit/commands/run/run-flow/nodejs-run-test.js b/test/unit/commands/run/run-flow/nodejs-run-test.js index 0b826c4b..b0899132 100644 --- a/test/unit/commands/run/run-flow/nodejs-run-test.js +++ b/test/unit/commands/run/run-flow/nodejs-run-test.js @@ -1,86 +1,94 @@ -const { expect } = require('chai'); -const path = require('path'); -const fs = require('fs'); -const sinon = require('sinon'); -const NodejsRunFlow = require('@src/commands/run/run-flow/nodejs-run'); -const CONSTANTS = require('@src/utils/constants'); +const {expect} = require("chai"); +const path = require("path"); +const fs = require("fs"); +const sinon = require("sinon"); +const NodejsRunFlow = require("../../../../../lib/commands/run/run-flow/nodejs-run"); +const CONSTANTS = require("../../../../../lib/utils/constants"); -describe('Node run flow test', () => { - const skillInvocationInfo = { - skillCodeFolderName: 'fooFolder', - handlerName: 'fooHandler', - skillFileName: 'fooFileName' - }; - afterEach(() => { - sinon.restore(); +describe("Node run flow test", () => { + const skillInvocationInfo = { + skillCodeFolderName: "fooFolder", + handlerName: "fooHandler", + skillFileName: "fooFileName", + }; + afterEach(() => { + sinon.restore(); + }); + it("| validate nodemon config, run mode", () => { + sinon.stub(fs, "existsSync").returns(true); + const runFlow = new NodejsRunFlow({ + skillInvocationInfo, + waitForAttach: false, + debugPort: CONSTANTS.RUN.DEFAULT_DEBUG_PORT, + token: "fooToken", + skillId: "fooSkill", + runRegion: CONSTANTS.ALEXA.REGION.NA, + watch: false, }); - it('| validate nodemon config, run mode', () => { - sinon.stub(fs, 'existsSync').returns(true); - const runFlow = new NodejsRunFlow({ skillInvocationInfo, - waitForAttach: false, - debugPort: CONSTANTS.RUN.DEFAULT_DEBUG_PORT, - token: 'fooToken', - skillId: 'fooSkill', - runRegion: CONSTANTS.ALEXA.REGION.NA, - watch: false }); - const nodemonConfig = runFlow.getExecConfig(); - expect(nodemonConfig.execMap).eq(undefined); - expect(nodemonConfig.script).eq(path.join(process.cwd(), 'fooFolder', CONSTANTS.RUN.NODE.SCRIPT_LOCATION)); - expect(nodemonConfig.args).to.deep.equal([ - '--accessToken', - '"fooToken"', - '--skillId', - 'fooSkill', - '--handlerName', - 'fooHandler', - '--skillEntryFile', - path.join(process.cwd(), 'fooFolder', 'fooFileName.js'), - '--region', - CONSTANTS.ALEXA.REGION.NA - ]); - expect(nodemonConfig.watch).eq(false); + const nodemonConfig = runFlow.getExecConfig(); + expect(nodemonConfig.execMap).eq(undefined); + expect(nodemonConfig.script).eq(path.join(process.cwd(), "fooFolder", CONSTANTS.RUN.NODE.SCRIPT_LOCATION)); + expect(nodemonConfig.args).to.deep.equal([ + "--accessToken", + '"fooToken"', + "--skillId", + "fooSkill", + "--handlerName", + "fooHandler", + "--skillEntryFile", + path.join(process.cwd(), "fooFolder", "fooFileName.js"), + "--region", + CONSTANTS.ALEXA.REGION.NA, + ]); + expect(nodemonConfig.watch).eq(false); + }); + it("| validate nodemon config, debug mode, watch enabled", () => { + sinon.stub(fs, "existsSync").returns(true); + const runFlow = new NodejsRunFlow({ + skillInvocationInfo, + waitForAttach: true, + debugPort: CONSTANTS.RUN.DEFAULT_DEBUG_PORT, + token: "fooToken", + skillId: "fooSkill", + runRegion: CONSTANTS.ALEXA.REGION.NA, + watch: true, }); - it('| validate nodemon config, debug mode, watch enabled', () => { - sinon.stub(fs, 'existsSync').returns(true); - const runFlow = new NodejsRunFlow({ skillInvocationInfo, - waitForAttach: true, - debugPort: CONSTANTS.RUN.DEFAULT_DEBUG_PORT, - token: 'fooToken', - skillId: 'fooSkill', - runRegion: CONSTANTS.ALEXA.REGION.NA, - watch: true }); - const nodemonConfig = runFlow.getExecConfig(); - expect(nodemonConfig.execMap).to.deep.equal({ - js: `node --inspect-brk=${CONSTANTS.RUN.DEFAULT_DEBUG_PORT}` - }); - expect(nodemonConfig.script).eq(path.join(process.cwd(), 'fooFolder', CONSTANTS.RUN.NODE.SCRIPT_LOCATION)); - expect(nodemonConfig.args).to.deep.equal([ - '--accessToken', - '"fooToken"', - '--skillId', - 'fooSkill', - '--handlerName', - 'fooHandler', - '--skillEntryFile', - path.join(process.cwd(), 'fooFolder', 'fooFileName.js'), - '--region', - CONSTANTS.ALEXA.REGION.NA - ]); - expect(nodemonConfig.watch).eq('fooFolder'); - }); - it('| ask-sdk-local-debug has not been installed', () => { - sinon.stub(fs, 'existsSync').returns(false); - try { - new NodejsRunFlow({ skillInvocationInfo, - waitForAttach: true, - debugPort: CONSTANTS.RUN.DEFAULT_DEBUG_PORT, - token: 'fooToken', - skillId: 'fooSkill', - runRegion: CONSTANTS.ALEXA.REGION.NA, - watch: true }); - } catch (err) { - expect(err.message).eq('ask-sdk-local-debug cannot be found. Please install ask-sdk-local-debug to your skill code project. ' - + 'Refer https://www.npmjs.com/package/ask-sdk-local-debug for more info.'); - } + const nodemonConfig = runFlow.getExecConfig(); + expect(nodemonConfig.execMap).to.deep.equal({ + js: `node --inspect-brk=${CONSTANTS.RUN.DEFAULT_DEBUG_PORT}`, }); + expect(nodemonConfig.script).eq(path.join(process.cwd(), "fooFolder", CONSTANTS.RUN.NODE.SCRIPT_LOCATION)); + expect(nodemonConfig.args).to.deep.equal([ + "--accessToken", + '"fooToken"', + "--skillId", + "fooSkill", + "--handlerName", + "fooHandler", + "--skillEntryFile", + path.join(process.cwd(), "fooFolder", "fooFileName.js"), + "--region", + CONSTANTS.ALEXA.REGION.NA, + ]); + expect(nodemonConfig.watch).eq("fooFolder"); + }); + it("| ask-sdk-local-debug has not been installed", () => { + sinon.stub(fs, "existsSync").returns(false); + try { + new NodejsRunFlow({ + skillInvocationInfo, + waitForAttach: true, + debugPort: CONSTANTS.RUN.DEFAULT_DEBUG_PORT, + token: "fooToken", + skillId: "fooSkill", + runRegion: CONSTANTS.ALEXA.REGION.NA, + watch: true, + }); + } catch (err) { + expect(err.message).eq( + "ask-sdk-local-debug cannot be found. Please install ask-sdk-local-debug to your skill code project. " + + "Refer https://www.npmjs.com/package/ask-sdk-local-debug for more info.", + ); + } + }); }); diff --git a/test/unit/commands/run/run-flow/python-run-test.js b/test/unit/commands/run/run-flow/python-run-test.js index 4ded140c..e8dbb687 100644 --- a/test/unit/commands/run/run-flow/python-run-test.js +++ b/test/unit/commands/run/run-flow/python-run-test.js @@ -1,111 +1,110 @@ -const { expect } = require('chai'); -const path = require('path'); -const fs = require('fs'); -const sinon = require('sinon'); -const childProcess = require('child_process'); -const PythonRunFlow = require('@src/commands/run/run-flow/python-run'); -const CONSTANTS = require('@src/utils/constants'); +const {expect} = require("chai"); +const path = require("path"); +const fs = require("fs"); +const sinon = require("sinon"); +const childProcess = require("child_process"); +const PythonRunFlow = require("../../../../../lib/commands/run/run-flow/python-run"); +const CONSTANTS = require("../../../../../lib/utils/constants"); -describe('Python run flow test', () => { - const skillPackagePath = 'fooPythonPath'; - const pythonDebugPath = path.join(skillPackagePath, CONSTANTS.RUN.PYTHON.SCRIPT_LOCATION); - const skillInvocationInfo = { - skillCodeFolderName: 'fooFolder', - handlerName: 'fooHandler', - skillFileName: 'fooFileName' - }; - beforeEach(() => { - sinon.stub(childProcess, 'execSync').withArgs('python3 -c "import site; import json; print(json.dumps(site.getsitepackages()))"') - .returns('') - .withArgs('python3 -m pip install debugpy', { stdio: 'inherit' }) - .returns(''); - sinon.stub(JSON, 'parse').returns([ - skillPackagePath - ]); +describe("Python run flow test", () => { + const skillPackagePath = "fooPythonPath"; + const pythonDebugPath = path.join(skillPackagePath, CONSTANTS.RUN.PYTHON.SCRIPT_LOCATION); + const skillInvocationInfo = { + skillCodeFolderName: "fooFolder", + handlerName: "fooHandler", + skillFileName: "fooFileName", + }; + beforeEach(() => { + sinon + .stub(childProcess, "execSync") + .withArgs('python3 -c "import site; import json; print(json.dumps(site.getsitepackages()))"') + .returns("") + .withArgs("python3 -m pip install debugpy", {stdio: "inherit"}) + .returns(""); + sinon.stub(JSON, "parse").returns([skillPackagePath]); + }); + afterEach(() => { + sinon.restore(); + }); + it("| validate nodemon config, run mode", () => { + sinon.stub(fs, "existsSync").withArgs(skillPackagePath).returns(true).withArgs(pythonDebugPath).returns(true); + const runFlow = new PythonRunFlow({ + skillInvocationInfo, + waitForAttach: false, + debugPort: CONSTANTS.RUN.DEFAULT_DEBUG_PORT, + token: "fooToken", + skillId: "fooSkill", + runRegion: CONSTANTS.ALEXA.REGION.NA, + watch: false, }); - afterEach(() => { - sinon.restore(); + const nodemonConfig = runFlow.getExecConfig(); + expect(nodemonConfig.execMap).to.deep.equal({ + py: "python3", }); - it('| validate nodemon config, run mode', () => { - sinon.stub(fs, 'existsSync').withArgs(skillPackagePath) - .returns(true) - .withArgs(pythonDebugPath) - .returns(true); - const runFlow = new PythonRunFlow({ skillInvocationInfo, - waitForAttach: false, - debugPort: CONSTANTS.RUN.DEFAULT_DEBUG_PORT, - token: 'fooToken', - skillId: 'fooSkill', - runRegion: CONSTANTS.ALEXA.REGION.NA, - watch: false }); - const nodemonConfig = runFlow.getExecConfig(); - expect(nodemonConfig.execMap).to.deep.equal({ - py: 'python3' - }); - expect(nodemonConfig.script).eq(pythonDebugPath); - expect(nodemonConfig.args).to.deep.equal([ - '--accessToken', - '"fooToken"', - '--skillId', - 'fooSkill', - '--skillHandler', - 'fooHandler', - '--skillFilePath', - path.join('fooFolder', 'fooFileName.py'), - '--region', - CONSTANTS.ALEXA.REGION.NA - ]); - expect(nodemonConfig.watch).eq(false); - expect(nodemonConfig.ext).eq('py,json,txt'); + expect(nodemonConfig.script).eq(pythonDebugPath); + expect(nodemonConfig.args).to.deep.equal([ + "--accessToken", + '"fooToken"', + "--skillId", + "fooSkill", + "--skillHandler", + "fooHandler", + "--skillFilePath", + path.join("fooFolder", "fooFileName.py"), + "--region", + CONSTANTS.ALEXA.REGION.NA, + ]); + expect(nodemonConfig.watch).eq(false); + expect(nodemonConfig.ext).eq("py,json,txt"); + }); + it("| validate nodemon config, debug mode, watch enabled", () => { + sinon.stub(fs, "existsSync").withArgs(skillPackagePath).returns(true).withArgs(pythonDebugPath).returns(true); + const runFlow = new PythonRunFlow({ + skillInvocationInfo, + waitForAttach: true, + debugPort: CONSTANTS.RUN.DEFAULT_DEBUG_PORT, + token: "fooToken", + skillId: "fooSkill", + runRegion: CONSTANTS.ALEXA.REGION.NA, + watch: true, }); - it('| validate nodemon config, debug mode, watch enabled', () => { - sinon.stub(fs, 'existsSync').withArgs(skillPackagePath) - .returns(true) - .withArgs(pythonDebugPath) - .returns(true); - const runFlow = new PythonRunFlow({ skillInvocationInfo, - waitForAttach: true, - debugPort: CONSTANTS.RUN.DEFAULT_DEBUG_PORT, - token: 'fooToken', - skillId: 'fooSkill', - runRegion: CONSTANTS.ALEXA.REGION.NA, - watch: true }); - const nodemonConfig = runFlow.getExecConfig(); - expect(nodemonConfig.execMap).to.deep.equal({ - py: `python3 -m debugpy --listen ${CONSTANTS.RUN.DEFAULT_DEBUG_PORT} --wait-for-client` - }); - expect(nodemonConfig.script).eq(path.join('fooPythonPath', CONSTANTS.RUN.PYTHON.SCRIPT_LOCATION)); - expect(nodemonConfig.args).to.deep.equal([ - '--accessToken', - '"fooToken"', - '--skillId', - 'fooSkill', - '--skillHandler', - 'fooHandler', - '--skillFilePath', - path.join('fooFolder', 'fooFileName.py'), - '--region', - CONSTANTS.ALEXA.REGION.NA - ]); - expect(nodemonConfig.watch).eq('fooFolder'); - expect(nodemonConfig.ext).eq('py,json,txt'); - }); - it('| ask-sdk-local-debug has not been installed', () => { - sinon.stub(fs, 'existsSync').withArgs(skillPackagePath) - .returns(true) - .withArgs(pythonDebugPath) - .returns(false); - try { - new PythonRunFlow({ skillInvocationInfo, - waitForAttach: true, - debugPort: CONSTANTS.RUN.DEFAULT_DEBUG_PORT, - token: 'fooToken', - skillId: 'fooSkill', - runRegion: CONSTANTS.ALEXA.REGION.NA, - watch: true }); - } catch (err) { - expect(err.message).eq('ask-sdk-local-debug cannot be found. Please install ask-sdk-local-debug to your skill code project. ' - + 'Refer https://pypi.org/project/ask-sdk-local-debug, for more info.'); - } + const nodemonConfig = runFlow.getExecConfig(); + expect(nodemonConfig.execMap).to.deep.equal({ + py: `python3 -m debugpy --listen ${CONSTANTS.RUN.DEFAULT_DEBUG_PORT} --wait-for-client`, }); + expect(nodemonConfig.script).eq(path.join("fooPythonPath", CONSTANTS.RUN.PYTHON.SCRIPT_LOCATION)); + expect(nodemonConfig.args).to.deep.equal([ + "--accessToken", + '"fooToken"', + "--skillId", + "fooSkill", + "--skillHandler", + "fooHandler", + "--skillFilePath", + path.join("fooFolder", "fooFileName.py"), + "--region", + CONSTANTS.ALEXA.REGION.NA, + ]); + expect(nodemonConfig.watch).eq("fooFolder"); + expect(nodemonConfig.ext).eq("py,json,txt"); + }); + it("| ask-sdk-local-debug has not been installed", () => { + sinon.stub(fs, "existsSync").withArgs(skillPackagePath).returns(true).withArgs(pythonDebugPath).returns(false); + try { + new PythonRunFlow({ + skillInvocationInfo, + waitForAttach: true, + debugPort: CONSTANTS.RUN.DEFAULT_DEBUG_PORT, + token: "fooToken", + skillId: "fooSkill", + runRegion: CONSTANTS.ALEXA.REGION.NA, + watch: true, + }); + } catch (err) { + expect(err.message).eq( + "ask-sdk-local-debug cannot be found. Please install ask-sdk-local-debug to your skill code project. " + + "Refer https://pypi.org/project/ask-sdk-local-debug, for more info.", + ); + } + }); }); diff --git a/test/unit/commands/skill/add-locales/helper-test.js b/test/unit/commands/skill/add-locales/helper-test.js index ecc5b402..7252f56c 100644 --- a/test/unit/commands/skill/add-locales/helper-test.js +++ b/test/unit/commands/skill/add-locales/helper-test.js @@ -1,188 +1,191 @@ -const { expect } = require('chai'); -const sinon = require('sinon'); -const fs = require('fs-extra'); -const path = require('path'); - -const httpClient = require('@src/clients/http-client'); -const SkillMetadataController = require('@src/controllers/skill-metadata-controller'); -const helper = require('@src/commands/skill/add-locales/helper'); -const Manifest = require('@src/model/manifest'); -const ResourcesConfig = require('@src/model/resources-config'); -const CONSTANTS = require('@src/utils/constants'); -const stringUtils = require('@src/utils/string-utils'); - -describe('Commands add-locales - helper test', () => { - const FIXTURE_RESOURCES_CONFIG_FILE_PATH = path.join(process.cwd(), 'test', 'unit', 'fixture', 'model', 'regular-proj', 'ask-resources.json'); - const FIXTURE_MANIFEST_FILE_PATH = path.join(process.cwd(), 'test', 'unit', 'fixture', 'model', 'manifest.json'); - const TEST_PROFILE = 'profile'; - const TEST_DEBUG = false; - - describe('# unit test for method initiateModels', () => { - beforeEach(() => { - sinon.stub(path, 'join') - .onFirstCall() - .returns(FIXTURE_RESOURCES_CONFIG_FILE_PATH) - .onSecondCall() - .returns(FIXTURE_MANIFEST_FILE_PATH); - }); - - afterEach(() => { - sinon.restore(); - }); - - it('| skill package source is not set, expect throw error', () => { - // setup - sinon.stub(stringUtils, 'isNonBlankString').returns(false); - // call & verify - expect(() => helper.initiateModels(TEST_PROFILE)).to.throw('Skill package src is not found in ask-resources.json.'); - }); - - it('| skill package source does not exist, expect throw error', () => { - // setup - sinon.stub(stringUtils, 'isNonBlankString').returns(true); - sinon.stub(fs, 'existsSync').returns(false); - // call & verify - expect(() => helper.initiateModels(TEST_PROFILE)).to.throw(/The skillMetadata src file/); - }); - - it('| project model intiated successfully', () => { - // setup - sinon.stub(stringUtils, 'isNonBlankString').returns(true); - sinon.stub(fs, 'existsSync').returns(true); - // call - expect(() => helper.initiateModels(TEST_PROFILE)).not.to.throw(); - }); +const {expect} = require("chai"); +const sinon = require("sinon"); +const fs = require("fs-extra"); +const path = require("path"); + +const httpClient = require("../../../../../lib/clients/http-client"); +const SkillMetadataController = require("../../../../../lib/controllers/skill-metadata-controller"); +const helper = require("../../../../../lib/commands/skill/add-locales/helper"); +const Manifest = require("../../../../../lib/model/manifest"); +const ResourcesConfig = require("../../../../../lib/model/resources-config"); +const stringUtils = require("../../../../../lib/utils/string-utils"); + +describe("Commands add-locales - helper test", () => { + const FIXTURE_RESOURCES_CONFIG_FILE_PATH = path.join( + process.cwd(), + "test", + "unit", + "fixture", + "model", + "regular-proj", + "ask-resources.json", + ); + const FIXTURE_MANIFEST_FILE_PATH = path.join(process.cwd(), "test", "unit", "fixture", "model", "manifest.json"); + const TEST_PROFILE = "profile"; + const TEST_DEBUG = false; + + describe("# unit test for method initiateModels", () => { + beforeEach(() => { + sinon.stub(path, "join").onFirstCall().returns(FIXTURE_RESOURCES_CONFIG_FILE_PATH).onSecondCall().returns(FIXTURE_MANIFEST_FILE_PATH); }); - describe('# unit test for method addLocales', () => { - const TEST_ERROR = 'error'; - const TEST_MODEL_PATH = 'filepath'; - const TEST_SKILL_META_SRC = 'skillmetasrc'; - const TEST_PATH = 'pathdoesnotmatter'; - const TEST_TEMPLATE_BODY = { body: 'template' }; - const TEST_TEMPLATE_MAP = { - statusCode: 200, - body: JSON.stringify({ - INTERACTION_MODEL_BY_LANGUAGE: { - es: 'TEST_ES_URL', - en: 'TEST_EN_URL' - } - }) - }; - new ResourcesConfig(FIXTURE_RESOURCES_CONFIG_FILE_PATH); - new Manifest(FIXTURE_MANIFEST_FILE_PATH); - - beforeEach(() => { - sinon.stub(path, 'join').returns(TEST_PATH); - sinon.stub(httpClient, 'request'); - sinon.stub(SkillMetadataController.prototype, 'getInteractionModelLocales'); - sinon.stub(ResourcesConfig.prototype, 'getSkillMetaSrc').returns(TEST_SKILL_META_SRC); - sinon.stub(fs, 'existsSync'); - sinon.stub(fs, 'copySync'); - sinon.stub(fs, 'writeFileSync'); - sinon.stub(Manifest.prototype, 'write'); - sinon.stub(Manifest.prototype, 'getPublishingLocale').returns({ dummy: 'dummy' }); - }); - - afterEach(() => { - sinon.restore(); - }); - - it('| fail to get the template map with http error', (done) => { - // setup - httpClient.request.onFirstCall().callsArgWith(3, TEST_ERROR); - // call - helper.addLocales(['en-US'], TEST_PROFILE, TEST_DEBUG, (err, result) => { - expect(err).equal('Failed to retrieve the template list.\nError: error'); - expect(result).equal(undefined); - done(); - }); - }); - - it('| fail to get the template map with statusCode not correct', (done) => { - // setup - httpClient.request.onFirstCall().callsArgWith(3, undefined, { statusCode: 401 }); - // call - helper.addLocales(['en-US'], TEST_PROFILE, TEST_DEBUG, (err, result) => { - expect(err).equal(`Failed to retrieve the template list, please see the details from the error response. -${JSON.stringify({ statusCode: 401 }, null, 2)}`); - expect(result).equal(undefined); - done(); - }); - }); - - it('| selected locale is same as local file', (done) => { - // setup - httpClient.request.onFirstCall().callsArgWith(3, undefined, TEST_TEMPLATE_MAP); - SkillMetadataController.prototype.getInteractionModelLocales.returns({ 'en-US': TEST_MODEL_PATH }); - // call - helper.addLocales(['en-US'], TEST_PROFILE, TEST_DEBUG, (err, result) => { - expect(err).equal(undefined); - expect(result.size).equal(0); - done(); - }); - }); - - it('| selected locale has same language as the local file', (done) => { - // setup - httpClient.request.onFirstCall().callsArgWith(3, undefined, TEST_TEMPLATE_MAP); - SkillMetadataController.prototype.getInteractionModelLocales.returns({ 'en-XX': TEST_MODEL_PATH }); - fs.existsSync.returns(true); - // call - helper.addLocales(['en-US'], TEST_PROFILE, TEST_DEBUG, (err, result) => { - expect(fs.copySync.args[0][0]).equal(TEST_MODEL_PATH); - expect(err).equal(undefined); - expect(result.size).equal(1); - expect(result.get('en-US')).deep.equal({ uri: TEST_MODEL_PATH, canCopy: true }); - done(); - }); - }); - - it('| interaction model for the selected locale can only be provided by official template, http fails', (done) => { - // setup - httpClient.request.onFirstCall().callsArgWith(3, undefined, TEST_TEMPLATE_MAP); - SkillMetadataController.prototype.getInteractionModelLocales.returns({ 'es-US': TEST_MODEL_PATH }); - fs.existsSync.returns(false); - httpClient.request.onSecondCall().callsArgWith(3, TEST_ERROR); - // call - helper.addLocales(['en-US'], TEST_PROFILE, TEST_DEBUG, (err, result) => { - expect(err).equal(`Failed to retrieve the template list.\n${TEST_ERROR}`); - expect(result).equal(undefined); - done(); - }); - }); - - it('| interaction model for the selected locale can only be provided by official template, http returns with 4xx', (done) => { - // setup - httpClient.request.onFirstCall().callsArgWith(3, undefined, TEST_TEMPLATE_MAP); - SkillMetadataController.prototype.getInteractionModelLocales.returns({ 'es-US': TEST_MODEL_PATH }); - fs.existsSync.returns(false); - httpClient.request.onSecondCall().callsArgWith(3, null, { statusCode: 401 }); - // call - helper.addLocales(['en-US'], TEST_PROFILE, TEST_DEBUG, (err, result) => { - expect(err).equal(`Failed to retrieve the template list, please see the details from the error response. + afterEach(() => { + sinon.restore(); + }); + + it("| skill package source is not set, expect throw error", () => { + // setup + sinon.stub(stringUtils, "isNonBlankString").returns(false); + // call & verify + expect(() => helper.initiateModels(TEST_PROFILE)).to.throw("Skill package src is not found in ask-resources.json."); + }); + + it("| skill package source does not exist, expect throw error", () => { + // setup + sinon.stub(stringUtils, "isNonBlankString").returns(true); + sinon.stub(fs, "existsSync").returns(false); + // call & verify + expect(() => helper.initiateModels(TEST_PROFILE)).to.throw(/The skillMetadata src file/); + }); + + it("| project model intiated successfully", () => { + // setup + sinon.stub(stringUtils, "isNonBlankString").returns(true); + sinon.stub(fs, "existsSync").returns(true); + // call + expect(() => helper.initiateModels(TEST_PROFILE)).not.to.throw(); + }); + }); + + describe("# unit test for method addLocales", () => { + const TEST_ERROR = "error"; + const TEST_MODEL_PATH = "filepath"; + const TEST_SKILL_META_SRC = "skillmetasrc"; + const TEST_PATH = "pathdoesnotmatter"; + const TEST_TEMPLATE_BODY = {body: "template"}; + const TEST_TEMPLATE_MAP = { + statusCode: 200, + body: JSON.stringify({ + INTERACTION_MODEL_BY_LANGUAGE: { + es: "TEST_ES_URL", + en: "TEST_EN_URL", + }, + }), + }; + new ResourcesConfig(FIXTURE_RESOURCES_CONFIG_FILE_PATH); + new Manifest(FIXTURE_MANIFEST_FILE_PATH); + + beforeEach(() => { + sinon.stub(path, "join").returns(TEST_PATH); + sinon.stub(httpClient, "request"); + sinon.stub(SkillMetadataController.prototype, "getInteractionModelLocales"); + sinon.stub(ResourcesConfig.prototype, "getSkillMetaSrc").returns(TEST_SKILL_META_SRC); + sinon.stub(fs, "existsSync"); + sinon.stub(fs, "copySync"); + sinon.stub(fs, "writeFileSync"); + sinon.stub(Manifest.prototype, "write"); + sinon.stub(Manifest.prototype, "getPublishingLocale").returns({dummy: "dummy"}); + }); + + afterEach(() => { + sinon.restore(); + }); + + it("| fail to get the template map with http error", (done) => { + // setup + httpClient.request.onFirstCall().callsArgWith(3, TEST_ERROR); + // call + helper.addLocales(["en-US"], TEST_PROFILE, TEST_DEBUG, (err, result) => { + expect(err).equal("Failed to retrieve the template list.\nError: error"); + expect(result).equal(undefined); + done(); + }); + }); + + it("| fail to get the template map with statusCode not correct", (done) => { + // setup + httpClient.request.onFirstCall().callsArgWith(3, undefined, {statusCode: 401}); + // call + helper.addLocales(["en-US"], TEST_PROFILE, TEST_DEBUG, (err, result) => { + expect(err).equal(`Failed to retrieve the template list, please see the details from the error response. +${JSON.stringify({statusCode: 401}, null, 2)}`); + expect(result).equal(undefined); + done(); + }); + }); + + it("| selected locale is same as local file", (done) => { + // setup + httpClient.request.onFirstCall().callsArgWith(3, undefined, TEST_TEMPLATE_MAP); + SkillMetadataController.prototype.getInteractionModelLocales.returns({"en-US": TEST_MODEL_PATH}); + // call + helper.addLocales(["en-US"], TEST_PROFILE, TEST_DEBUG, (err, result) => { + expect(err).equal(undefined); + expect(result.size).equal(0); + done(); + }); + }); + + it("| selected locale has same language as the local file", (done) => { + // setup + httpClient.request.onFirstCall().callsArgWith(3, undefined, TEST_TEMPLATE_MAP); + SkillMetadataController.prototype.getInteractionModelLocales.returns({"en-XX": TEST_MODEL_PATH}); + fs.existsSync.returns(true); + // call + helper.addLocales(["en-US"], TEST_PROFILE, TEST_DEBUG, (err, result) => { + expect(fs.copySync.args[0][0]).equal(TEST_MODEL_PATH); + expect(err).equal(undefined); + expect(result.size).equal(1); + expect(result.get("en-US")).deep.equal({uri: TEST_MODEL_PATH, canCopy: true}); + done(); + }); + }); + + it("| interaction model for the selected locale can only be provided by official template, http fails", (done) => { + // setup + httpClient.request.onFirstCall().callsArgWith(3, undefined, TEST_TEMPLATE_MAP); + SkillMetadataController.prototype.getInteractionModelLocales.returns({"es-US": TEST_MODEL_PATH}); + fs.existsSync.returns(false); + httpClient.request.onSecondCall().callsArgWith(3, TEST_ERROR); + // call + helper.addLocales(["en-US"], TEST_PROFILE, TEST_DEBUG, (err, result) => { + expect(err).equal(`Failed to retrieve the template list.\n${TEST_ERROR}`); + expect(result).equal(undefined); + done(); + }); + }); + + it("| interaction model for the selected locale can only be provided by official template, http returns with 4xx", (done) => { + // setup + httpClient.request.onFirstCall().callsArgWith(3, undefined, TEST_TEMPLATE_MAP); + SkillMetadataController.prototype.getInteractionModelLocales.returns({"es-US": TEST_MODEL_PATH}); + fs.existsSync.returns(false); + httpClient.request.onSecondCall().callsArgWith(3, null, {statusCode: 401}); + // call + helper.addLocales(["en-US"], TEST_PROFILE, TEST_DEBUG, (err, result) => { + expect(err).equal(`Failed to retrieve the template list, please see the details from the error response. { "statusCode": 401 }`); - expect(result).equal(undefined); - done(); - }); - }); - - it('| interaction model for the selected locale can only be provided by official template, http request passes', (done) => { - // setup - httpClient.request.onFirstCall().callsArgWith(3, undefined, TEST_TEMPLATE_MAP); - SkillMetadataController.prototype.getInteractionModelLocales.returns({ 'es-US': TEST_MODEL_PATH }); - fs.existsSync.returns(false); - httpClient.request.onSecondCall().callsArgWith(3, null, TEST_TEMPLATE_BODY); - // call - helper.addLocales(['en-US'], TEST_PROFILE, TEST_DEBUG, (err, result) => { - expect(fs.writeFileSync.args[0][1]).equal(TEST_TEMPLATE_BODY.body); - expect(result.size).equal(1); - expect(result.get('en-US')).deep.equal({ uri: 'TEST_EN_URL', canCopy: false }); - expect(err).equal(undefined); - done(); - }); - }); + expect(result).equal(undefined); + done(); + }); + }); + + it("| interaction model for the selected locale can only be provided by official template, http request passes", (done) => { + // setup + httpClient.request.onFirstCall().callsArgWith(3, undefined, TEST_TEMPLATE_MAP); + SkillMetadataController.prototype.getInteractionModelLocales.returns({"es-US": TEST_MODEL_PATH}); + fs.existsSync.returns(false); + httpClient.request.onSecondCall().callsArgWith(3, null, TEST_TEMPLATE_BODY); + // call + helper.addLocales(["en-US"], TEST_PROFILE, TEST_DEBUG, (err, result) => { + expect(fs.writeFileSync.args[0][1]).equal(TEST_TEMPLATE_BODY.body); + expect(result.size).equal(1); + expect(result.get("en-US")).deep.equal({uri: "TEST_EN_URL", canCopy: false}); + expect(err).equal(undefined); + done(); + }); }); + }); }); diff --git a/test/unit/commands/skill/add-locales/index-test.js b/test/unit/commands/skill/add-locales/index-test.js deleted file mode 100644 index 78d6d2e0..00000000 --- a/test/unit/commands/skill/add-locales/index-test.js +++ /dev/null @@ -1,155 +0,0 @@ -const { expect } = require('chai'); -const sinon = require('sinon'); - -const AddLocalesCommand = require('@src/commands/skill/add-locales'); -const helper = require('@src/commands/skill/add-locales/helper'); -const optionModel = require('@src/commands/option-model'); -const ui = require('@src/commands/skill/add-locales/ui'); -const profileHelper = require('@src/utils/profile-helper'); -const Messenger = require('@src/view/messenger'); - -describe('Commands add-locales test - command class test', () => { - const TEST_DEBUG = false; - - let infoStub; - let errorStub; - let warnStub; - - beforeEach(() => { - infoStub = sinon.stub(); - errorStub = sinon.stub(); - warnStub = sinon.stub(); - sinon.stub(Messenger, 'getInstance').returns({ - info: infoStub, - error: errorStub, - warn: warnStub - }); - }); - - afterEach(() => { - sinon.restore(); - }); - - it('| validate command information is set correctly', () => { - const instance = new AddLocalesCommand(optionModel); - expect(instance.name()).equal('add-locales'); - expect(instance.description()).equal('add new locale(s) from existing locale or from the template'); - expect(instance.requiredOptions()).deep.equal([]); - expect(instance.optionalOptions()).deep.equal(['profile', 'debug']); - }); - - describe('validate command handle', () => { - const TEST_ERROR = 'command error'; - const TEST_PROFILE = 'profile'; - const TEST_LOCALES_LIST = ['1', '2', '3']; - const TEST_LOCALES_SOURCE_MAP = new Map([ - ['1', 'file1'], - ['2', 'file2'], - ['3', 'file3'], - ]); - let instance; - - beforeEach(() => { - instance = new AddLocalesCommand(optionModel); - }); - - afterEach(() => { - sinon.restore(); - }); - - it('| profile fails to get the runtime profile, expect error message error out', (done) => { - // setup - const TEST_CMD = { - debug: TEST_DEBUG - }; - sinon.stub(profileHelper, 'runtimeProfile').throws(TEST_ERROR); - // call - instance.handle(TEST_CMD, (err) => { - // verify - expect(err.name).equal(TEST_ERROR); - expect(errorStub.args[0][0].name).equal(TEST_ERROR); - expect(infoStub.callCount).equal(0); - expect(warnStub.callCount).equal(0); - done(); - }); - }); - - it('| helper fails to initiate proj models, expect error message error out', (done) => { - // setup - const TEST_CMD = { - debug: TEST_DEBUG - }; - sinon.stub(profileHelper, 'runtimeProfile').returns(TEST_PROFILE); - sinon.stub(helper, 'initiateModels').throws(TEST_ERROR); - // call - instance.handle(TEST_CMD, (err) => { - // verify - expect(err.name).equal(TEST_ERROR); - expect(errorStub.args[0][0].name).equal(TEST_ERROR); - expect(infoStub.callCount).equal(0); - expect(warnStub.callCount).equal(0); - done(); - }); - }); - - it('| select locales fails with error, expect error message error out', (done) => { - // setup - const TEST_CMD = { - debug: TEST_DEBUG - }; - sinon.stub(profileHelper, 'runtimeProfile').returns(TEST_PROFILE); - sinon.stub(helper, 'initiateModels').returns(null); - sinon.stub(ui, 'selectLocales').callsArgWith(1, TEST_ERROR); - // call - instance.handle(TEST_CMD, (err) => { - // verify - expect(err).equal(TEST_ERROR); - expect(errorStub.args[0][0]).equal(TEST_ERROR); - expect(infoStub.callCount).equal(0); - expect(warnStub.callCount).equal(0); - done(); - }); - }); - - it('| add locales fails with error, expect error message error out', (done) => { - // setup - const TEST_CMD = { - debug: TEST_DEBUG - }; - sinon.stub(profileHelper, 'runtimeProfile').returns(TEST_PROFILE); - sinon.stub(helper, 'initiateModels').returns(null); - sinon.stub(ui, 'selectLocales').callsArgWith(1, undefined, TEST_LOCALES_LIST); - sinon.stub(helper, 'addLocales').callsArgWith(3, TEST_ERROR); - // call - instance.handle(TEST_CMD, (err) => { - // verify - expect(err).equal(TEST_ERROR); - expect(errorStub.args[0][0]).equal(TEST_ERROR); - expect(infoStub.callCount).equal(0); - expect(warnStub.callCount).equal(0); - done(); - }); - }); - - it('| cmd executes without error, expect callback without error', (done) => { - // setup - const TEST_CMD = { - debug: TEST_DEBUG - }; - sinon.stub(profileHelper, 'runtimeProfile').returns(TEST_PROFILE); - sinon.stub(helper, 'initiateModels').returns(null); - sinon.stub(ui, 'selectLocales').callsArgWith(1, undefined, TEST_LOCALES_LIST); - sinon.stub(helper, 'addLocales').callsArgWith(3, undefined, TEST_LOCALES_SOURCE_MAP); - sinon.stub(ui, 'displayAddLocalesResult').returns(null); - // call - instance.handle(TEST_CMD, (err) => { - // verify - expect(err).equal(undefined); - expect(errorStub.callCount).equal(0); - expect(infoStub.callCount).equal(0); - expect(warnStub.callCount).equal(0); - done(); - }); - }); - }); -}); diff --git a/test/unit/commands/skill/add-locales/index-test.ts b/test/unit/commands/skill/add-locales/index-test.ts new file mode 100644 index 00000000..ea1457f5 --- /dev/null +++ b/test/unit/commands/skill/add-locales/index-test.ts @@ -0,0 +1,140 @@ +import {expect} from "chai"; +import sinon from "sinon"; +import AddLocalesCommand from "../../../../../lib/commands/skill/add-locales"; +import helper from "../../../../../lib/commands/skill/add-locales/helper"; +import optionModel from "../../../../../lib/commands/option-model.json"; +import ui from "../../../../../lib/commands/skill/add-locales/ui"; +import profileHelper from "../../../../../lib/utils/profile-helper"; +import Messenger from "../../../../../lib/view/messenger"; +import {OptionModel} from "../../../../../lib/commands/option-validator"; + +describe("Commands add-locales test - command class test", () => { + const TEST_DEBUG = false; + + let infoStub: sinon.SinonStub; + let errorStub: sinon.SinonStub; + let warnStub: sinon.SinonStub; + + beforeEach(() => { + infoStub = sinon.stub(); + errorStub = sinon.stub(); + warnStub = sinon.stub(); + sinon.stub(Messenger, "getInstance").returns({ + info: infoStub, + error: errorStub, + warn: warnStub, + }); + }); + + afterEach(() => { + sinon.restore(); + }); + + it("| validate command information is set correctly", () => { + const instance = new AddLocalesCommand(optionModel as OptionModel); + expect(instance.name()).equal("add-locales"); + expect(instance.description()).equal("add new locale(s) from existing locale or from the template"); + expect(instance.requiredOptions()).deep.equal([]); + expect(instance.optionalOptions()).deep.equal(["profile", "debug"]); + }); + + describe("validate command handle", () => { + const TEST_ERROR = Error("command error"); + const TEST_PROFILE = "profile"; + const TEST_LOCALES_LIST = ["1", "2", "3"]; + const TEST_LOCALES_SOURCE_MAP = new Map([ + ["1", "file1"], + ["2", "file2"], + ["3", "file3"], + ]); + let instance: AddLocalesCommand; + + beforeEach(() => { + instance = new AddLocalesCommand(optionModel as OptionModel); + }); + + afterEach(() => { + sinon.restore(); + }); + + it("| profile fails to get the runtime profile, expect error message error out", async () => { + // setup + const TEST_CMD = { + debug: TEST_DEBUG, + }; + sinon.stub(profileHelper, "runtimeProfile").throws(TEST_ERROR); + // call + await expect(instance.handle(TEST_CMD)).rejectedWith(TEST_ERROR); + // verify + expect(errorStub).calledWith(TEST_ERROR); + expect(infoStub).not.called; + expect(warnStub).not.called; + }); + + it("| helper fails to initiate proj models, expect error message error out", async () => { + // setup + const TEST_CMD = { + debug: TEST_DEBUG, + }; + sinon.stub(profileHelper, "runtimeProfile").returns(TEST_PROFILE); + sinon.stub(helper, "initiateModels").throws(TEST_ERROR); + // call + await expect(instance.handle(TEST_CMD)).rejectedWith(TEST_ERROR); + // verify + expect(errorStub).calledWith(TEST_ERROR); + expect(infoStub).not.called; + expect(warnStub).not.called; + }); + + it("| select locales fails with error, expect error message error out", async () => { + // setup + const TEST_CMD = { + debug: TEST_DEBUG, + }; + sinon.stub(profileHelper, "runtimeProfile").returns(TEST_PROFILE); + sinon.stub(helper, "initiateModels").returns(null as any); + sinon.stub(ui, "selectLocales").callsArgWith(1, TEST_ERROR); + // call + await expect(instance.handle(TEST_CMD)).rejectedWith(TEST_ERROR); + // verify + expect(errorStub).calledWith(TEST_ERROR); + expect(infoStub).not.called; + expect(warnStub).not.called; + }); + + it("| add locales fails with error, expect error message error out", async () => { + // setup + const TEST_CMD = { + debug: TEST_DEBUG, + }; + sinon.stub(profileHelper, "runtimeProfile").returns(TEST_PROFILE); + sinon.stub(helper, "initiateModels").returns(null as any); + sinon.stub(ui, "selectLocales").callsArgWith(1, undefined, TEST_LOCALES_LIST); + sinon.stub(helper, "addLocales").callsArgWith(3, TEST_ERROR); + // call + await expect(instance.handle(TEST_CMD)).rejectedWith(TEST_ERROR); + // verify + expect(errorStub).calledWith(TEST_ERROR); + expect(infoStub).not.called; + expect(warnStub).not.called; + }); + + it("| cmd executes without error, expect callback without error", async () => { + // setup + const TEST_CMD = { + debug: TEST_DEBUG, + }; + sinon.stub(profileHelper, "runtimeProfile").returns(TEST_PROFILE); + sinon.stub(helper, "initiateModels").returns(null as any); + sinon.stub(ui, "selectLocales").callsArgWith(1, undefined, TEST_LOCALES_LIST); + sinon.stub(helper, "addLocales").callsArgWith(3, undefined, TEST_LOCALES_SOURCE_MAP); + sinon.stub(ui, "displayAddLocalesResult").returns(null as any); + // call + await expect(instance.handle(TEST_CMD)).not.rejected; + // verify + expect(errorStub).not.called; + expect(infoStub).not.called; + expect(warnStub).not.called; + }); + }); +}); diff --git a/test/unit/commands/skill/add-locales/ui-test.js b/test/unit/commands/skill/add-locales/ui-test.js index b245fd30..fb444b1c 100644 --- a/test/unit/commands/skill/add-locales/ui-test.js +++ b/test/unit/commands/skill/add-locales/ui-test.js @@ -1,107 +1,131 @@ -const { expect } = require('chai'); -const inquirer = require('inquirer'); -const sinon = require('sinon'); +const {expect} = require("chai"); +const inquirer = require("inquirer"); +const sinon = require("sinon"); -const Messenger = require('@src/view/messenger'); - -const ui = require('@src/commands/skill/add-locales/ui'); +const Messenger = require("../../../../../lib/view/messenger"); +const acUtils = require("../../../../../lib/utils/ac-util"); +const ui = require("../../../../../lib/commands/skill/add-locales/ui"); function validateInquirerConfig(stub, expectedConfig) { - const { message, type, choices } = expectedConfig; - expect(stub.message).equal(message); - expect(stub.type).equal(type); - if (choices) { - expect(stub.choices).deep.equal(choices); - } + const {message, type, choices} = expectedConfig; + expect(stub.message).equal(message); + expect(stub.type).equal(type); + if (choices) { + expect(stub.choices).deep.equal(choices); + } } -describe('Commands add-locales - UI test', () => { - describe('# validate method selectLocales', () => { - const TEST_LOCALES = ['1', '2', '3']; - const TEST_SELECTED_LOCALES = ['1']; - const TEST_ERROR = 'error'; +describe("Commands add-locales - UI test", () => { + describe("# validate method selectLocales", () => { + const TEST_LOCALES = ["1", "2", "3"]; + const TEST_SELECTED_LOCALES = ["1"]; + const TEST_ERROR = "error"; - beforeEach(() => { - sinon.stub(inquirer, 'prompt'); - }); + beforeEach(() => { + sinon.stub(inquirer, "prompt"); + }); - afterEach(() => { - sinon.restore(); - }); + afterEach(() => { + sinon.restore(); + }); - it('| select locales with error throw, expect error called back', (done) => { - // setup - inquirer.prompt.rejects(TEST_ERROR); - // call - ui.selectLocales(TEST_LOCALES, (err, results) => { - // verify - validateInquirerConfig(inquirer.prompt.args[0][0][0], { - message: 'Please select at least one locale to add:', - type: 'checkbox', - choices: TEST_LOCALES - }); - expect(results).equal(undefined); - expect(err.name).equal(TEST_ERROR); - done(); - }); + it("| select locales with error throw, expect error called back", (done) => { + // setup + inquirer.prompt.rejects(TEST_ERROR); + // call + ui.selectLocales(TEST_LOCALES, (err, results) => { + // verify + validateInquirerConfig(inquirer.prompt.args[0][0][0], { + message: "Please select at least one locale to add:", + type: "checkbox", + choices: TEST_LOCALES, }); + expect(results).equal(undefined); + expect(err.name).equal(TEST_ERROR); + done(); + }); + }); - it('| select locales successfully, expect result list called back', (done) => { - // setup - inquirer.prompt.resolves({ localeList: TEST_SELECTED_LOCALES }); - // call - ui.selectLocales(TEST_LOCALES, (err, results) => { - // verify - expect(err).equal(null); - expect(results).deep.equal(TEST_SELECTED_LOCALES); - done(); - }); - }); + it("| select locales successfully, expect result list called back", (done) => { + // setup + inquirer.prompt.resolves({localeList: TEST_SELECTED_LOCALES}); + // call + ui.selectLocales(TEST_LOCALES, (err, results) => { + // verify + expect(err).equal(null); + expect(results).deep.equal(TEST_SELECTED_LOCALES); + done(); + }); }); + }); - describe('# validate method displayAddLocalesResult', () => { - new Messenger({}); - let infoStub; + describe("# validate method displayAddLocalesResult", () => { + new Messenger({}); + let infoStub; + const TEST_PROFILE = "profile1"; + let isACSkillStub; - beforeEach(() => { - infoStub = sinon.stub(); - sinon.stub(Messenger, 'getInstance').returns({ - info: infoStub - }); - }); + beforeEach(() => { + infoStub = sinon.stub(); + sinon.stub(Messenger, "getInstance").returns({ + info: infoStub, + }); + isACSkillStub = sinon.stub(acUtils, "isAcSkill"); + isACSkillStub.returns(false); + }); - afterEach(() => { - sinon.restore(); - }); + afterEach(() => { + sinon.restore(); + }); - it('| display info message when all locales exist', () => { - // setup - const TEST_MAP = new Map(); - const TEST_LIST = ['1', '2', '3']; - // call - ui.displayAddLocalesResult(TEST_LIST, TEST_MAP); - // verify - expect(infoStub.args[0][0]).equal('Locale 1.json already exists'); - expect(infoStub.args[1][0]).equal('Locale 2.json already exists'); - expect(infoStub.args[2][0]).equal('Locale 3.json already exists'); - }); + it("| display info message when all locales exist", () => { + // setup + const TEST_MAP = new Map(); + const TEST_LIST = ["1", "2", "3"]; + // call + ui.displayAddLocalesResult(TEST_LIST, TEST_MAP, TEST_PROFILE); + // verify + expect(infoStub.args[0][0]).equal("Locale 1.json already exists"); + expect(infoStub.args[1][0]).equal("Locale 2.json already exists"); + expect(infoStub.args[2][0]).equal("Locale 3.json already exists"); + }); - it('| display info message when all selected locales are added', () => { - // setup - const TEST_MAP = new Map([ - ['1', { uri: 'file1.json', canCopy: true }], - ['2', { uri: 'file2.json', canCopy: false }] - ]); - const TEST_LIST = ['1', '2', '3']; - // call - ui.displayAddLocalesResult(TEST_LIST, TEST_MAP); - // verify - expect(infoStub.args[0][0]).equal('Locale 3.json already exists'); - expect(infoStub.args[1][0]).equal(''); - expect(infoStub.args[2][0]).equal('The following skill locale(s) have been added according to your local project:'); - expect(infoStub.args[3][0]).equal(' Added locale 1.json from file1\'s interactionModel'); - expect(infoStub.args[4][0]).equal(' Added locale 2.json from the template of interactionModel'); - expect(infoStub.args[5][0]).equal('Please check the added files above, and run "ask deploy" to deploy the changes.'); - }); + it("| display info message when all selected locales are added for IM skill", () => { + // setup + const TEST_MAP = new Map([ + ["1", {uri: "file1.json", canCopy: true}], + ["2", {uri: "file2.json", canCopy: false}], + ]); + const TEST_LIST = ["1", "2", "3"]; + // call + ui.displayAddLocalesResult(TEST_LIST, TEST_MAP, TEST_PROFILE); + // verify + expect(infoStub.args[0][0]).equal("Locale 3.json already exists"); + expect(infoStub.args[1][0]).equal(""); + expect(infoStub.args[2][0]).equal("The following skill locale(s) have been added according to your local project:"); + expect(infoStub.args[3][0]).equal(" Added locale 1.json from file1's interactionModel"); + expect(infoStub.args[4][0]).equal(" Added locale 2.json from the template of interactionModel"); + expect(infoStub.args[5][0]).equal('Please check the added files above, and run "ask deploy" to deploy the changes.'); + }); + + + it("| display info message when all selected locales are added for AC skill", () => { + // setup + const TEST_MAP = new Map([ + ["1", {uri: "file1.json", canCopy: true}], + ["2", {uri: "file2.json", canCopy: false}], + ]); + const TEST_LIST = ["1", "2", "3"]; + isACSkillStub.returns(false); + // call + ui.displayAddLocalesResult(TEST_LIST, TEST_MAP, TEST_PROFILE); + // verify + expect(infoStub.args[0][0]).equal("Locale 3.json already exists"); + expect(infoStub.args[1][0]).equal(""); + expect(infoStub.args[2][0]).equal("The following skill locale(s) have been added according to your local project:"); + expect(infoStub.args[3][0]).equal(" Added locale 1.json from file1's interactionModel"); + expect(infoStub.args[4][0]).equal(" Added locale 2.json from the template of interactionModel"); + expect(infoStub.args[5][0]).equal('Please check the added files above, and run "ask deploy" to deploy the changes.'); }); + }); }); diff --git a/test/unit/commands/skill/skill-commander-test.ts b/test/unit/commands/skill/skill-commander-test.ts new file mode 100644 index 00000000..0c8d74e4 --- /dev/null +++ b/test/unit/commands/skill/skill-commander-test.ts @@ -0,0 +1,36 @@ +import {commander} from "../../../../lib/commands/skill/skill-commander"; +import AddlocalesCommand from "../../../../lib/commands/skill/add-locales"; +import sinon from "sinon"; +import Messenger from "../../../../lib/view/messenger"; +import httpClient from "../../../../lib/clients/http-client"; + +/** + * Simple test which loads the skill commander while running tests. + * This was previously not done and could fail due to changes. + */ +describe("Skill Commander Test", () => { + let errorStub, warnStub, infoStub; + + beforeEach(() => { + errorStub = sinon.stub(); + warnStub = sinon.stub(); + infoStub = sinon.stub(); + sinon.stub(Messenger, "getInstance").returns({ + info: infoStub, + warn: warnStub, + error: errorStub, + dispose: sinon.stub(), + }); + sinon.stub(process, "exit"); + sinon.stub(httpClient, "request").yields({statusCode: 200}); + }); + + it("loads and runs a command", async () => { + sinon.stub(AddlocalesCommand.prototype, "handle").resolves(); + await commander.parseAsync(["something", "something", "add-locales"]); + }); + + afterEach(() => { + sinon.restore(); + }); +}); diff --git a/test/unit/commands/smapi/appended-commands/export-package/helper-test.js b/test/unit/commands/smapi/appended-commands/export-package/helper-test.js index 56c97a3a..63d2aab6 100644 --- a/test/unit/commands/smapi/appended-commands/export-package/helper-test.js +++ b/test/unit/commands/smapi/appended-commands/export-package/helper-test.js @@ -1,75 +1,75 @@ -const { expect } = require('chai'); -const sinon = require('sinon'); +const {expect} = require("chai"); +const sinon = require("sinon"); -const AuthorizationController = require('@src/controllers/authorization-controller'); -const helper = require('@src/commands/smapi/appended-commands/export-package/helper'); -const httpClient = require('@src/clients/http-client'); -const jsonView = require('@src/view/json-view'); -const SmapiClient = require('@src/clients/smapi-client/index.js'); +const AuthorizationController = require("../../../../../../lib/controllers/authorization-controller"); +const helper = require("../../../../../../lib/commands/smapi/appended-commands/export-package/helper"); +const httpClient = require("../../../../../../lib/clients/http-client"); +const jsonView = require("../../../../../../lib/view/json-view"); +const SmapiClient = require("../../../../../../lib/clients/smapi-client").default; -describe('Commands export-package - helper test', () => { - const TEST_EXPORT_ID = 'EXPORT_ID'; - const TEST_STATUS_CODE = 200; - const TEST_ERROR_MESSAGE = 'ERROR_MESSAGE'; - const ERROR = new Error(TEST_ERROR_MESSAGE); +describe("Commands export-package - helper test", () => { + const TEST_EXPORT_ID = "EXPORT_ID"; + const TEST_STATUS_CODE = 200; + const TEST_ERROR_MESSAGE = "ERROR_MESSAGE"; + const ERROR = new Error(TEST_ERROR_MESSAGE); - describe('# pollExportStatus check', () => { - const smapiClient = new SmapiClient({ - profile: 'TEST_PROFILE', - doDebug: 'TEST_DEBUG' - }); - const GET_STATUS_ERROR = { - statusCode: 403, - body: { - error: TEST_ERROR_MESSAGE - } - }; - const GET_STATUS_RESPONSE = { - statusCode: 200, - headers: {}, - body: {} - }; - beforeEach(() => { - sinon.stub(AuthorizationController.prototype, 'tokenRefreshAndRead').callsArgWith(1); - }); - afterEach(() => { - sinon.restore(); - }); + describe("# pollExportStatus check", () => { + const smapiClient = new SmapiClient({ + profile: "TEST_PROFILE", + doDebug: "TEST_DEBUG", + }); + const GET_STATUS_ERROR = { + statusCode: 403, + body: { + error: TEST_ERROR_MESSAGE, + }, + }; + const GET_STATUS_RESPONSE = { + statusCode: 200, + headers: {}, + body: {}, + }; + beforeEach(() => { + sinon.stub(AuthorizationController.prototype, "tokenRefreshAndRead").callsArgWith(1); + }); + afterEach(() => { + sinon.restore(); + }); - it('| pollExportStatus fails, expect throw error', (done) => { - // setup - sinon.stub(httpClient, 'request').callsArgWith(3, ERROR); // stub smapi request - // call - helper.pollExportStatus(smapiClient, TEST_EXPORT_ID, (err, response) => { - // verify - expect(err.message).equal(TEST_ERROR_MESSAGE); - expect(response).equal(null); - done(); - }); - }); + it("| pollExportStatus fails, expect throw error", (done) => { + // setup + sinon.stub(httpClient, "request").callsArgWith(3, ERROR); // stub smapi request + // call + helper.pollExportStatus(smapiClient, TEST_EXPORT_ID, (err, response) => { + // verify + expect(err.message).equal(TEST_ERROR_MESSAGE); + expect(response).equal(null); + done(); + }); + }); - it('| pollExportStatus with status code >= 300, expect throw error', (done) => { - // setup - sinon.stub(httpClient, 'request').callsArgWith(3, null, GET_STATUS_ERROR); // stub smapi request - // call - helper.pollExportStatus(smapiClient, TEST_EXPORT_ID, (err, response) => { - // verify - expect(err).equal(jsonView.toString({ error: TEST_ERROR_MESSAGE })); - expect(response).equal(null); - done(); - }); - }); + it("| pollExportStatus with status code >= 300, expect throw error", (done) => { + // setup + sinon.stub(httpClient, "request").callsArgWith(3, null, GET_STATUS_ERROR); // stub smapi request + // call + helper.pollExportStatus(smapiClient, TEST_EXPORT_ID, (err, response) => { + // verify + expect(err).equal(jsonView.toString({error: TEST_ERROR_MESSAGE})); + expect(response).equal(null); + done(); + }); + }); - it('| pollExportStatus passes', (done) => { - // setup - sinon.stub(httpClient, 'request').callsArgWith(3, null, GET_STATUS_RESPONSE); // stub smapi request - // call - helper.pollExportStatus(smapiClient, TEST_EXPORT_ID, (err, response) => { - // verify - expect(err).equal(null); - expect(response.statusCode).equal(TEST_STATUS_CODE); - done(); - }); - }); + it("| pollExportStatus passes", (done) => { + // setup + sinon.stub(httpClient, "request").callsArgWith(3, null, GET_STATUS_RESPONSE); // stub smapi request + // call + helper.pollExportStatus(smapiClient, TEST_EXPORT_ID, (err, response) => { + // verify + expect(err).equal(null); + expect(response.statusCode).equal(TEST_STATUS_CODE); + done(); + }); }); + }); }); diff --git a/test/unit/commands/smapi/appended-commands/export-package/index-test.js b/test/unit/commands/smapi/appended-commands/export-package/index-test.js deleted file mode 100644 index 608319d3..00000000 --- a/test/unit/commands/smapi/appended-commands/export-package/index-test.js +++ /dev/null @@ -1,203 +0,0 @@ -const { expect } = require('chai'); -const fs = require('fs'); -const sinon = require('sinon'); - -const AuthorizationController = require('@src/controllers/authorization-controller'); -const CONSTANTS = require('@src/utils/constants'); -const ExportPackageCommand = require('@src/commands/smapi/appended-commands/export-package'); -const helper = require('@src/commands/smapi/appended-commands/export-package/helper'); -const httpClient = require('@src/clients/http-client'); -const jsonView = require('@src/view/json-view'); -const Messenger = require('@src/view/messenger'); -const optionModel = require('@src/commands/option-model'); -const profileHelper = require('@src/utils/profile-helper'); -const zipUtils = require('@src/utils/zip-utils'); - -describe('Commands export-package test - command class test', () => { - const TEST_PROFILE = 'default'; - const TEST_DEBUG = false; - - let infoStub; - let errorStub; - let warnStub; - - beforeEach(() => { - infoStub = sinon.stub(); - errorStub = sinon.stub(); - warnStub = sinon.stub(); - sinon.stub(Messenger, 'getInstance').returns({ - info: infoStub, - error: errorStub, - warn: warnStub - }); - }); - - afterEach(() => { - sinon.restore(); - }); - - it('| validate command information is set correctly', () => { - const instance = new ExportPackageCommand(optionModel); - expect(instance.name()).equal('export-package'); - expect(instance.description()).equal('download the skill package to "skill-package" folder in current directory'); - expect(instance.requiredOptions()).deep.equal(['skill-id', 'stage']); - expect(instance.optionalOptions()).deep.equal(['profile', 'debug']); - }); - - describe('validate command handle', () => { - const TEST_CMD = { - profile: TEST_PROFILE, - debug: TEST_DEBUG - }; - const TEST_ERROR_MESSAGE = 'ERROR'; - const ERROR = new Error(TEST_ERROR_MESSAGE); - let instance; - beforeEach(() => { - sinon.stub(profileHelper, 'runtimeProfile').returns(TEST_PROFILE); - instance = new ExportPackageCommand(optionModel); - }); - - afterEach(() => { - sinon.restore(); - }); - - describe('command handle - before export package', () => { - it('| when profile is not correct, expect throw error', (done) => { - // setup - profileHelper.runtimeProfile.throws(new Error('error')); - // call - instance.handle(TEST_CMD, (err) => { - // verify - expect(err.message).equal('error'); - expect(infoStub.callCount).equal(0); - expect(warnStub.callCount).equal(0); - done(); - }); - }); - - it('| when skillPackage folder exists, expect throw error', (done) => { - // setup - sinon.stub(fs, 'existsSync').returns(true); - // call - instance.handle(TEST_CMD, (err) => { - // verify - expect(err.message).equal(`A ${CONSTANTS.FILE_PATH.SKILL_PACKAGE.PACKAGE} fold already exists in the current working directory.`); - expect(errorStub.args[0][0].message).equal(`A ${CONSTANTS.FILE_PATH.SKILL_PACKAGE.PACKAGE} ` - + 'fold already exists in the current working directory.'); - expect(infoStub.callCount).equal(0); - expect(warnStub.callCount).equal(0); - done(); - }); - }); - }); - - describe('command handle - request to export skill package', () => { - const EXPORT_ERROR = { - statusCode: 403, - body: { - error: TEST_ERROR_MESSAGE - } - }; - beforeEach(() => { - sinon.stub(AuthorizationController.prototype, 'tokenRefreshAndRead').callsArgWith(1); - }); - - it('| export skill package fails, expect throw error', (done) => { - // setup - sinon.stub(fs, 'existsSync').returns(false); - sinon.stub(httpClient, 'request').callsArgWith(3, ERROR); // stub smapi request - // call - instance.handle(TEST_CMD, (err) => { - // verify - expect(err.message).equal(TEST_ERROR_MESSAGE); - expect(infoStub.callCount).equal(0); - expect(warnStub.callCount).equal(0); - done(); - }); - }); - - it('| export skill package response with status code >= 300, expect throw error', (done) => { - // setup - sinon.stub(fs, 'existsSync').returns(false); - sinon.stub(httpClient, 'request').callsArgWith(3, null, EXPORT_ERROR); // stub smapi request - // call - instance.handle(TEST_CMD, (err) => { - // verify - expect(err).equal(jsonView.toString({ error: TEST_ERROR_MESSAGE })); - expect(infoStub.callCount).equal(0); - expect(warnStub.callCount).equal(0); - done(); - }); - }); - }); - - describe('command handle - poll export skill package status and download file', () => { - const EXPORT_RESPONSE = { - statusCode: 200, - headers: { - location: 'TEST_LOCATION' - }, - body: {} - }; - const POLL_RESPONSE = { - statusCode: 200, - headers: {}, - body: { - skill: { - location: 'TEST_LOCATION' - } - } - }; - beforeEach(() => { - sinon.stub(AuthorizationController.prototype, 'tokenRefreshAndRead').callsArgWith(1); - }); - - it('| poll skill package fails, expect throw error', (done) => { - // setup - sinon.stub(fs, 'existsSync').returns(false); - sinon.stub(httpClient, 'request').callsArgWith(3, null, EXPORT_RESPONSE); // stub smapi request - sinon.stub(helper, 'pollExportStatus').callsArgWith(2, ERROR); - // call - instance.handle(TEST_CMD, (err) => { - // verify - expect(err.message).equal(TEST_ERROR_MESSAGE); - expect(infoStub.callCount).equal(0); - expect(warnStub.callCount).equal(0); - done(); - }); - }); - - it('| unzipRemoteZipFile fails, expect throw error', (done) => { - // setup - sinon.stub(fs, 'existsSync').returns(false); - sinon.stub(httpClient, 'request').callsArgWith(3, null, EXPORT_RESPONSE); // stub smapi request - sinon.stub(helper, 'pollExportStatus').callsArgWith(2, null, POLL_RESPONSE); - sinon.stub(zipUtils, 'unzipRemoteZipFile').callsArgWith(3, ERROR); - // call - instance.handle(TEST_CMD, (err) => { - // verify - expect(err.message).equal(TEST_ERROR_MESSAGE); - expect(infoStub.callCount).equal(0); - expect(warnStub.callCount).equal(0); - done(); - }); - }); - - it('| unzipRemoteZipFile passes', (done) => { - // setup - sinon.stub(fs, 'existsSync').returns(false); - sinon.stub(httpClient, 'request').callsArgWith(3, null, EXPORT_RESPONSE); // stub smapi request - sinon.stub(helper, 'pollExportStatus').callsArgWith(2, null, POLL_RESPONSE); - sinon.stub(zipUtils, 'unzipRemoteZipFile').callsArgWith(3, null); - // call - instance.handle(TEST_CMD, (err) => { - // verify - expect(err).equal(undefined); - expect(infoStub.callCount).equal(1); - expect(warnStub.callCount).equal(0); - done(); - }); - }); - }); - }); -}); diff --git a/test/unit/commands/smapi/appended-commands/export-package/index-test.ts b/test/unit/commands/smapi/appended-commands/export-package/index-test.ts new file mode 100644 index 00000000..8bf2e3cf --- /dev/null +++ b/test/unit/commands/smapi/appended-commands/export-package/index-test.ts @@ -0,0 +1,195 @@ +import {expect} from "chai"; +import fs from "fs"; +import sinon from "sinon"; +import AuthorizationController from "../../../../../../lib/controllers/authorization-controller"; +import CONSTANTS from "../../../../../../lib/utils/constants"; +import ExportPackageCommand from "../../../../../../lib/commands/smapi/appended-commands/export-package"; +import helper from "../../../../../../lib/commands/smapi/appended-commands/export-package/helper"; +import httpClient from "../../../../../../lib/clients/http-client"; +import jsonView from "../../../../../../lib/view/json-view"; +import Messenger from "../../../../../../lib/view/messenger"; +import optionModel from "../../../../../../lib/commands/option-model.json"; +import profileHelper from "../../../../../../lib/utils/profile-helper"; +import zipUtils from "../../../../../../lib/utils/zip-utils"; +import {OptionModel} from "../../../../../../lib/commands/option-validator"; + +describe("Commands export-package test - command class test", () => { + const TEST_PROFILE = "default"; + const TEST_DEBUG = false; + + let infoStub: sinon.SinonStub; + let errorStub: sinon.SinonStub; + let warnStub: sinon.SinonStub; + + beforeEach(() => { + infoStub = sinon.stub(); + errorStub = sinon.stub(); + warnStub = sinon.stub(); + sinon.stub(Messenger, "getInstance").returns({ + info: infoStub, + error: errorStub, + warn: warnStub, + }); + }); + + afterEach(() => { + sinon.restore(); + }); + + it("| validate command information is set correctly", () => { + const instance = new ExportPackageCommand(optionModel as OptionModel); + expect(instance.name()).equal("export-package"); + expect(instance.description()).equal('download the skill package to "skill-package" folder in current directory'); + expect(instance.requiredOptions()).deep.equal(["skill-id", "stage"]); + expect(instance.optionalOptions()).deep.equal(["profile", "debug"]); + }); + + describe("validate command handle", () => { + const TEST_CMD = { + profile: TEST_PROFILE, + debug: TEST_DEBUG, + }; + const TEST_ERROR_MESSAGE = "ERROR"; + const ERROR = new Error(TEST_ERROR_MESSAGE); + let instance: ExportPackageCommand; + let profileHelperRuntimeProfileStub: sinon.SinonStub; + beforeEach(() => { + profileHelperRuntimeProfileStub = sinon.stub(profileHelper, "runtimeProfile").returns(TEST_PROFILE); + instance = new ExportPackageCommand(optionModel as OptionModel); + }); + + afterEach(() => { + sinon.restore(); + }); + + describe("command handle - before export package", () => { + it("| when profile is not correct, expect throw error", async () => { + // setup + profileHelperRuntimeProfileStub.throws(new Error("error")); + // call + await expect(instance.handle(TEST_CMD)).rejectedWith("error"); + + // verify + expect(infoStub).not.called; + expect(warnStub).not.called; + }); + + it("| when skillPackage folder exists, expect throw error", async () => { + // setup + sinon.stub(fs, "existsSync").returns(true); + // call + await expect(instance.handle(TEST_CMD)).rejectedWith( + `A ${CONSTANTS.FILE_PATH.SKILL_PACKAGE.PACKAGE} fold already exists in the current working directory.`, + ); + + // verify + expect(errorStub).calledOnceWith( + sinon.match({ + message: `A ${CONSTANTS.FILE_PATH.SKILL_PACKAGE.PACKAGE} ` + "fold already exists in the current working directory.", + }), + ); + expect(infoStub).not.called; + expect(warnStub).not.called; + }); + }); + + describe("command handle - request to export skill package", () => { + const EXPORT_ERROR = { + statusCode: 403, + body: { + error: TEST_ERROR_MESSAGE, + }, + }; + beforeEach(() => { + sinon.stub(AuthorizationController.prototype, "tokenRefreshAndRead").callsArgWith(1); + }); + + it("| export skill package fails, expect throw error", async () => { + // setup + sinon.stub(fs, "existsSync").returns(false); + sinon.stub(httpClient, "request").callsArgWith(3, ERROR); // stub smapi request + // call + await expect(instance.handle(TEST_CMD)).rejectedWith(TEST_ERROR_MESSAGE); + + // verify + expect(infoStub).not.called; + expect(warnStub).not.called; + }); + + it("| export skill package response with status code >= 300, expect throw error", async () => { + // setup + sinon.stub(fs, "existsSync").returns(false); + sinon.stub(httpClient, "request").callsArgWith(3, null, EXPORT_ERROR); // stub smapi request + // call + await expect(instance.handle(TEST_CMD)).rejectedWith(jsonView.toString({error: TEST_ERROR_MESSAGE})); + + // verify + expect(infoStub).not.called; + expect(warnStub).not.called; + }); + }); + + describe("command handle - poll export skill package status and download file", () => { + const EXPORT_RESPONSE = { + statusCode: 200, + headers: { + location: "TEST_LOCATION", + }, + body: {}, + }; + const POLL_RESPONSE = { + statusCode: 200, + headers: {}, + body: { + skill: { + location: "TEST_LOCATION", + }, + }, + }; + beforeEach(() => { + sinon.stub(AuthorizationController.prototype, "tokenRefreshAndRead").callsArgWith(1); + }); + + it("| poll skill package fails, expect throw error", async () => { + // setup + sinon.stub(fs, "existsSync").returns(false); + sinon.stub(httpClient, "request").callsArgWith(3, null, EXPORT_RESPONSE); // stub smapi request + sinon.stub(helper, "pollExportStatus").callsArgWith(2, ERROR); + // call + await expect(instance.handle(TEST_CMD)).rejectedWith(TEST_ERROR_MESSAGE); + + // verify + expect(infoStub).not.called; + expect(warnStub).not.called; + }); + + it("| unzipRemoteZipFile fails, expect throw error", async () => { + // setup + sinon.stub(fs, "existsSync").returns(false); + sinon.stub(httpClient, "request").callsArgWith(3, null, EXPORT_RESPONSE); // stub smapi request + sinon.stub(helper, "pollExportStatus").callsArgWith(2, null, POLL_RESPONSE); + sinon.stub(zipUtils, "unzipRemoteZipFile").callsArgWith(3, ERROR); + // call + await expect(instance.handle(TEST_CMD)).rejectedWith(TEST_ERROR_MESSAGE); + + // verify + expect(infoStub).not.called; + expect(warnStub).not.called; + }); + + it("| unzipRemoteZipFile passes", async () => { + // setup + sinon.stub(fs, "existsSync").returns(false); + sinon.stub(httpClient, "request").callsArgWith(3, null, EXPORT_RESPONSE); // stub smapi request + sinon.stub(helper, "pollExportStatus").callsArgWith(2, null, POLL_RESPONSE); + sinon.stub(zipUtils, "unzipRemoteZipFile").callsArgWith(3, null); + // call + await instance.handle(TEST_CMD); + + // verify + expect(infoStub).calledOnce; + expect(warnStub).not.called; + }); + }); + }); +}); diff --git a/test/unit/commands/smapi/appended-commands/get-task/index-test.js b/test/unit/commands/smapi/appended-commands/get-task/index-test.js deleted file mode 100644 index 800ff769..00000000 --- a/test/unit/commands/smapi/appended-commands/get-task/index-test.js +++ /dev/null @@ -1,76 +0,0 @@ -const { expect } = require('chai'); -const sinon = require('sinon'); - -const AuthorizationController = require('@src/controllers/authorization-controller'); -const GetTaskCommand = require('@src/commands/smapi/appended-commands/get-task'); -const httpClient = require('@src/clients/http-client'); -const jsonView = require('@src/view/json-view'); -const Messenger = require('@src/view/messenger'); -const optionModel = require('@src/commands/option-model'); -const profileHelper = require('@src/utils/profile-helper'); - - -describe('Command get-task test ', () => { - let infoStub; - let errorStub; - let instance; - const cmdOptions = { - skillId: 'test', - taskName: 'test', - taskVersion: 'test' - }; - - beforeEach(() => { - infoStub = sinon.stub(); - errorStub = sinon.stub(); - sinon.stub(Messenger, 'getInstance').returns({ - info: infoStub, - error: errorStub, - }); - sinon.stub(AuthorizationController.prototype, 'tokenRefreshAndRead').callsArgWith(1); - sinon.stub(profileHelper, 'runtimeProfile').returns('test'); - instance = new GetTaskCommand(optionModel); - }); - - it('| should have options configured', () => { - expect(instance.name()).be.a('string'); - expect(instance.description()).be.a('string'); - expect(instance.requiredOptions()).be.a('array'); - expect(instance.optionalOptions()).be.a('array'); - }); - - it('| should display task definition', (done) => { - const definition = '{ "x":"y", "b": "z"}'; - const expectedOutput = jsonView.toString(JSON.parse(definition)); - sinon.stub(httpClient, 'request').yields(null, { body: { definition }, statusCode: 200 }); - - instance.handle(cmdOptions, () => { - expect(infoStub.calledOnceWith(expectedOutput)).eql(true); - done(); - }); - }); - - it('| should display error thrown by smapi client', (done) => { - const testError = 'testError'; - sinon.stub(httpClient, 'request').yields(new Error(testError)); - - instance.handle(cmdOptions, (err) => { - expect(err.message).eql(testError); - done(); - }); - }); - - it('| should display error thrown by smapi server', (done) => { - const body = { message: 'Bad request.' }; - sinon.stub(httpClient, 'request').yields(null, { body, statusCode: 400 }); - - instance.handle(cmdOptions, (err) => { - expect(err).includes('"message": "Bad request."'); - done(); - }); - }); - - afterEach(() => { - sinon.restore(); - }); -}); diff --git a/test/unit/commands/smapi/appended-commands/get-task/index-test.ts b/test/unit/commands/smapi/appended-commands/get-task/index-test.ts new file mode 100644 index 00000000..245fb370 --- /dev/null +++ b/test/unit/commands/smapi/appended-commands/get-task/index-test.ts @@ -0,0 +1,67 @@ +import {expect} from "chai"; +import sinon from "sinon"; +import AuthorizationController from "../../../../../../lib/controllers/authorization-controller"; +import GetTaskCommand from "../../../../../../lib/commands/smapi/appended-commands/get-task"; +import httpClient from "../../../../../../lib/clients/http-client"; +import jsonView from "../../../../../../lib/view/json-view"; +import Messenger from "../../../../../../lib/view/messenger"; +import optionModel from "../../../../../../lib/commands/option-model.json"; +import profileHelper from "../../../../../../lib/utils/profile-helper"; +import {OptionModel} from "../../../../../../lib/commands/option-validator"; + +describe("Command get-task test ", () => { + let infoStub: sinon.SinonStub; + let errorStub: sinon.SinonStub; + let instance: GetTaskCommand; + const cmdOptions = { + skillId: "test", + taskName: "test", + taskVersion: "test", + }; + + beforeEach(() => { + infoStub = sinon.stub(); + errorStub = sinon.stub(); + sinon.stub(Messenger, "getInstance").returns({ + info: infoStub, + error: errorStub, + }); + sinon.stub(AuthorizationController.prototype, "tokenRefreshAndRead").callsArgWith(1); + sinon.stub(profileHelper, "runtimeProfile").returns("test"); + instance = new GetTaskCommand(optionModel as OptionModel); + }); + + it("| should have options configured", () => { + expect(instance.name()).be.a("string"); + expect(instance.description()).be.a("string"); + expect(instance.requiredOptions()).be.a("array"); + expect(instance.optionalOptions()).be.a("array"); + }); + + it("| should display task definition", async () => { + const definition = '{ "x":"y", "b": "z"}'; + const expectedOutput = jsonView.toString(JSON.parse(definition)); + sinon.stub(httpClient, "request").yields(null, {body: {definition}, statusCode: 200}); + + await instance.handle(cmdOptions); + expect(infoStub).calledOnceWith(expectedOutput); + }); + + it("| should display error thrown by smapi client", async () => { + const testError = "testError"; + sinon.stub(httpClient, "request").yields(new Error(testError)); + + await expect(instance.handle(cmdOptions)).rejectedWith(testError); + }); + + it("| should display error thrown by smapi server", async () => { + const body = {message: "Bad request."}; + sinon.stub(httpClient, "request").yields(null, {body, statusCode: 400}); + + await expect(instance.handle(cmdOptions)).eventually.rejected.include('"message": "Bad request."'); + }); + + afterEach(() => { + sinon.restore(); + }); +}); diff --git a/test/unit/commands/smapi/appended-commands/search-task/index-test.js b/test/unit/commands/smapi/appended-commands/search-task/index-test.js deleted file mode 100644 index 255ea0d4..00000000 --- a/test/unit/commands/smapi/appended-commands/search-task/index-test.js +++ /dev/null @@ -1,93 +0,0 @@ -const { expect } = require('chai'); -const sinon = require('sinon'); - -const AuthorizationController = require('@src/controllers/authorization-controller'); -const SearchTaskCommand = require('@src/commands/smapi/appended-commands/search-task'); -const httpClient = require('@src/clients/http-client'); -const jsonView = require('@src/view/json-view'); -const Messenger = require('@src/view/messenger'); -const optionModel = require('@src/commands/option-model'); -const profileHelper = require('@src/utils/profile-helper'); - - -describe('Command search-task test ', () => { - let infoStub; - let errorStub; - let instance; - const cmdOptions = { - skillId: 'test', - providerSkillId: 'test', - maxResults: 'test', - nextToken: 'test' - }; - - beforeEach(() => { - infoStub = sinon.stub(); - errorStub = sinon.stub(); - sinon.stub(Messenger, 'getInstance').returns({ - info: infoStub, - error: errorStub, - }); - sinon.stub(AuthorizationController.prototype, 'tokenRefreshAndRead').callsArgWith(1); - sinon.stub(profileHelper, 'runtimeProfile').returns('test'); - instance = new SearchTaskCommand(optionModel); - }); - - it('| should have options configured', () => { - expect(instance.name()).be.a('string'); - expect(instance.description()).be.a('string'); - expect(instance.requiredOptions()).be.a('array'); - expect(instance.optionalOptions()).be.a('array'); - }); - - it('| should display task list', (done) => { - const body = { - taskSummaryList: [ - { - description: 'y', - name: 'x', - version: '1' - } - ], - totalCount: 1 - }; - const expectedOutput = jsonView.toString(body); - sinon.stub(httpClient, 'request').yields(null, { body, statusCode: 200 }); - - instance.handle(cmdOptions, () => { - expect(infoStub.calledOnceWith(expectedOutput)).eql(true); - done(); - }); - }); - - it('| should encode spaces', () => { - const input = 'Test, TestTwo, Three,Four'; - const expected = 'Test,%20TestTwo,%20Three,Four'; - const result = SearchTaskCommand.encodeSpaces(input); - expect(result).eql(expected); - }); - - it('| should display error thrown by smapi client', (done) => { - const testError = 'testError'; - sinon.stub(httpClient, 'request').yields(new Error(testError)); - - instance.handle(cmdOptions, (err) => { - expect(err.message).eql(testError); - done(); - }); - }); - - it('| should display error thrown by smapi server', (done) => { - const body = { message: 'Bad request.' }; - sinon.stub(httpClient, 'request').yields(null, { body, statusCode: 400 }); - - instance.handle(cmdOptions, (err) => { - expect(err).includes('"message": "Bad request."'); - done(); - }); - }); - - afterEach(() => { - sinon.restore(); - }); -}); diff --git a/test/unit/commands/smapi/appended-commands/search-task/index-test.ts b/test/unit/commands/smapi/appended-commands/search-task/index-test.ts new file mode 100644 index 00000000..0f34b875 --- /dev/null +++ b/test/unit/commands/smapi/appended-commands/search-task/index-test.ts @@ -0,0 +1,84 @@ +import {expect} from "chai"; +import sinon from "sinon"; +import AuthorizationController from "../../../../../../lib/controllers/authorization-controller"; +import SearchTaskCommand from "../../../../../../lib/commands/smapi/appended-commands/search-task"; +import httpClient from "../../../../../../lib/clients/http-client"; +import jsonView from "../../../../../../lib/view/json-view"; +import Messenger from "../../../../../../lib/view/messenger"; +import optionModel from "../../../../../../lib/commands/option-model.json"; +import profileHelper from "../../../../../../lib/utils/profile-helper"; +import {OptionModel} from "../../../../../../lib/commands/option-validator"; + +describe("Command search-task test ", () => { + let infoStub: sinon.SinonStub; + let errorStub: sinon.SinonStub; + let instance: SearchTaskCommand; + const cmdOptions = { + skillId: "test", + providerSkillId: "test", + maxResults: "test", + nextToken: "test", + }; + + beforeEach(() => { + infoStub = sinon.stub(); + errorStub = sinon.stub(); + sinon.stub(Messenger, "getInstance").returns({ + info: infoStub, + error: errorStub, + }); + sinon.stub(AuthorizationController.prototype, "tokenRefreshAndRead").callsArgWith(1); + sinon.stub(profileHelper, "runtimeProfile").returns("test"); + instance = new SearchTaskCommand(optionModel as OptionModel); + }); + + it("| should have options configured", () => { + expect(instance.name()).be.a("string"); + expect(instance.description()).be.a("string"); + expect(instance.requiredOptions()).be.a("array"); + expect(instance.optionalOptions()).be.a("array"); + }); + + it("| should display task list", async () => { + const body = { + taskSummaryList: [ + { + description: "y", + name: "x", + version: "1", + }, + ], + totalCount: 1, + }; + const expectedOutput = jsonView.toString(body); + sinon.stub(httpClient, "request").yields(null, {body, statusCode: 200}); + + await instance.handle(cmdOptions); + expect(infoStub).calledOnceWith(expectedOutput); + }); + + it("| should encode spaces", () => { + const input = "Test, TestTwo, Three,Four"; + const expected = "Test,%20TestTwo,%20Three,Four"; + const result = SearchTaskCommand.encodeSpaces(input); + expect(result).eql(expected); + }); + + it("| should display error thrown by smapi client", async () => { + const testError = "testError"; + sinon.stub(httpClient, "request").yields(new Error(testError)); + + await expect(instance.handle(cmdOptions)).rejectedWith(testError); + }); + + it("| should display error thrown by smapi server", async () => { + const body = {message: "Bad request."}; + sinon.stub(httpClient, "request").yields(null, {body, statusCode: 400}); + + await expect(instance.handle(cmdOptions)).eventually.rejected.include('"message": "Bad request."'); + }); + + afterEach(() => { + sinon.restore(); + }); +}); diff --git a/test/unit/commands/smapi/before-send-processor-test.js b/test/unit/commands/smapi/before-send-processor-test.js index 2efd9106..30504ed2 100644 --- a/test/unit/commands/smapi/before-send-processor-test.js +++ b/test/unit/commands/smapi/before-send-processor-test.js @@ -1,95 +1,94 @@ -const { expect } = require('chai'); -const sinon = require('sinon'); -const AppConfig = require('@src/model/app-config'); -const BeforeSendProcessor = require('@src/commands/smapi/before-send-processor'); - - -describe('Smapi test - BeforeSendProcessor class tests', () => { - const vendorId = 'some vendor id'; - const profile = 'test'; - const definitionRef = 'v1.someDefinition'; - const paramName = 'someParam'; - const commandName = 'some-command'; - beforeEach(() => { - sinon.stub(AppConfig, 'getInstance').returns({ - getVendorId() { - return vendorId; - } - }); - }); - it('| should add vendor id to body param', () => { - const paramObject = {}; - const params = [{ in: 'body', name: paramName, required: true, schema: { $ref: `#/definitions/${definitionRef}` } }]; - const modelInterceptor = { - operations: new Map([[commandName, { params }]]), - definitions: new Map([[definitionRef, { properties: { vendorId: {} } }]]) - }; - - const beforeSendProcessor = new BeforeSendProcessor(commandName, paramObject, modelInterceptor, profile); - beforeSendProcessor.processAll(); - - expect(paramObject[paramName].vendorId).eql(vendorId); - }); - - it('| should not add vendor id when no properties in reference object', () => { - const paramObject = {}; - const params = [{ in: 'body', name: paramName, required: true, schema: { $ref: `#/definitions/${definitionRef}` } }]; - const modelInterceptor = { - operations: new Map([[commandName, { params }]]), - definitions: new Map([[definitionRef, { }]]) - }; - - const beforeSendProcessor = new BeforeSendProcessor(commandName, paramObject, modelInterceptor, profile); - beforeSendProcessor.processAll(); - - expect(paramObject[paramName]).eql(undefined); - }); - - it('| should not add vendor id when no vendorId property in reference object', () => { - const paramObject = {}; - const params = [{ in: 'body', name: paramName, required: true, schema: { $ref: `#/definitions/${definitionRef}` } }]; - const modelInterceptor = { - operations: new Map([[commandName, { params }]]), - definitions: new Map([[definitionRef, { properties: { someProperty: {} } }]]) - }; - - const beforeSendProcessor = new BeforeSendProcessor(commandName, paramObject, modelInterceptor, profile); - beforeSendProcessor.processAll(); - - expect(paramObject[paramName]).eql(undefined); - }); - - it('| should add vendor id to non body param', () => { - const paramObject = {}; - const params = [{ in: 'path', name: 'vendorId' }]; - const modelInterceptor = { - operations: new Map([[commandName, { params }]]), - definitions: new Map([[definitionRef, { properties: { vendorId: {} } }]]) - }; - - const beforeSendProcessor = new BeforeSendProcessor(commandName, paramObject, modelInterceptor, profile); - beforeSendProcessor.processAll(); - - expect(paramObject.vendorId).eql(vendorId); - }); - - it('| should map testers emails', () => { - const paramObject = { testersEmails: ['tester1', 'tester2'] }; - const params = [{ in: 'body', name: 'TestersRequest' }]; - const modelInterceptor = { - operations: new Map([[commandName, { params }]]), - }; - - const beforeSendProcessor = new BeforeSendProcessor(commandName, paramObject, modelInterceptor, profile); - beforeSendProcessor.processAll(); - - const expected = { testers: [{ emailId: 'tester1' }, { emailId: 'tester2' }] }; - - expect(paramObject.testersRequest).eql(expected); - expect(paramObject.testersEmails).eql(undefined); - }); - - afterEach(() => { - sinon.restore(); +const {expect} = require("chai"); +const sinon = require("sinon"); +const AppConfig = require("../../../../lib/model/app-config"); +const BeforeSendProcessor = require("../../../../lib/commands/smapi/before-send-processor"); + +describe("Smapi test - BeforeSendProcessor class tests", () => { + const vendorId = "some vendor id"; + const profile = "test"; + const definitionRef = "v1.someDefinition"; + const paramName = "someParam"; + const commandName = "some-command"; + beforeEach(() => { + sinon.stub(AppConfig, "getInstance").returns({ + getVendorId() { + return vendorId; + }, }); + }); + it("| should add vendor id to body param", () => { + const paramObject = {}; + const params = [{in: "body", name: paramName, required: true, schema: {$ref: `#/definitions/${definitionRef}`}}]; + const modelInterceptor = { + operations: new Map([[commandName, {params}]]), + definitions: new Map([[definitionRef, {properties: {vendorId: {}}}]]), + }; + + const beforeSendProcessor = new BeforeSendProcessor(commandName, paramObject, modelInterceptor, profile); + beforeSendProcessor.processAll(); + + expect(paramObject[paramName].vendorId).eql(vendorId); + }); + + it("| should not add vendor id when no properties in reference object", () => { + const paramObject = {}; + const params = [{in: "body", name: paramName, required: true, schema: {$ref: `#/definitions/${definitionRef}`}}]; + const modelInterceptor = { + operations: new Map([[commandName, {params}]]), + definitions: new Map([[definitionRef, {}]]), + }; + + const beforeSendProcessor = new BeforeSendProcessor(commandName, paramObject, modelInterceptor, profile); + beforeSendProcessor.processAll(); + + expect(paramObject[paramName]).eql(undefined); + }); + + it("| should not add vendor id when no vendorId property in reference object", () => { + const paramObject = {}; + const params = [{in: "body", name: paramName, required: true, schema: {$ref: `#/definitions/${definitionRef}`}}]; + const modelInterceptor = { + operations: new Map([[commandName, {params}]]), + definitions: new Map([[definitionRef, {properties: {someProperty: {}}}]]), + }; + + const beforeSendProcessor = new BeforeSendProcessor(commandName, paramObject, modelInterceptor, profile); + beforeSendProcessor.processAll(); + + expect(paramObject[paramName]).eql(undefined); + }); + + it("| should add vendor id to non body param", () => { + const paramObject = {}; + const params = [{in: "path", name: "vendorId"}]; + const modelInterceptor = { + operations: new Map([[commandName, {params}]]), + definitions: new Map([[definitionRef, {properties: {vendorId: {}}}]]), + }; + + const beforeSendProcessor = new BeforeSendProcessor(commandName, paramObject, modelInterceptor, profile); + beforeSendProcessor.processAll(); + + expect(paramObject.vendorId).eql(vendorId); + }); + + it("| should map testers emails", () => { + const paramObject = {testersEmails: ["tester1", "tester2"]}; + const params = [{in: "body", name: "TestersRequest"}]; + const modelInterceptor = { + operations: new Map([[commandName, {params}]]), + }; + + const beforeSendProcessor = new BeforeSendProcessor(commandName, paramObject, modelInterceptor, profile); + beforeSendProcessor.processAll(); + + const expected = {testers: [{emailId: "tester1"}, {emailId: "tester2"}]}; + + expect(paramObject.testersRequest).eql(expected); + expect(paramObject.testersEmails).eql(undefined); + }); + + afterEach(() => { + sinon.restore(); + }); }); diff --git a/test/unit/commands/smapi/cli-customization-processor-test.js b/test/unit/commands/smapi/cli-customization-processor-test.js index 4c8f7071..50bff5fc 100644 --- a/test/unit/commands/smapi/cli-customization-processor-test.js +++ b/test/unit/commands/smapi/cli-customization-processor-test.js @@ -1,286 +1,301 @@ -const { expect } = require('chai'); -const sinon = require('sinon'); -const { camelCase, standardize } = require('@src/utils/string-utils'); -const CliError = require('@src/exceptions/cli-error'); -const { customizationMap } = require('@src/commands/smapi/customizations/parameters-map'); -const { CliCustomizationProcessor, BODY_PATH_DELIMITER, MAX_NESTED_PROPERTIES } = require('@src/commands/smapi/cli-customization-processor'); - +const {expect} = require("chai"); +const sinon = require("sinon"); +const {camelCase, standardize} = require("../../../../lib/utils/string-utils"); +const CliError = require("../../../../lib/exceptions/cli-error"); +const {customizationMap} = require("../../../../lib/commands/smapi/customizations/parameters-map"); +const { + CliCustomizationProcessor, + BODY_PATH_DELIMITER, + MAX_NESTED_PROPERTIES, +} = require("../../../../lib/commands/smapi/cli-customization-processor"); const makeParameter = (options = {}) => { - const defaultValues = { - name: 'someId', - in: 'path', - description: 'some description', - required: true, - type: 'string' - }; - - return { ...defaultValues, ...options }; + const defaultValues = { + name: "someId", + in: "path", + description: "some description", + required: true, + type: "string", + }; + + return {...defaultValues, ...options}; }; function mapExpectedParams(parentName, bodyPropertyName) { - const name = `${parentName} ${bodyPropertyName}`; - const bodyPath = `${parentName}${BODY_PATH_DELIMITER}${bodyPropertyName}`; - const key = camelCase(name); - return { name, bodyPath, key }; + const name = `${parentName} ${bodyPropertyName}`; + const bodyPath = `${parentName}${BODY_PATH_DELIMITER}${bodyPropertyName}`; + const key = camelCase(name); + return {name, bodyPath, key}; } -describe('Smapi test - CliCustomizationProcessor class', () => { - const enumValues = ['a', 'b']; - const refObjectDescription = 'description for type'; - const enumDescription = 'some enum description'; - const parentDescription = 'some parent description'; - const bodyPropertyOneName = 'propertyOne'; - const bodyPropertyTwoName = 'propertyTwo'; - const nestedPropertyName = 'nestedProperty'; - const nestedEnumPropertyName = 'nestedEnumProperty'; - const bodyProperty = { type: 'number' }; - const bodyPropertyWithSimpleArray = { type: 'array', items: { $ref: '#/definitions/SomeEnumType' } }; - const bodyPropertyWithComplexArray = { type: 'array', items: { $ref: '#/definitions/SomeSimpleObjectType' } }; - const bodyPropertyWithDescription = { description: 'property description', type: 'boolean' }; - const nestedProperty = { $ref: 'SomeObjectType' }; - const nestedEnumProperty = { $ref: 'SomeEnumTypeWithDescription' }; - let processor; - let parentOperation; - let definitions; - const objectWithTooManyProperties = {}; - for (let i = 0; i < MAX_NESTED_PROPERTIES; i++) { - objectWithTooManyProperties[i] = 'test'; - } - - - beforeEach(() => { - processor = new CliCustomizationProcessor(); - parentOperation = { customizationMetadata: { - flatParamsMap: new Map() - } }; - definitions = new Map([ - ['SomeEnumType', { enum: enumValues }], - ['SomeEnumTypeWithDescription', { enum: enumValues, description: enumDescription }], - ['SomeTypeWithDescription', { enum: enumValues, description: refObjectDescription }], - ['SomeSimpleObjectType', { type: 'object', properties: {} }], - ['SomeObjectType', { description: parentDescription, - required: ['propertyTwo'], - properties: { propertyOne: bodyProperty, - propertyTwo: bodyPropertyWithDescription, - propertyThree: { $ref: 'SomeEnumType' }, - propertyFour: { $ref: 'SomeEnumTypeWithDescription' }, - propertyFive: bodyPropertyWithSimpleArray, - propertySix: bodyPropertyWithComplexArray, - propertySeven: { type: 'object', properties: { } } } }], - ['SomeNestedType', { required: [nestedPropertyName], - properties: { nestedProperty } }], - ['SomeTooManyPropertiesType', { properties: { ...objectWithTooManyProperties } }], - ['SomeTooNestedType', { properties: { test: { $ref: 'SomeNestedType' } } }], - ['SomeNestedEnumType', { required: [nestedPropertyName], - description: refObjectDescription, - properties: { nestedEnumProperty } }] - ]); +describe("Smapi test - CliCustomizationProcessor class", () => { + const enumValues = ["a", "b"]; + const refObjectDescription = "description for type"; + const enumDescription = "some enum description"; + const parentDescription = "some parent description"; + const bodyPropertyOneName = "propertyOne"; + const bodyPropertyTwoName = "propertyTwo"; + const nestedPropertyName = "nestedProperty"; + const nestedEnumPropertyName = "nestedEnumProperty"; + const bodyProperty = {type: "number"}; + const bodyPropertyWithSimpleArray = {type: "array", items: {$ref: "#/definitions/SomeEnumType"}}; + const bodyPropertyWithComplexArray = {type: "array", items: {$ref: "#/definitions/SomeSimpleObjectType"}}; + const bodyPropertyWithDescription = {description: "property description", type: "boolean"}; + const nestedProperty = {$ref: "SomeObjectType"}; + const nestedEnumProperty = {$ref: "SomeEnumTypeWithDescription"}; + let processor; + let parentOperation; + let definitions; + const objectWithTooManyProperties = {}; + for (let i = 0; i < MAX_NESTED_PROPERTIES; i++) { + objectWithTooManyProperties[i] = "test"; + } + + beforeEach(() => { + processor = new CliCustomizationProcessor(); + parentOperation = { + customizationMetadata: { + flatParamsMap: new Map(), + }, + }; + definitions = new Map([ + ["SomeEnumType", {enum: enumValues}], + ["SomeEnumTypeWithDescription", {enum: enumValues, description: enumDescription}], + ["SomeTypeWithDescription", {enum: enumValues, description: refObjectDescription}], + ["SomeSimpleObjectType", {type: "object", properties: {}}], + [ + "SomeObjectType", + { + description: parentDescription, + required: ["propertyTwo"], + properties: { + propertyOne: bodyProperty, + propertyTwo: bodyPropertyWithDescription, + propertyThree: {$ref: "SomeEnumType"}, + propertyFour: {$ref: "SomeEnumTypeWithDescription"}, + propertyFive: bodyPropertyWithSimpleArray, + propertySix: bodyPropertyWithComplexArray, + propertySeven: {type: "object", properties: {}}, + }, + }, + ], + ["SomeNestedType", {required: [nestedPropertyName], properties: {nestedProperty}}], + ["SomeTooManyPropertiesType", {properties: {...objectWithTooManyProperties}}], + ["SomeTooNestedType", {properties: {test: {$ref: "SomeNestedType"}}}], + ["SomeNestedEnumType", {required: [nestedPropertyName], description: refObjectDescription, properties: {nestedEnumProperty}}], + ]); + }); + + describe("# processOperationName", () => { + it("| should convert to kebab case and strip last 2 characters for version", () => { + const result = processor.processOperationName("getContentUploadByIdV1"); + expect(result).eql("get-content-upload-by-id"); }); + }); - describe('# processOperationName', () => { - it('| should convert to kebab case and strip last 2 characters for version', () => { - const result = processor.processOperationName('getContentUploadByIdV1'); - expect(result).eql('get-content-upload-by-id'); - }); + describe("# processOperation", () => { + it("| should create empty flatParamsMap on operator object", () => { + const operation = {customizationMetadata: {}}; + processor.processOperation("test", operation); + expect(operation.customizationMetadata.flatParamsMap).eql(new Map()); }); + }); - describe('# processOperation', () => { - it('| should create empty flatParamsMap on operator object', () => { - const operation = { customizationMetadata: {} }; - processor.processOperation('test', operation); - expect(operation.customizationMetadata.flatParamsMap).eql(new Map()); - }); - }); + describe("# processParameter", () => { + it("| should add simple non body paramter", () => { + const parameter = makeParameter(); + + processor.processParameter(parameter, parentOperation, definitions); - describe('# processParameter', () => { - it('| should add simple non body paramter', () => { - const parameter = makeParameter(); + const key = camelCase(parameter.name); + const {flatParamsMap} = parentOperation.customizationMetadata; - processor.processParameter(parameter, parentOperation, definitions); + const expected = {...parameter, enum: undefined}; + expect(flatParamsMap.get(standardize(key))).eql(expected); + }); - const key = camelCase(parameter.name); - const { flatParamsMap } = parentOperation.customizationMetadata; + it("| should skip processing of parameter", () => { + const parameter = makeParameter(); + const skip = true; - const expected = { ...parameter, enum: undefined }; - expect(flatParamsMap.get(standardize(key))).eql(expected); - }); + sinon.stub(customizationMap, "get").returns({skip}); - it('| should skip processing of parameter', () => { - const parameter = makeParameter(); - const skip = true; + processor.processParameter(parameter, parentOperation, definitions); + + expect(parentOperation.customizationMetadata.flatParamsMap.size).eql(0); + }); - sinon.stub(customizationMap, 'get').returns({ skip }); + it("| should add simple array of non body paramter", () => { + const parameter = makeParameter({type: "array"}); - processor.processParameter(parameter, parentOperation, definitions); + processor.processParameter(parameter, parentOperation, definitions); - expect(parentOperation.customizationMetadata.flatParamsMap.size).eql(0); - }); + const key = camelCase(parameter.name); + const {flatParamsMap} = parentOperation.customizationMetadata; + const expected = {...parameter, enum: undefined, isArray: true}; + expect(flatParamsMap.get(standardize(key))).eql(expected); + }); - it('| should add simple array of non body paramter', () => { - const parameter = makeParameter({ type: 'array' }); + it("| should add reference enum of non body paramter", () => { + const parameter = makeParameter({type: "array", items: {$ref: "#/definitions/SomeEnumType"}}); - processor.processParameter(parameter, parentOperation, definitions); + processor.processParameter(parameter, parentOperation, definitions); - const key = camelCase(parameter.name); - const { flatParamsMap } = parentOperation.customizationMetadata; + const key = camelCase(parameter.name); + const {flatParamsMap} = parentOperation.customizationMetadata; - const expected = { ...parameter, enum: undefined, isArray: true }; - expect(flatParamsMap.get(standardize(key))).eql(expected); - }); + const expected = {...parameter, enum: enumValues, isArray: true}; + expect(flatParamsMap.get(standardize(key))).eql(expected); + }); - it('| should add reference enum of non body paramter', () => { - const parameter = makeParameter({ type: 'array', items: { $ref: '#/definitions/SomeEnumType' } }); + it("| should add reference items of non body paramter and use reference item description if not defined", () => { + const parameter = makeParameter({type: "array", items: {$ref: "#/definitions/SomeTypeWithDescription"}}); - processor.processParameter(parameter, parentOperation, definitions); + processor.processParameter(parameter, parentOperation, definitions); - const key = camelCase(parameter.name); - const { flatParamsMap } = parentOperation.customizationMetadata; + const key = camelCase(parameter.name); + const {flatParamsMap} = parentOperation.customizationMetadata; - const expected = { ...parameter, enum: enumValues, isArray: true }; - expect(flatParamsMap.get(standardize(key))).eql(expected); - }); + const expected = {...parameter, enum: enumValues, description: refObjectDescription, isArray: true}; + expect(flatParamsMap.get(standardize(key))).eql(expected); + }); - it('| should add reference items of non body paramter and use reference item description if not defined', () => { - const parameter = makeParameter({ type: 'array', items: { $ref: '#/definitions/SomeTypeWithDescription' } }); + it("| should add body parameter", () => { + const parameter = makeParameter({in: "body", schema: {$ref: "#/definitions/SomeObjectType"}}); - processor.processParameter(parameter, parentOperation, definitions); + processor.processParameter(parameter, parentOperation, definitions); - const key = camelCase(parameter.name); - const { flatParamsMap } = parentOperation.customizationMetadata; + const rootName = camelCase(parameter.name); + const {flatParamsMap} = parentOperation.customizationMetadata; - const expected = { ...parameter, enum: enumValues, description: refObjectDescription, isArray: true }; - expect(flatParamsMap.get(standardize(key))).eql(expected); - }); + const expectedOne = { + ...bodyProperty, + description: undefined, + required: false, + rootName, + bodyPath: bodyPropertyOneName, + name: bodyPropertyOneName, + json: false, + isNumber: true, + }; + expect(flatParamsMap.get(standardize(bodyPropertyOneName))).eql(expectedOne); - it('| should add body parameter', () => { - const parameter = makeParameter({ in: 'body', schema: { $ref: '#/definitions/SomeObjectType' } }); + const expectedTwo = { + ...bodyPropertyWithDescription, + required: true, + rootName, + bodyPath: bodyPropertyTwoName, + name: bodyPropertyTwoName, + json: false, + isBoolean: true, + }; + expect(flatParamsMap.get(standardize(bodyPropertyTwoName))).eql(expectedTwo); + }); - processor.processParameter(parameter, parentOperation, definitions); + it("| should add customized body parameter", () => { + sinon.stub(customizationMap, "get").returns({ + skipUnwrap: true, + }); + const parameter = makeParameter({in: "body", schema: {$ref: "#/definitions/SomeObjectType"}}); - const rootName = camelCase(parameter.name); - const { flatParamsMap } = parentOperation.customizationMetadata; + processor.processParameter(parameter, parentOperation, definitions); - const expectedOne = { ...bodyProperty, - description: undefined, - required: false, - rootName, - bodyPath: bodyPropertyOneName, - name: bodyPropertyOneName, - json: false, - isNumber: true }; - expect(flatParamsMap.get(standardize(bodyPropertyOneName))).eql(expectedOne); + const {flatParamsMap} = parentOperation.customizationMetadata; + const {name, required, description} = parameter; + const expected = {name, required, description, json: true}; + expect(flatParamsMap.get(standardize(parameter.name))).eql(expected); + }); - const expectedTwo = { ...bodyPropertyWithDescription, - required: true, - rootName, - bodyPath: bodyPropertyTwoName, - name: bodyPropertyTwoName, - json: false, - isBoolean: true }; - expect(flatParamsMap.get(standardize(bodyPropertyTwoName))).eql(expectedTwo); - }); + it("| should add customized body parameter with custom properties", () => { + const name = "customName"; + const required = true; + const description = "custom description"; + sinon.stub(customizationMap, "get").returns({ + customParameters: [{name, description, required}], + }); + const parameter = makeParameter({in: "body", schema: {$ref: "#/definitions/SomeObjectType"}}); - it('| should add customized body parameter', () => { - sinon.stub(customizationMap, 'get').returns({ - skipUnwrap: true - }); - const parameter = makeParameter({ in: 'body', schema: { $ref: '#/definitions/SomeObjectType' } }); + processor.processParameter(parameter, parentOperation, definitions); - processor.processParameter(parameter, parentOperation, definitions); + const {flatParamsMap} = parentOperation.customizationMetadata; - const { flatParamsMap } = parentOperation.customizationMetadata; - const { name, required, description } = parameter; - const expected = { name, required, description, json: true }; - expect(flatParamsMap.get(standardize(parameter.name))).eql(expected); - }); + const expected = {name, required, description}; + expect(flatParamsMap.get(standardize(name))).eql(expected); + }); - it('| should add customized body parameter with custom properties', () => { - const name = 'customName'; - const required = true; - const description = 'custom description'; - sinon.stub(customizationMap, 'get').returns({ - customParameters: [{ name, description, required }] - }); - const parameter = makeParameter({ in: 'body', schema: { $ref: '#/definitions/SomeObjectType' } }); + it("| should add one level deep body parameter", () => { + const parameter = makeParameter({in: "body", schema: {$ref: "#/definitions/SomeNestedType"}}); + + processor.processParameter(parameter, parentOperation, definitions); + + const rootName = camelCase(parameter.name); + const {flatParamsMap} = parentOperation.customizationMetadata; + let {name, bodyPath, key} = mapExpectedParams(nestedPropertyName, bodyPropertyOneName); + + let expected = { + description: parentDescription, + name, + rootName, + bodyPath, + required: false, + enum: null, + json: false, + isNumber: true, + type: "number", + }; + expect(flatParamsMap.get(standardize(key))).eql(expected); + + const expectedParams = mapExpectedParams(nestedPropertyName, bodyPropertyTwoName); + name = expectedParams.name; + bodyPath = expectedParams.bodyPath; + key = expectedParams.key; + expected = {...bodyPropertyWithDescription, name, rootName, bodyPath, required: true, enum: null, json: false, isBoolean: true}; + + expect(flatParamsMap.get(standardize(key))).eql(expected); + }); - processor.processParameter(parameter, parentOperation, definitions); + it("| should fail since the body parameter is nested too deep", () => { + const parameter = makeParameter({in: "body", schema: {$ref: "#/definitions/SomeTooNestedType"}}); - const { flatParamsMap } = parentOperation.customizationMetadata; + const badFn = () => processor.processParameter(parameter, parentOperation, definitions); - const expected = { name, required, description }; - expect(flatParamsMap.get(standardize(name))).eql(expected); - }); + expect(badFn).to.throw(CliError, "Cannot unwrap more then"); + }); - it('| should add one level deep body parameter', () => { - const parameter = makeParameter({ in: 'body', schema: { $ref: '#/definitions/SomeNestedType' } }); + it("| should fail since the body parameter has too many properties", () => { + const parameter = makeParameter({in: "body", schema: {$ref: "#/definitions/SomeTooManyPropertiesType"}}); - processor.processParameter(parameter, parentOperation, definitions); + const badFn = () => processor.processParameter(parameter, parentOperation, definitions); - const rootName = camelCase(parameter.name); - const { flatParamsMap } = parentOperation.customizationMetadata; - let { name, bodyPath, key } = mapExpectedParams(nestedPropertyName, bodyPropertyOneName); - - let expected = { description: parentDescription, - name, - rootName, - bodyPath, - required: false, - enum: null, - json: false, - isNumber: true, - type: 'number' }; - expect(flatParamsMap.get(standardize(key))).eql(expected); - - const expectedParams = mapExpectedParams(nestedPropertyName, bodyPropertyTwoName); - name = expectedParams.name; - bodyPath = expectedParams.bodyPath; - key = expectedParams.key; - expected = { ...bodyPropertyWithDescription, name, rootName, bodyPath, required: true, enum: null, json: false, isBoolean: true }; - - expect(flatParamsMap.get(standardize(key))).eql(expected); - }); - - it('| should fail since the body parameter is nested too deep', () => { - const parameter = makeParameter({ in: 'body', schema: { $ref: '#/definitions/SomeTooNestedType' } }); - - const badFn = () => processor.processParameter(parameter, parentOperation, definitions); - - expect(badFn).to.throw(CliError, 'Cannot unwrap more then'); - }); - - it('| should fail since the body parameter has too many properties', () => { - const parameter = makeParameter({ in: 'body', schema: { $ref: '#/definitions/SomeTooManyPropertiesType' } }); - - const badFn = () => processor.processParameter(parameter, parentOperation, definitions); - - expect(badFn).to.throw(CliError, 'number of body properties exceeds'); - }); - - it('| should add one level deep body enum parameter', () => { - const parameter = makeParameter({ in: 'body', schema: { $ref: '#/definitions/SomeNestedEnumType' } }); - - processor.processParameter(parameter, parentOperation, definitions); - - const rootName = camelCase(parameter.name); - const { flatParamsMap } = parentOperation.customizationMetadata; - const name = nestedEnumPropertyName; - const bodyPath = nestedEnumPropertyName; - - const expected = { ...bodyProperty, - name, - rootName, - bodyPath, - required: false, - enum: enumValues, - description: enumDescription, - type: undefined }; - expect(flatParamsMap.get(standardize(nestedEnumPropertyName))).eql(expected); - }); + expect(badFn).to.throw(CliError, "number of body properties exceeds"); }); - afterEach(() => { - sinon.restore(); + it("| should add one level deep body enum parameter", () => { + const parameter = makeParameter({in: "body", schema: {$ref: "#/definitions/SomeNestedEnumType"}}); + + processor.processParameter(parameter, parentOperation, definitions); + + const rootName = camelCase(parameter.name); + const {flatParamsMap} = parentOperation.customizationMetadata; + const name = nestedEnumPropertyName; + const bodyPath = nestedEnumPropertyName; + + const expected = { + ...bodyProperty, + name, + rootName, + bodyPath, + required: false, + enum: enumValues, + description: enumDescription, + type: undefined, + }; + expect(flatParamsMap.get(standardize(nestedEnumPropertyName))).eql(expected); }); + }); + + afterEach(() => { + sinon.restore(); + }); }); diff --git a/test/unit/commands/smapi/smapi-command-handler-test.js b/test/unit/commands/smapi/smapi-command-handler-test.js index f84dfaa1..1d0dcdee 100644 --- a/test/unit/commands/smapi/smapi-command-handler-test.js +++ b/test/unit/commands/smapi/smapi-command-handler-test.js @@ -1,261 +1,285 @@ -const { expect } = require('chai'); -const sinon = require('sinon'); -const fs = require('fs-extra'); -const { CustomSmapiClientBuilder } = require('ask-smapi-sdk'); -const AppConfig = require('@src/model/app-config'); -const { ARRAY_SPLIT_DELIMITER } = require('@src/commands/smapi/cli-customization-processor'); -const Messenger = require('@src/view/messenger'); -const jsonView = require('@src/view/json-view'); -const BeforeSendProcessor = require('@src/commands/smapi/before-send-processor'); -const AuthorizationController = require('@src/controllers/authorization-controller'); -const profileHelper = require('@src/utils/profile-helper'); -const { smapiCommandHandler, parseSmapiResponse } = require('@src/commands/smapi/smapi-command-handler'); - -describe('Smapi test - smapiCommandHandler function', () => { - const apiOperationName = 'someApiOperation'; - const sdkFunctionName = 'callSomeApiOperation'; - const commandName = 'some-api-operation'; - const skillId = 'some skill id'; - const someNumber = '20'; - const someBoolean = 'true'; - const jsonValue = { test: 'test' }; - const arrayValue = ['test', 'test1', 'test2']; - const arrayValueStr = arrayValue.join(ARRAY_SPLIT_DELIMITER); - const fakeResponse = { - body: { someProperty: 'x' }, - headers: [{ - key: 'x', - value: 'y' - }, - { - key: 'z', - value: 'b' - }], - statusCode: 200 +const {expect} = require("chai"); +const sinon = require("sinon"); +const fs = require("fs-extra"); +const {CustomSmapiClientBuilder} = require("ask-smapi-sdk"); +const AppConfig = require("../../../../lib/model/app-config"); +const {ARRAY_SPLIT_DELIMITER} = require("../../../../lib/commands/smapi/cli-customization-processor"); +const Messenger = require("../../../../lib/view/messenger"); +const jsonView = require("../../../../lib/view/json-view"); +const BeforeSendProcessor = require("../../../../lib/commands/smapi/before-send-processor"); +const AuthorizationController = require("../../../../lib/controllers/authorization-controller"); +const profileHelper = require("../../../../lib/utils/profile-helper"); +const {smapiCommandHandler, parseSmapiResponse} = require("../../../../lib/commands/smapi/smapi-command-handler"); + +describe("Smapi test - smapiCommandHandler function", () => { + const apiOperationName = "someApiOperation"; + const sdkFunctionName = "callSomeApiOperation"; + const commandName = "some-api-operation"; + const skillId = "some skill id"; + const someNumber = "20"; + const someBoolean = "true"; + const jsonValue = {test: "test"}; + const arrayValue = ["test", "test1", "test2"]; + const arrayValueStr = arrayValue.join(ARRAY_SPLIT_DELIMITER); + const fakeResponse = { + body: {someProperty: "x"}, + headers: [ + { + key: "x", + value: "y", + }, + { + key: "z", + value: "b", + }, + ], + statusCode: 200, + }; + + const flatParamsMap = new Map([ + ["skillid", {name: "skillId"}], + ["somejson", {name: "someJson", json: true}], + ["somearray", {name: "someArray", isArray: true}], + ["somenumber", {rootName: "simulationsApiRequest", bodyPath: "input>>>someNumber", isNumber: true}], + ["someboolean", {rootName: "simulationsApiRequest", bodyPath: "input>>>someBoolean", isBoolean: true}], + ["sessionmode", {rootName: "simulationsApiRequest", bodyPath: "session>>>mode"}], + ]); + + const commanderToApiCustomizationMap = new Map(); + let cmdObj; + + const clientStub = {apiConfiguration: {apiEndpoint: null}}; + + const modelInterceptor = { + operations: new Map([[commandName, {params: []}]]), + definitions: new Map(), + }; + + beforeEach(() => { + cmdObj = { + opts() { + return {skillId, someNumber, someBoolean, someJson: JSON.stringify(jsonValue), someArray: arrayValueStr}; + }, + _name: commandName, }; - - const flatParamsMap = new Map([ - ['skillid', { name: 'skillId' }], - ['somejson', { name: 'someJson', json: true }], - ['somearray', { name: 'someArray', isArray: true }], - ['somenumber', { rootName: 'simulationsApiRequest', bodyPath: 'input>>>someNumber', isNumber: true }], - ['someboolean', { rootName: 'simulationsApiRequest', bodyPath: 'input>>>someBoolean', isBoolean: true }], - ['sessionmode', { rootName: 'simulationsApiRequest', bodyPath: 'session>>>mode' }]]); - - const commanderToApiCustomizationMap = new Map(); - let cmdObj; - - const clientStub = { apiConfiguration: { apiEndpoint: null } }; - - const modelInterceptor = { - operations: new Map([[commandName, { params: [] }]]), - definitions: new Map() - }; - - beforeEach(() => { - cmdObj = { - opts() { - return { skillId, someNumber, someBoolean, someJson: JSON.stringify(jsonValue), someArray: arrayValueStr }; - }, - _name: commandName - }; - sinon.stub(AuthorizationController.prototype, '_getAuthClientInstance').returns( - { config: {} } - ); - sinon.stub(profileHelper, 'runtimeProfile').returns('test'); - sinon.stub(AppConfig.prototype, '_validateFilePath'); - sinon.stub(AppConfig.prototype, 'read'); - sinon.stub(AppConfig, 'getInstance').returns({ - getToken() { - return { refresh_token: 'test' }; - } - }); - clientStub[sdkFunctionName] = sinon.stub(); - clientStub[sdkFunctionName].resolves({ ...fakeResponse }); - clientStub[sdkFunctionName].toString = () => 'function (someJson, skillId, ' - + 'someNonPopulatedProperty, someArray, simulationsApiRequest) { return 0};'; - sinon.stub(BeforeSendProcessor.prototype, 'processAll'); - sinon.stub(CustomSmapiClientBuilder.prototype, 'client').returns(clientStub); - }); - - it('| should send smapi command with correct parameter mapping', async () => { - await smapiCommandHandler(apiOperationName, flatParamsMap, commanderToApiCustomizationMap, cmdObj, modelInterceptor); - - const expectedParams = [jsonValue, skillId, null, arrayValue, - { input: { someNumber: Number(someNumber), someBoolean: Boolean(someBoolean) } }]; - const calledParams = clientStub[sdkFunctionName].args[0]; - - expect(calledParams).eql(expectedParams); - }); - - it('| should return command executed successfully when no response body', async () => { - const { headers, statusCode } = fakeResponse; - clientStub[sdkFunctionName].resolves({ headers, statusCode }); - - const result = await smapiCommandHandler(apiOperationName, flatParamsMap, commanderToApiCustomizationMap, cmdObj, modelInterceptor); - - expect(result).eql('Command executed successfully!'); - }); - - it('| should read parameter from json file amd send smapi command', async () => { - const jsonFilePath = 'file:some-file.json'; - sinon.stub(fs, 'readFileSync').returns(JSON.stringify(jsonValue)); - cmdObj.opts = () => ({ skillId, someNumber, someBoolean, someJson: jsonFilePath, someArray: arrayValueStr }); - - await smapiCommandHandler(apiOperationName, flatParamsMap, commanderToApiCustomizationMap, cmdObj, modelInterceptor); - - const expectedParams = [jsonValue, skillId, null, arrayValue, - { input: { someNumber: Number(someNumber), someBoolean: Boolean(someBoolean) } }]; - const calledParams = clientStub[sdkFunctionName].args[0]; - - expect(calledParams).eql(expectedParams); - }); - - it('| should read parameter from text file amd send smapi command', async () => { - const textFilePath = 'file:some-file.txt'; - const textValue = 'some text'; - sinon.stub(fs, 'readFileSync').returns(textValue); - cmdObj.opts = () => ({ skillId, someNumber, someBoolean, someJson: textFilePath, someArray: arrayValueStr }); - - await smapiCommandHandler(apiOperationName, flatParamsMap, commanderToApiCustomizationMap, cmdObj, modelInterceptor); - - const expectedParams = [textValue, skillId, null, arrayValue, - { input: { someNumber: Number(someNumber), someBoolean: Boolean(someBoolean) } }]; - const calledParams = clientStub[sdkFunctionName].args[0]; - - expect(calledParams).eql(expectedParams); - }); - - it('| should parse parameter as text if not able to parse to json amd send smapi command', async () => { - const textValue = 'some text'; - sinon.stub(fs, 'readFileSync').returns(textValue); - cmdObj.opts = () => ({ skillId, someNumber, someBoolean, someJson: textValue, someArray: arrayValueStr }); - - await smapiCommandHandler(apiOperationName, flatParamsMap, commanderToApiCustomizationMap, cmdObj, modelInterceptor); - - const expectedParams = [textValue, skillId, null, arrayValue, - { input: { someNumber: Number(someNumber), someBoolean: Boolean(someBoolean) } }]; - const calledParams = clientStub[sdkFunctionName].args[0]; - - expect(calledParams).eql(expectedParams); - }); - - it('| should display debug message when debug flag is passed', async () => { - const cmdObjDebug = { - opts() { - return { debug: true, skillId }; - }, - _name: commandName - }; - - const messengerStub = sinon.stub(Messenger, 'displayMessage'); - - await smapiCommandHandler(apiOperationName, flatParamsMap, commanderToApiCustomizationMap, cmdObjDebug, modelInterceptor); - - expect(messengerStub.args[0]).eql(['INFO', 'Operation: someApiOperation']); - expect(messengerStub.args[1]).eql(['INFO', 'Payload:']); - expect(messengerStub.args[2]) - .eql(['INFO', `${jsonView.toString({ someJson: null, - skillId, - someNonPopulatedProperty: null, - someArray: null, - simulationsApiRequest: {} })}\n`]); - expect(messengerStub.args[3]).eql(['INFO', 'Response:']); - expect(messengerStub.args[4]).eql(['INFO', jsonView.toString(fakeResponse)]); + sinon.stub(AuthorizationController.prototype, "_getAuthClientInstance").returns({config: {}}); + sinon.stub(profileHelper, "runtimeProfile").returns("test"); + sinon.stub(AppConfig.prototype, "_validateFilePath"); + sinon.stub(AppConfig.prototype, "read"); + sinon.stub(AppConfig, "getInstance").returns({ + getToken() { + return {refresh_token: "test"}; + }, }); + clientStub[sdkFunctionName] = sinon.stub(); + clientStub[sdkFunctionName].resolves({...fakeResponse}); + clientStub[sdkFunctionName].toString = () => + "function (someJson, skillId, " + "someNonPopulatedProperty, someArray, simulationsApiRequest) { return 0};"; + sinon.stub(BeforeSendProcessor.prototype, "processAll"); + sinon.stub(CustomSmapiClientBuilder.prototype, "client").returns(clientStub); + }); + + it("| should send smapi command with correct parameter mapping", async () => { + await smapiCommandHandler(apiOperationName, flatParamsMap, commanderToApiCustomizationMap, cmdObj, modelInterceptor); + + const expectedParams = [ + jsonValue, + skillId, + null, + arrayValue, + {input: {someNumber: Number(someNumber), someBoolean: Boolean(someBoolean)}}, + ]; + const calledParams = clientStub[sdkFunctionName].args[0]; + + expect(calledParams).eql(expectedParams); + }); + + it("| should return command executed successfully when no response body", async () => { + const {headers, statusCode} = fakeResponse; + clientStub[sdkFunctionName].resolves({headers, statusCode}); + + const result = await smapiCommandHandler(apiOperationName, flatParamsMap, commanderToApiCustomizationMap, cmdObj, modelInterceptor); + + expect(result).eql("Command executed successfully!"); + }); + + it("| should read parameter from json file amd send smapi command", async () => { + const jsonFilePath = "file:some-file.json"; + sinon.stub(fs, "readFileSync").returns(JSON.stringify(jsonValue)); + cmdObj.opts = () => ({skillId, someNumber, someBoolean, someJson: jsonFilePath, someArray: arrayValueStr}); + + await smapiCommandHandler(apiOperationName, flatParamsMap, commanderToApiCustomizationMap, cmdObj, modelInterceptor); + + const expectedParams = [ + jsonValue, + skillId, + null, + arrayValue, + {input: {someNumber: Number(someNumber), someBoolean: Boolean(someBoolean)}}, + ]; + const calledParams = clientStub[sdkFunctionName].args[0]; + + expect(calledParams).eql(expectedParams); + }); + + it("| should read parameter from text file amd send smapi command", async () => { + const textFilePath = "file:some-file.txt"; + const textValue = "some text"; + sinon.stub(fs, "readFileSync").returns(textValue); + cmdObj.opts = () => ({skillId, someNumber, someBoolean, someJson: textFilePath, someArray: arrayValueStr}); + + await smapiCommandHandler(apiOperationName, flatParamsMap, commanderToApiCustomizationMap, cmdObj, modelInterceptor); + + const expectedParams = [ + textValue, + skillId, + null, + arrayValue, + {input: {someNumber: Number(someNumber), someBoolean: Boolean(someBoolean)}}, + ]; + const calledParams = clientStub[sdkFunctionName].args[0]; + + expect(calledParams).eql(expectedParams); + }); + + it("| should parse parameter as text if not able to parse to json amd send smapi command", async () => { + const textValue = "some text"; + sinon.stub(fs, "readFileSync").returns(textValue); + cmdObj.opts = () => ({skillId, someNumber, someBoolean, someJson: textValue, someArray: arrayValueStr}); + + await smapiCommandHandler(apiOperationName, flatParamsMap, commanderToApiCustomizationMap, cmdObj, modelInterceptor); + + const expectedParams = [ + textValue, + skillId, + null, + arrayValue, + {input: {someNumber: Number(someNumber), someBoolean: Boolean(someBoolean)}}, + ]; + const calledParams = clientStub[sdkFunctionName].args[0]; + + expect(calledParams).eql(expectedParams); + }); + + it("| should display debug message when debug flag is passed", async () => { + const cmdObjDebug = { + opts() { + return {debug: true, skillId}; + }, + _name: commandName, + }; - it('| should display body, headers and status code when full response flag is passed', async () => { - const cmdObjDebug = { - opts() { - return { fullResponse: true, skillId }; - }, - _name: commandName - }; + const messengerStub = sinon.stub(Messenger.getInstance(), "displayMessage"); + + await smapiCommandHandler(apiOperationName, flatParamsMap, commanderToApiCustomizationMap, cmdObjDebug, modelInterceptor); + + expect(messengerStub.args[0]).eql(["INFO", "Operation: someApiOperation"]); + expect(messengerStub.args[1]).eql(["INFO", "Payload:"]); + expect(messengerStub.args[2]).eql([ + "INFO", + `${jsonView.toString({someJson: null, skillId, someNonPopulatedProperty: null, someArray: null, simulationsApiRequest: {}})}\n`, + ]); + expect(messengerStub.args[3]).eql(["INFO", "Response:"]); + expect(messengerStub.args[4]).eql(["INFO", jsonView.toString(fakeResponse)]); + }); + + it("| should display body, headers and status code when full response flag is passed", async () => { + const cmdObjDebug = { + opts() { + return {fullResponse: true, skillId}; + }, + _name: commandName, + }; - const result = await smapiCommandHandler(apiOperationName, flatParamsMap, commanderToApiCustomizationMap, cmdObjDebug, modelInterceptor); + const result = await smapiCommandHandler( + apiOperationName, + flatParamsMap, + commanderToApiCustomizationMap, + cmdObjDebug, + modelInterceptor, + ); - expect(result).eql(jsonView.toString(fakeResponse)); - }); + expect(result).eql(jsonView.toString(fakeResponse)); + }); - afterEach(() => { - sinon.restore(); - }); + afterEach(() => { + sinon.restore(); + }); }); -describe('Smapi test - parseSmapiResponse function', () => { - let warnStub; - beforeEach(() => { - warnStub = sinon.stub(); - sinon.stub(Messenger, 'getInstance').returns({ - warn: warnStub - }); - }); - it('| should parse text/csv response', () => { - const content = 'foo bar\n foo'; - const response = { headers: [{ key: 'content-type', value: 'text/csv' }], body: content }; - - const result = parseSmapiResponse(response); - - expect(result).eql(content); - }); - - it('| should parse application/json response', () => { - const content = { foo: 'bar' }; - const response = { headers: [{ key: 'content-type', value: 'application/json' }], body: content }; - - const result = parseSmapiResponse(response); - - expect(result).eql(jsonView.toString(content)); - }); - - it('| should return command executed successfully if not response body', () => { - const response = { headers: [] }; - - const result = parseSmapiResponse(response); - - expect(result).eql('Command executed successfully!'); - }); - - it('| should show warning with status hint command when able to find one', () => { - const skillId = 'someSkillId'; - const resource = 'someResource'; - const profile = 'test'; - const url = `/v1/skills/${skillId}/status?resource=${resource}`; - const response = { headers: [{ key: 'location', value: url }], statusCode: 202 }; - - parseSmapiResponse(response, profile); - expect(warnStub.firstCall.lastArg).eql('This is an asynchronous operation. Check the progress ' - + `using the following command: ask smapi get-skill-status --skill-id ${skillId} --resource ${resource} --profile ${profile}`); - }); - - it('| should show warning with status hint for customized parameters', () => { - const skillId = 'someSkillId'; - const resource = 'someResource'; - const vendorId = 'someVendorId'; - sinon.stub(Map.prototype, 'get') - .withArgs('vendorId') - .returns({ skip: true }) - .withArgs('resource') - .returns('someCustomName'); - - const url = `/v1/skills/${skillId}/status?resource=${resource}&vendorId=${vendorId}`; - const response = { headers: [{ key: 'location', value: url }], statusCode: 202 }; - - parseSmapiResponse(response); - expect(warnStub.firstCall.lastArg).eql('This is an asynchronous operation. Check the progress ' - + `using the following command: ask smapi get-skill-status --skill-id ${skillId} --some-custom-name ${resource}`); - }); - - it('| should not show warning with status hint command when not able to find one', () => { - const url = '/some-random-non-smapi-url'; - const response = { headers: [{ key: 'location', value: url }], statusCode: 202 }; - - parseSmapiResponse(response); - - expect(warnStub.firstCall.lastArg).eql('This is an asynchronous operation. Check the progress ' - + `using the following url: ${url}`); - }); - afterEach(() => { - sinon.restore(); +describe("Smapi test - parseSmapiResponse function", () => { + let warnStub; + beforeEach(() => { + warnStub = sinon.stub(); + sinon.stub(Messenger, "getInstance").returns({ + warn: warnStub, }); + }); + it("| should parse text/csv response", () => { + const content = "foo bar\n foo"; + const response = {headers: [{key: "content-type", value: "text/csv"}], body: content}; + + const result = parseSmapiResponse(response); + + expect(result).eql(content); + }); + + it("| should parse application/json response", () => { + const content = {foo: "bar"}; + const response = {headers: [{key: "content-type", value: "application/json"}], body: content}; + + const result = parseSmapiResponse(response); + + expect(result).eql(jsonView.toString(content)); + }); + + it("| should return command executed successfully if not response body", () => { + const response = {headers: []}; + + const result = parseSmapiResponse(response); + + expect(result).eql("Command executed successfully!"); + }); + + it("| should show warning with status hint command when able to find one", () => { + const skillId = "someSkillId"; + const resource = "someResource"; + const profile = "test"; + const url = `/v1/skills/${skillId}/status?resource=${resource}`; + const response = {headers: [{key: "location", value: url}], statusCode: 202}; + + parseSmapiResponse(response, profile); + expect(warnStub.firstCall.lastArg).eql( + "This is an asynchronous operation. Check the progress " + + `using the following command: ask smapi get-skill-status --skill-id ${skillId} --resource ${resource} --profile ${profile}`, + ); + }); + + it("| should show warning with status hint for customized parameters", () => { + const skillId = "someSkillId"; + const resource = "someResource"; + const vendorId = "someVendorId"; + sinon.stub(Map.prototype, "get").withArgs("vendorId").returns({skip: true}).withArgs("resource").returns("someCustomName"); + + const url = `/v1/skills/${skillId}/status?resource=${resource}&vendorId=${vendorId}`; + const response = {headers: [{key: "location", value: url}], statusCode: 202}; + + parseSmapiResponse(response); + expect(warnStub.firstCall.lastArg).eql( + "This is an asynchronous operation. Check the progress " + + `using the following command: ask smapi get-skill-status --skill-id ${skillId} --some-custom-name ${resource}`, + ); + }); + + it("| should not show warning with status hint command when not able to find one", () => { + const url = "/some-random-non-smapi-url"; + const response = {headers: [{key: "location", value: url}], statusCode: 202}; + + parseSmapiResponse(response); + + expect(warnStub.firstCall.lastArg).eql("This is an asynchronous operation. Check the progress " + `using the following url: ${url}`); + }); + afterEach(() => { + sinon.restore(); + }); }); diff --git a/test/unit/commands/smapi/smapi-commander-test.js b/test/unit/commands/smapi/smapi-commander-test.js index 8d7faa91..5507fe51 100644 --- a/test/unit/commands/smapi/smapi-commander-test.js +++ b/test/unit/commands/smapi/smapi-commander-test.js @@ -1,47 +1,67 @@ -const { expect } = require('chai'); -const sinon = require('sinon'); -const { makeSmapiCommander } = require('@src/commands/smapi/smapi-commander'); -const handler = require('@src/commands/smapi/smapi-command-handler'); +const {expect} = require("chai"); +const sinon = require("sinon"); +const {makeSmapiCommander} = require("../../../../lib/commands/smapi/smapi-commander"); +const handler = require("../../../../lib/commands/smapi/smapi-command-handler"); +const metricClient = require("../../../../lib/utils/metrics"); -describe('Smapi test - makeSmapiCommander function', () => { - beforeEach(() => { - sinon.stub(process, 'exit'); - sinon.stub(console, 'error'); - }); +describe("Smapi test - makeSmapiCommander function", () => { + beforeEach(() => { + sinon.stub(process, "exit"); + sinon.stub(console, "error"); + }); - it('| should create instance of commander', () => { - const commander = makeSmapiCommander(); + it("| should create instance of commander", () => { + const commander = makeSmapiCommander(); - expect(commander._name).eql('ask smapi'); - expect(commander.commands.length).gt(0); - }); + expect(commander._name).eql("ask smapi"); + expect(commander.commands.length).gt(0); + }); - it('| should show command not recognized for unknown command', async () => { - const commander = makeSmapiCommander(); + it("| should show command not recognized for unknown command", async () => { + const commander = makeSmapiCommander(); - commander.emit('command:*'); + commander.emit("command:*"); - expect(console.error.calledWithMatch('Command not recognized')).eql(true); - }); + expect(console.error.calledWithMatch("Command not recognized")).eql(true); + }); - it('| should execute a command successfully', () => { - sinon.stub(handler, 'smapiCommandHandler').resolves('some data'); - const commander = makeSmapiCommander(); + it("| should execute a command successfully", () => { + sinon.stub(handler, "smapiCommandHandler").resolves("some data"); + const commander = makeSmapiCommander(); - return commander.parseAsync(['', '', 'list-skills-for-vendor']) - .then(res => expect(res[0]).eql('some data')); - }); + return commander.parseAsync(["", "", "list-skills-for-vendor"]).then((res) => expect(res[0]).eql("some data")); + }); - it('| should propagate error if handler fails', () => { - sinon.stub(handler, 'smapiCommandHandler').rejects(new Error('some error')); - const commander = makeSmapiCommander(); + it("| should initialize metrics when command starts", () => { + sinon.stub(handler, "smapiCommandHandler").resolves("some data"); - return commander.parseAsync(['', '', 'list-skills-for-vendor']) - .then(res => expect(res).eql(undefined)) - .catch(err => expect(err.message).eql('some error')); - }); + // call + const commander = makeSmapiCommander(); + commander.parseAsync(["", "", "list-skills-for-vendor", "--max-results", "4"]); + + // verify + const data = metricClient.getData(); + expect(data).to.exist; - afterEach(() => { - sinon.restore(); - }); + const lastAction = data.actions[data.actions.length - 1]; + expect(lastAction.name).to.equal("smapi"); + expect(lastAction.type).to.equal("list-skills-for-vendor"); + + const options = lastAction.options; + expect(options).has.members(["max_results"]); + }); + + it("| should propagate error if handler fails", () => { + sinon.stub(handler, "smapiCommandHandler").rejects(new Error("some error")); + const commander = makeSmapiCommander(); + + return commander + .parseAsync(["", "", "list-skills-for-vendor"]) + .then((res) => expect(res).eql(undefined)) + .catch((err) => expect(err.message).eql("some error")); + }); + + afterEach(() => { + sinon.restore(); + }); }); diff --git a/test/unit/commands/smapi/smapi-docs-test.js b/test/unit/commands/smapi/smapi-docs-test.js index 24ff5da3..9e4c3452 100644 --- a/test/unit/commands/smapi/smapi-docs-test.js +++ b/test/unit/commands/smapi/smapi-docs-test.js @@ -1,53 +1,58 @@ -const { expect } = require('chai'); -const { SmapiDocs } = require('@src/commands/smapi/smapi-docs'); -const { makeSmapiCommander } = require('@src/commands/smapi/smapi-commander'); - -describe('Smapi test - Smapi Docs class', () => { - it('| should generate view data from existing smapi commander', () => { - const commander = makeSmapiCommander(); - - const docs = new SmapiDocs(commander); - - const viewData = docs.generateViewData(); - - expect(viewData.baseCommand).a('string'); - expect(viewData.smapiCommandDescription).a('string'); - expect(viewData.commands).instanceof(Array); - expect(viewData.commands.length).above(1); - expect(viewData.commands[0].options).instanceof(Array); - }); - - it('| should generate view data commands list from a commander', () => { - const parentCommandName = 'ask smapi'; - const commandName = 'generate-something'; - const commandDescription = 'command description'; - const optionDescription = 'some option description'; - const optionOneFlags = '-c,--catalog-id '; - const optionTwoFlags = '--profile '; - const commander = { - _name: parentCommandName, - commands: [ - { - _name: commandName, - _description: commandDescription, - options: [ - { flags: optionOneFlags, description: optionDescription }, - { flags: optionTwoFlags, mandatory: false } - ] - } - ] - }; - - const docs = new SmapiDocs(commander); - const viewData = docs.generateViewData(); - - const expectedCommands = [{ name: commandName, - description: `${commandDescription}.`, - optionsString: '[-c|--catalog-id ] [--profile ]', - options: [ - { name: optionOneFlags, description: `${optionDescription}.` }, - { name: optionTwoFlags, description: '' }] }]; - - expect(viewData.commands).eql(expectedCommands); - }); +const {expect} = require("chai"); +const {SmapiDocs} = require("../../../../lib/commands/smapi/smapi-docs"); +const {makeSmapiCommander} = require("../../../../lib/commands/smapi/smapi-commander"); + +describe("Smapi test - Smapi Docs class", () => { + it("| should generate view data from existing smapi commander", () => { + const commander = makeSmapiCommander(); + + const docs = new SmapiDocs(commander); + + const viewData = docs.generateViewData(); + + expect(viewData.baseCommand).a("string"); + expect(viewData.smapiCommandDescription).a("string"); + expect(viewData.commands).instanceof(Array); + expect(viewData.commands.length).above(1); + expect(viewData.commands[0].options).instanceof(Array); + }); + + it("| should generate view data commands list from a commander", () => { + const parentCommandName = "ask smapi"; + const commandName = "generate-something"; + const commandDescription = "command description"; + const optionDescription = "some option description"; + const optionOneFlags = "-c,--catalog-id "; + const optionTwoFlags = "--profile "; + const commander = { + _name: parentCommandName, + commands: [ + { + _name: commandName, + _description: commandDescription, + options: [ + {flags: optionOneFlags, description: optionDescription}, + {flags: optionTwoFlags, mandatory: false}, + ], + }, + ], + }; + + const docs = new SmapiDocs(commander); + const viewData = docs.generateViewData(); + + const expectedCommands = [ + { + name: commandName, + description: `${commandDescription}.`, + optionsString: "[-c|--catalog-id ] [--profile ]", + options: [ + {name: optionOneFlags, description: `${optionDescription}.`}, + {name: optionTwoFlags, description: ""}, + ], + }, + ]; + + expect(viewData.commands).eql(expectedCommands); + }); }); diff --git a/test/unit/commands/util/generate-lwa-tokens/index-test.js b/test/unit/commands/util/generate-lwa-tokens/index-test.js deleted file mode 100644 index 7501ef99..00000000 --- a/test/unit/commands/util/generate-lwa-tokens/index-test.js +++ /dev/null @@ -1,171 +0,0 @@ -const { expect } = require('chai'); -const sinon = require('sinon'); - -const AuthorizationController = require('@src/controllers/authorization-controller'); -const configureUi = require('@src/commands/configure/ui'); -const GenerateLwaTokensCommand = require('@src/commands/util/generate-lwa-tokens'); -const jsonView = require('@src/view/json-view'); -const Messenger = require('@src/view/messenger'); -const optionModel = require('@src/commands/option-model'); - -describe('Commands generate-lwa-tokens test - command class test', () => { - const TEST_DEBUG = false; - - let infoStub; - let errorStub; - let warnStub; - - beforeEach(() => { - infoStub = sinon.stub(); - errorStub = sinon.stub(); - warnStub = sinon.stub(); - sinon.stub(Messenger, 'getInstance').returns({ - info: infoStub, - error: errorStub, - warn: warnStub - }); - }); - - afterEach(() => { - sinon.restore(); - }); - - it('| validate command information is set correctly', () => { - const instance = new GenerateLwaTokensCommand(optionModel); - expect(instance.name()).equal('generate-lwa-tokens'); - expect(instance.description()).equal('generate Login with Amazon tokens from any LWA client'); - expect(instance.requiredOptions()).deep.equal([]); - expect(instance.optionalOptions()).deep.equal(['client-id', 'client-confirmation', 'scopes', 'no-browser', 'debug']); - }); - - describe('validate command handle', () => { - const TEST_CLIENT_ID = 'client id'; - const TEST_CLIENT_CONFIRMATION = 'client confirmation'; - const TEST_SCOPES = 'scopes1 scopes2'; - const TEST_ERROR = 'error'; - const TEST_AUTHORIZE_URL = 'authorize url'; - const TEST_AUTH_CODE = 'auth code'; - const TEST_ACCESS_TOKEN = { - access_token: 'AToken' - }; - let instance; - - beforeEach(() => { - sinon.stub(configureUi, 'getAuthCode'); - sinon.stub(AuthorizationController.prototype, 'getAuthorizeUrl'); - sinon.stub(AuthorizationController.prototype, 'getAccessTokenUsingAuthCode'); - sinon.stub(AuthorizationController.prototype, 'getTokensByListeningOnPort'); - instance = new GenerateLwaTokensCommand(optionModel); - }); - - afterEach(() => { - sinon.restore(); - }); - - describe('command handle - no browser approach', () => { - it('| ui get authCode fails with error, expect error displayed', (done) => { - // setup - const TEST_CMD = { - browser: false, - debug: TEST_DEBUG - }; - AuthorizationController.prototype.getAuthorizeUrl.returns(TEST_AUTHORIZE_URL); - configureUi.getAuthCode.callsArgWith(0, TEST_ERROR); - // call - instance.handle(TEST_CMD, (err) => { - // verify - expect(err).equal(TEST_ERROR); - expect(errorStub.args[0][0]).equal(TEST_ERROR); - expect(infoStub.callCount).equal(1); - expect(warnStub.callCount).equal(0); - done(); - }); - }); - - it('| lwa controller fails to get accessToken with the input authCode, expect error displayed', (done) => { - // setup - const TEST_CMD = { - browser: false, - debug: TEST_DEBUG - }; - AuthorizationController.prototype.getAuthorizeUrl.returns(TEST_AUTHORIZE_URL); - configureUi.getAuthCode.callsArgWith(0, null, TEST_AUTH_CODE); - AuthorizationController.prototype.getAccessTokenUsingAuthCode.callsArgWith(1, TEST_ERROR); - // call - instance.handle(TEST_CMD, (err) => { - // verify - expect(err).equal(TEST_ERROR); - expect(errorStub.args[0][0]).equal(TEST_ERROR); - expect(infoStub.callCount).equal(1); - expect(warnStub.callCount).equal(0); - done(); - }); - }); - - it('| no-browser flow succeeds, expect ui displays properly', (done) => { - // setup - const TEST_CMD = { - clientId: TEST_CLIENT_ID, - clientConfirmation: TEST_CLIENT_CONFIRMATION, - scopes: TEST_SCOPES, - browser: false, - debug: TEST_DEBUG - }; - AuthorizationController.prototype.getAuthorizeUrl.returns(TEST_AUTHORIZE_URL); - configureUi.getAuthCode.callsArgWith(0, null, TEST_AUTH_CODE); - AuthorizationController.prototype.getAccessTokenUsingAuthCode.callsArgWith(1, null, TEST_ACCESS_TOKEN); - // call - instance.handle(TEST_CMD, (err) => { - // verify - expect(err).equal(undefined); - expect(infoStub.args[0][0]).equal(`Paste the following url to your browser:\n ${TEST_AUTHORIZE_URL}`); - expect(infoStub.args[1][0]).equal('\nThe LWA tokens result:'); - expect(infoStub.args[2][0]).equal(jsonView.toString(TEST_ACCESS_TOKEN)); - expect(errorStub.callCount).equal(0); - expect(warnStub.callCount).equal(0); - done(); - }); - }); - }); - - describe('command handle - use browser approach', () => { - it('| lwa controller fails to get token by listening, expect error displayed', (done) => { - // setup - const TEST_CMD = { - debug: TEST_DEBUG - }; - AuthorizationController.prototype.getTokensByListeningOnPort.callsArgWith(0, TEST_ERROR); - // call - instance.handle(TEST_CMD, (err) => { - // verify - expect(err).equal(TEST_ERROR); - expect(errorStub.args[0][0]).equal(TEST_ERROR); - expect(infoStub.callCount).equal(0); - expect(warnStub.callCount).equal(0); - done(); - }); - }); - - it('| flow with browser succeeds, expect ui displays token info properly', (done) => { - // setup - const TEST_CMD = { - clientId: TEST_CLIENT_ID, - clientConfirmation: TEST_CLIENT_CONFIRMATION, - scopes: TEST_SCOPES, - debug: TEST_DEBUG - }; - AuthorizationController.prototype.getTokensByListeningOnPort.callsArgWith(0, null, TEST_ACCESS_TOKEN); - // call - instance.handle(TEST_CMD, (err) => { - // verify - expect(err).equal(undefined); - expect(infoStub.args[0][0]).equal('The LWA tokens result:'); - expect(infoStub.args[1][0]).equal(jsonView.toString(TEST_ACCESS_TOKEN)); - expect(errorStub.callCount).equal(0); - expect(warnStub.callCount).equal(0); - done(); - }); - }); - }); - }); -}); diff --git a/test/unit/commands/util/generate-lwa-tokens/index-test.ts b/test/unit/commands/util/generate-lwa-tokens/index-test.ts new file mode 100644 index 00000000..6a895d30 --- /dev/null +++ b/test/unit/commands/util/generate-lwa-tokens/index-test.ts @@ -0,0 +1,158 @@ +import {expect} from "chai"; +import sinon from "sinon"; +import AuthorizationController from "../../../../../lib/controllers/authorization-controller"; +import configureUi from "../../../../../lib/commands/configure/ui"; +import GenerateLwaTokensCommand from "../../../../../lib/commands/util/generate-lwa-tokens"; +import jsonView from "../../../../../lib/view/json-view"; +import Messenger from "../../../../../lib/view/messenger"; +import optionModel from "../../../../../lib/commands/option-model.json"; +import {OptionModel} from "../../../../../lib/commands/option-validator"; + +describe("Commands generate-lwa-tokens test - command class test", () => { + const TEST_DEBUG = false; + + let infoStub: sinon.SinonStub; + let errorStub: sinon.SinonStub; + let warnStub: sinon.SinonStub; + + beforeEach(() => { + infoStub = sinon.stub(); + errorStub = sinon.stub(); + warnStub = sinon.stub(); + sinon.stub(Messenger, "getInstance").returns({ + info: infoStub, + error: errorStub, + warn: warnStub, + }); + }); + + afterEach(() => { + sinon.restore(); + }); + + it("| validate command information is set correctly", () => { + const instance = new GenerateLwaTokensCommand(optionModel as OptionModel); + expect(instance.name()).equal("generate-lwa-tokens"); + expect(instance.description()).equal("generate Login with Amazon tokens from any LWA client"); + expect(instance.requiredOptions()).deep.equal([]); + expect(instance.optionalOptions()).deep.equal(["client-id", "client-confirmation", "scopes", "no-browser", "debug"]); + }); + + describe("validate command handle", () => { + const TEST_CLIENT_ID = "client id"; + const TEST_CLIENT_CONFIRMATION = "client confirmation"; + const TEST_SCOPES = "scopes1 scopes2"; + const TEST_ERROR = "error"; + const TEST_AUTHORIZE_URL = "authorize url"; + const TEST_AUTH_CODE = "auth code"; + const TEST_ACCESS_TOKEN = { + access_token: "AToken", + }; + let instance: GenerateLwaTokensCommand; + let authorizationControllerGetAuthorizeUrlStub: sinon.SinonStub; + let configureUiGetAuthCodeStub: sinon.SinonStub; + let authorizationControllerGetAccessTokenUsingAuthCodeStub: sinon.SinonStub; + let authorizationControllerGetTokensByListeningOnPortStub: sinon.SinonStub; + + beforeEach(() => { + configureUiGetAuthCodeStub = sinon.stub(configureUi, "getAuthCode"); + authorizationControllerGetAuthorizeUrlStub = sinon.stub(AuthorizationController.prototype, "getAuthorizeUrl"); + authorizationControllerGetAccessTokenUsingAuthCodeStub = sinon.stub(AuthorizationController.prototype, "getAccessTokenUsingAuthCode"); + authorizationControllerGetTokensByListeningOnPortStub = sinon.stub(AuthorizationController.prototype, "getTokensByListeningOnPort"); + instance = new GenerateLwaTokensCommand(optionModel as OptionModel); + }); + + afterEach(() => { + sinon.restore(); + }); + + describe("command handle - no browser approach", () => { + it("| ui get authCode fails with error, expect error displayed", async () => { + // setup + const TEST_CMD = { + browser: false, + debug: TEST_DEBUG, + }; + authorizationControllerGetAuthorizeUrlStub.returns(TEST_AUTHORIZE_URL); + configureUiGetAuthCodeStub.callsArgWith(0, TEST_ERROR); + // call + await expect(instance.handle(TEST_CMD)).rejectedWith(TEST_ERROR); + expect(errorStub).calledOnceWith(TEST_ERROR); + expect(infoStub).calledOnce; + expect(warnStub).not.called; + }); + + it("| lwa controller fails to get accessToken with the input authCode, expect error displayed", async () => { + // setup + const TEST_CMD = { + browser: false, + debug: TEST_DEBUG, + }; + authorizationControllerGetAuthorizeUrlStub.returns(TEST_AUTHORIZE_URL); + configureUiGetAuthCodeStub.callsArgWith(0, null, TEST_AUTH_CODE); + authorizationControllerGetAccessTokenUsingAuthCodeStub.callsArgWith(1, TEST_ERROR); + // call + await expect(instance.handle(TEST_CMD)).rejectedWith(TEST_ERROR); + expect(errorStub).calledOnceWith(TEST_ERROR); + expect(infoStub).calledOnce; + expect(warnStub).not.called; + }); + + it("| no-browser flow succeeds, expect ui displays properly", async () => { + // setup + const TEST_CMD = { + clientId: TEST_CLIENT_ID, + clientConfirmation: TEST_CLIENT_CONFIRMATION, + scopes: TEST_SCOPES, + browser: false, + debug: TEST_DEBUG, + }; + authorizationControllerGetAuthorizeUrlStub.returns(TEST_AUTHORIZE_URL); + configureUiGetAuthCodeStub.callsArgWith(0, null, TEST_AUTH_CODE); + authorizationControllerGetAccessTokenUsingAuthCodeStub.callsArgWith(1, null, TEST_ACCESS_TOKEN); + // call + await instance.handle(TEST_CMD); + // verify + expect(infoStub.args[0][0]).equal(`Paste the following url to your browser:\n ${TEST_AUTHORIZE_URL}`); + expect(infoStub.args[1][0]).equal("\nThe LWA tokens result:"); + expect(infoStub.args[2][0]).equal(jsonView.toString(TEST_ACCESS_TOKEN)); + expect(errorStub).not.called; + expect(warnStub).not.called; + }); + }); + + describe("command handle - use browser approach", () => { + it("| lwa controller fails to get token by listening, expect error displayed", async () => { + // setup + const TEST_CMD = { + debug: TEST_DEBUG, + }; + authorizationControllerGetTokensByListeningOnPortStub.callsArgWith(0, TEST_ERROR); + // call + await expect(instance.handle(TEST_CMD)).rejectedWith(TEST_ERROR); + + expect(errorStub).calledOnceWith(TEST_ERROR); + expect(infoStub).not.called; + expect(warnStub).not.called; + }); + + it("| flow with browser succeeds, expect ui displays token info properly", async () => { + // setup + const TEST_CMD = { + clientId: TEST_CLIENT_ID, + clientConfirmation: TEST_CLIENT_CONFIRMATION, + scopes: TEST_SCOPES, + debug: TEST_DEBUG, + }; + authorizationControllerGetTokensByListeningOnPortStub.callsArgWith(0, null, TEST_ACCESS_TOKEN); + // call + await instance.handle(TEST_CMD); + // verify + expect(infoStub.args[0][0]).equal("The LWA tokens result:"); + expect(infoStub.args[1][0]).equal(jsonView.toString(TEST_ACCESS_TOKEN)); + expect(errorStub).not.called; + expect(warnStub).not.called; + }); + }); + }); +}); diff --git a/test/unit/commands/util/git-credentials-helper/index-test.js b/test/unit/commands/util/git-credentials-helper/index-test.js deleted file mode 100644 index e7060b05..00000000 --- a/test/unit/commands/util/git-credentials-helper/index-test.js +++ /dev/null @@ -1,207 +0,0 @@ -const { expect } = require('chai'); -const path = require('path'); -const sinon = require('sinon'); - -const AuthorizationController = require('@src/controllers/authorization-controller'); -const GitCredentialsHelperCommand = require('@src/commands/util/git-credentials-helper'); -const httpClient = require('@src/clients/http-client'); -const jsonView = require('@src/view/json-view'); -const Messenger = require('@src/view/messenger'); -const optionModel = require('@src/commands/option-model'); -const profileHelper = require('@src/utils/profile-helper'); -const ResourcesConfig = require('@src/model/resources-config'); - -describe('Commands git-credentials-helper test - command class test', () => { - const TEST_PROFILE = 'default'; - const TEST_DEBUG = false; - const FIXTURE_RESOURCES_CONFIG_FILE_PATH = path.join(process.cwd(), 'test', 'unit', 'fixture', 'model', 'hosted-proj', 'ask-resources.json'); - - let infoStub; - let errorStub; - let warnStub; - - beforeEach(() => { - infoStub = sinon.stub(); - errorStub = sinon.stub(); - warnStub = sinon.stub(); - sinon.stub(Messenger, 'getInstance').returns({ - info: infoStub, - error: errorStub, - warn: warnStub - }); - }); - - afterEach(() => { - sinon.restore(); - }); - - it('| validate command information is set correctly', () => { - const instance = new GitCredentialsHelperCommand(optionModel); - expect(instance.name()).equal('git-credentials-helper'); - expect(instance.description()).equal('gets git credentials for hosted skill repository'); - expect(instance.requiredOptions()).deep.equal([]); - expect(instance.optionalOptions()).deep.equal(['profile', 'debug']); - }); - - describe('validate command handle', () => { - const TEST_CMD = { - profile: TEST_PROFILE, - debug: TEST_DEBUG - }; - const TEST_ERROR_MESSAGE = 'ERROR'; - const ERROR = new Error(TEST_ERROR_MESSAGE); - let instance; - beforeEach(() => { - sinon.stub(profileHelper, 'runtimeProfile').returns(TEST_PROFILE); - instance = new GitCredentialsHelperCommand(optionModel); - new ResourcesConfig(FIXTURE_RESOURCES_CONFIG_FILE_PATH); - }); - - afterEach(() => { - sinon.restore(); - const repository = { - repository: { - type: 'GIT', - url: 'https://git-codecommit.us-east-1.amazonaws.com/v1/repos/5555555-4444-3333-2222-1111111111' - } - }; - ResourcesConfig.getInstance().setSkillInfraDeployState(TEST_PROFILE, repository); - }); - - describe('command handle - before get git credentials', () => { - it('| when called from git and operation is not get, expect error out', (done) => { - // setup - const remaining = ['not supported operation']; - // call - instance.handle(TEST_CMD, (err) => { - // verify - const expectedErr = `The ask-cli git credentials helper doesn't support operation "${remaining[0]}".`; - expect(err).equal(expectedErr); - expect(errorStub.args[0][0]).equal(expectedErr); - expect(infoStub.callCount).equal(0); - expect(warnStub.callCount).equal(0); - done(); - }, remaining); - }); - - it('| when called from git and operation is store, expect do nothing', (done) => { - // setup - const remaining = ['store']; - // call - instance.handle(TEST_CMD, () => { - // verify - expect(errorStub.callCount).equal(0); - expect(infoStub.callCount).equal(0); - expect(warnStub.callCount).equal(0); - done(); - }, remaining); - }); - - it('| when called from git and operation is erase, expect do nothing', (done) => { - // setup - const remaining = ['erase']; - // call - instance.handle(TEST_CMD, () => { - // verify - expect(errorStub.callCount).equal(0); - expect(infoStub.callCount).equal(0); - expect(warnStub.callCount).equal(0); - done(); - }, remaining); - }); - - it('| when profile is not correct, expect throw error', (done) => { - // setup - profileHelper.runtimeProfile.throws(new Error('error')); - // call - instance.handle(TEST_CMD, () => { - // verify - expect(errorStub.args[0][0].message).equal('error'); - expect(infoStub.callCount).equal(0); - expect(warnStub.callCount).equal(0); - done(); - }); - }); - }); - - describe('command handle - request to get git credentials', () => { - beforeEach(() => { - sinon.stub(AuthorizationController.prototype, 'tokenRefreshAndRead').callsArgWith(1); - }); - - it('| get git credentials fails, expect throw error', (done) => { - // setup - sinon.stub(path, 'join').returns(FIXTURE_RESOURCES_CONFIG_FILE_PATH); - sinon.stub(httpClient, 'request').callsArgWith(3, ERROR); // stub getGitCredentials request - // call - instance.handle(TEST_CMD, () => { - // verify - expect(errorStub.args[0][0].message).equal(TEST_ERROR_MESSAGE); - expect(infoStub.callCount).equal(0); - expect(warnStub.callCount).equal(0); - done(); - }); - }); - - it('| get git credentials response with status code >= 300, expect throw error', (done) => { - // setup - const GET_STATUS_ERROR = { - statusCode: 403, - body: { - error: TEST_ERROR_MESSAGE - } - }; - sinon.stub(path, 'join').returns(FIXTURE_RESOURCES_CONFIG_FILE_PATH); - sinon.stub(httpClient, 'request').callsArgWith(3, null, GET_STATUS_ERROR); // stub getGitCredentials request - // call - instance.handle(TEST_CMD, () => { - // verify - expect(errorStub.args[0][0]).equal(jsonView.toString({ error: TEST_ERROR_MESSAGE })); - done(); - }); - }); - - it('| get git credentials succeed, expect correct output', (done) => { - // setup - const TEST_STATUS_CODE = 200; - const TEST_USERNAME = 'TEST_USERNAME'; - const TEST_PASSWORD = 'TEST_PASSWORD'; - const GET_METADATA_RESPONSE = { - statusCode: TEST_STATUS_CODE, - headers: {}, - body: { - alexaHosted: { - repository: { - url: 'test' - } - } - } - }; - const GET_STATUS_RESPONSE = { - statusCode: TEST_STATUS_CODE, - headers: {}, - body: { - repositoryCredentials: { - username: TEST_USERNAME, - password: TEST_PASSWORD - } - } - }; - sinon.stub(path, 'join').returns(FIXTURE_RESOURCES_CONFIG_FILE_PATH); - - sinon.stub(httpClient, 'request') - .onFirstCall() - .yields(null, GET_METADATA_RESPONSE) - .onSecondCall() - .yields(null, GET_STATUS_RESPONSE); - - // call - instance.handle(TEST_CMD, () => { - // verify - expect(infoStub.args[0][0]).equal(`username=${TEST_USERNAME}\npassword=${TEST_PASSWORD}`); - done(); - }); - }); - }); - }); -}); diff --git a/test/unit/commands/util/git-credentials-helper/index-test.ts b/test/unit/commands/util/git-credentials-helper/index-test.ts new file mode 100644 index 00000000..e11717d3 --- /dev/null +++ b/test/unit/commands/util/git-credentials-helper/index-test.ts @@ -0,0 +1,204 @@ +import {expect} from "chai"; +import path from "path"; +import sinon from "sinon"; +import AuthorizationController from "../../../../../lib/controllers/authorization-controller"; +import GitCredentialsHelperCommand from "../../../../../lib/commands/util/git-credentials-helper"; +import httpClient from "../../../../../lib/clients/http-client"; +import jsonView from "../../../../../lib/view/json-view"; +import Messenger from "../../../../../lib/view/messenger"; +import optionModel from "../../../../../lib/commands/option-model.json"; +import profileHelper from "../../../../../lib/utils/profile-helper"; +import ResourcesConfig from "../../../../../lib/model/resources-config"; +import {OptionModel} from "../../../../../lib/commands/option-validator"; + +describe("Commands git-credentials-helper test - command class test", () => { + const TEST_PROFILE = "default"; + const TEST_DEBUG = false; + const FIXTURE_RESOURCES_CONFIG_FILE_PATH = path.join( + process.cwd(), + "test", + "unit", + "fixture", + "model", + "hosted-proj", + "ask-resources.json", + ); + + let infoStub: sinon.SinonStub; + let errorStub: sinon.SinonStub; + let warnStub: sinon.SinonStub; + + beforeEach(() => { + infoStub = sinon.stub(); + errorStub = sinon.stub(); + warnStub = sinon.stub(); + sinon.stub(Messenger, "getInstance").returns({ + info: infoStub, + error: errorStub, + warn: warnStub, + }); + }); + + afterEach(() => { + sinon.restore(); + }); + + it("| validate command information is set correctly", () => { + const instance = new GitCredentialsHelperCommand(optionModel as OptionModel); + expect(instance.name()).equal("git-credentials-helper"); + expect(instance.description()).equal("gets git credentials for hosted skill repository"); + expect(instance.requiredOptions()).deep.equal([]); + expect(instance.optionalOptions()).deep.equal(["profile", "debug"]); + }); + + describe("validate command handle", () => { + const TEST_CMD = { + profile: TEST_PROFILE, + debug: TEST_DEBUG, + }; + const TEST_ERROR_MESSAGE = "ERROR"; + const ERROR = new Error(TEST_ERROR_MESSAGE); + let instance: GitCredentialsHelperCommand; + let profileHelperRuntimeProfileStub: sinon.SinonStub; + beforeEach(() => { + profileHelperRuntimeProfileStub = sinon.stub(profileHelper, "runtimeProfile").returns(TEST_PROFILE); + instance = new GitCredentialsHelperCommand(optionModel as OptionModel); + new ResourcesConfig(FIXTURE_RESOURCES_CONFIG_FILE_PATH); + }); + + afterEach(() => { + sinon.restore(); + const repository = { + repository: { + type: "GIT", + url: "https://git-codecommit.us-east-1.amazonaws.com/v1/repos/5555555-4444-3333-2222-1111111111", + }, + }; + ResourcesConfig.getInstance().setSkillInfraDeployState(TEST_PROFILE, repository); + }); + + describe("command handle - before get git credentials", () => { + it("| when called from git and operation is not get, expect error out", async () => { + // setup + const remaining = ["not supported operation"]; + // call + const expectedErr = `The ask-cli git credentials helper doesn't support operation "${remaining[0]}".`; + + await expect(instance.handle(TEST_CMD, remaining)).rejectedWith(expectedErr); + + expect(errorStub).calledOnceWith(expectedErr); + expect(infoStub).not.called; + expect(warnStub).not.called; + }); + + it("| when called from git and operation is store, expect do nothing", async () => { + // setup + const remaining = ["store"]; + // call + await instance.handle(TEST_CMD, remaining); + //verify + expect(errorStub).not.called; + expect(infoStub).not.called; + expect(warnStub).not.called; + }); + + it("| when called from git and operation is erase, expect do nothing", async () => { + // setup + const remaining = ["erase"]; + // call + await instance.handle(TEST_CMD, remaining); + + expect(errorStub).not.called; + expect(infoStub).not.called; + expect(warnStub).not.called; + }); + + it("| when profile is not correct, expect throw error", async () => { + // setup + profileHelperRuntimeProfileStub.throws(new Error("error")); + // call + await expect(instance.handle(TEST_CMD, undefined)).eventually.rejected; + + // verify + expect(errorStub).calledOnceWith(sinon.match({message: "error"})); + expect(infoStub).not.called; + expect(warnStub).not.called; + }); + }); + + describe("command handle - request to get git credentials", () => { + beforeEach(() => { + sinon.stub(AuthorizationController.prototype, "tokenRefreshAndRead").callsArgWith(1); + }); + + it("| get git credentials fails, expect throw error", async () => { + // setup + sinon.stub(path, "join").returns(FIXTURE_RESOURCES_CONFIG_FILE_PATH); + sinon.stub(httpClient, "request").callsArgWith(3, ERROR); // stub getGitCredentials request + // call + await expect(instance.handle(TEST_CMD, undefined)).eventually.rejected; + // verify + expect(errorStub).calledOnceWith(sinon.match({message: TEST_ERROR_MESSAGE})); + expect(infoStub).not.called; + expect(warnStub).not.called; + }); + + it("| get git credentials response with status code >= 300, expect throw error", async () => { + // setup + const GET_STATUS_ERROR = { + statusCode: 403, + body: { + error: TEST_ERROR_MESSAGE, + }, + }; + sinon.stub(path, "join").returns(FIXTURE_RESOURCES_CONFIG_FILE_PATH); + sinon.stub(httpClient, "request").callsArgWith(3, null, GET_STATUS_ERROR); // stub getGitCredentials request + // call + await expect(instance.handle(TEST_CMD, undefined)).rejected; + //verify + expect(errorStub).calledOnceWith(jsonView.toString({error: TEST_ERROR_MESSAGE})); + }); + + it("| get git credentials succeed, expect correct output", async () => { + // setup + const TEST_STATUS_CODE = 200; + const TEST_USERNAME = "TEST_USERNAME"; + const TEST_PASSWORD = "TEST_PASSWORD"; + const GET_METADATA_RESPONSE = { + statusCode: TEST_STATUS_CODE, + headers: {}, + body: { + alexaHosted: { + repository: { + url: "test", + }, + }, + }, + }; + const GET_STATUS_RESPONSE = { + statusCode: TEST_STATUS_CODE, + headers: {}, + body: { + repositoryCredentials: { + username: TEST_USERNAME, + password: TEST_PASSWORD, + }, + }, + }; + sinon.stub(path, "join").returns(FIXTURE_RESOURCES_CONFIG_FILE_PATH); + + sinon + .stub(httpClient, "request") + .onFirstCall() + .yields(null, GET_METADATA_RESPONSE) + .onSecondCall() + .yields(null, GET_STATUS_RESPONSE); + + // call + await instance.handle(TEST_CMD, undefined); + //verify + expect(infoStub).calledOnceWith(`username=${TEST_USERNAME}\npassword=${TEST_PASSWORD}`); + }); + }); + }); +}); diff --git a/test/unit/commands/util/upgrade-project/helper-test.js b/test/unit/commands/util/upgrade-project/helper-test.js index 249c66f5..d8dd55ba 100644 --- a/test/unit/commands/util/upgrade-project/helper-test.js +++ b/test/unit/commands/util/upgrade-project/helper-test.js @@ -1,684 +1,707 @@ -const { expect } = require('chai'); -const R = require('ramda'); -const sinon = require('sinon'); -const fs = require('fs-extra'); -const path = require('path'); - -const awsUtil = require('@src/clients/aws-client/aws-util'); -const helper = require('@src/commands/util/upgrade-project/helper'); -const ui = require('@src/commands/util/upgrade-project/ui'); -const SkillMetadataController = require('@src/controllers/skill-metadata-controller'); -const CLiError = require('@src/exceptions/cli-error'); -const ResourcesConfig = require('@src/model/resources-config'); -const AskResources = require('@src/model/resources-config/ask-resources'); -const AskStates = require('@src/model/resources-config/ask-states'); -const Messenger = require('@src/view/messenger'); -const CONSTANTS = require('@src/utils/constants'); -const hashUtils = require('@src/utils/hash-utils'); - -describe('Commands upgrade-project test - helper test', () => { - const TEST_ERROR = 'testError'; - const TEST_PROFILE = 'default'; - const TEST_REGION = 'default'; - const TEST_REGION_NA = 'NA'; - const TEST_AWS_REGION = 'us-west-2'; - const TEST_DO_DEBUG = false; - const TEST_SKILL_ID = 'skillId'; - const TEST_SKILL_STAGE = 'development'; - const TEST_CODE_URI = 'codeUri'; - const TEST_V2_CODE_URI = path.join(CONSTANTS.FILE_PATH.SKILL_CODE.LAMBDA, TEST_CODE_URI); - const TEST_RUNTIME = 'runtime'; - const TEST_HANDLER = 'handler'; - const TEST_REVISION_ID = 'revisionId'; - const TEST_ROOT_PATH = 'rootPath'; - const TSET_SRC_DIR = 'sourceDir'; - const TEST_HIDDEN_NHS_CONFIG = { - deploy_settings: { - [TEST_PROFILE]: { - skill_id: TEST_SKILL_ID, - resources: { - lambda: [] - } - } - } - }; - const TEST_ARN = 'arn:aws:lambda:us-west-2:123456789012:function:ask-custom-skill-sample-nodejs-fact-default'; - const FIXTURE_RESOURCES_CONFIG_FILE_PATH = path.join(process.cwd(), 'test', 'unit', 'fixture', 'model', 'regular-proj', 'ask-resources.json'); - const FIXTURE_STATES_CONFIG_FILE_PATH = path.join(process.cwd(), 'test', 'unit', 'fixture', 'model', 'regular-proj', '.ask', 'ask-states.json'); - const TEST_LAMBDAS = [ - { - alexaUsage: ['custom/default'], - codeUri: TEST_CODE_URI, - runtime: TEST_RUNTIME, - handler: TEST_HANDLER, - revisionId: TEST_REVISION_ID - } - ]; - const TEST_RESOURCE_MAP = { - [TEST_REGION]: { - arn: TEST_ARN, - codeUri: TEST_CODE_URI, - runtime: TEST_RUNTIME, - handler: TEST_HANDLER, - v2CodeUri: `.${path.sep}${TEST_V2_CODE_URI}`, - revisionId: TEST_REVISION_ID +const {expect} = require("chai"); +const R = require("ramda"); +const sinon = require("sinon"); +const fs = require("fs-extra"); +const path = require("path"); + +const awsUtil = require("../../../../../lib/clients/aws-client/aws-util"); +const helper = require("../../../../../lib/commands/util/upgrade-project/helper"); +const ui = require("../../../../../lib/commands/util/upgrade-project/ui"); +const SkillMetadataController = require("../../../../../lib/controllers/skill-metadata-controller"); +const CLiError = require("../../../../../lib/exceptions/cli-error"); +const ResourcesConfig = require("../../../../../lib/model/resources-config"); +const AskResources = require("../../../../../lib/model/resources-config/ask-resources"); +const AskStates = require("../../../../../lib/model/resources-config/ask-states"); +const Messenger = require("../../../../../lib/view/messenger"); +const CONSTANTS = require("../../../../../lib/utils/constants"); +const hashUtils = require("../../../../../lib/utils/hash-utils"); + +describe("Commands upgrade-project test - helper test", () => { + const TEST_ERROR = "testError"; + const TEST_PROFILE = "default"; + const TEST_REGION = "default"; + const TEST_REGION_NA = "NA"; + const TEST_AWS_REGION = "us-west-2"; + const TEST_DO_DEBUG = false; + const TEST_SKILL_ID = "skillId"; + const TEST_SKILL_STAGE = "development"; + const TEST_CODE_URI = "codeUri"; + const TEST_V2_CODE_URI = path.join(CONSTANTS.FILE_PATH.SKILL_CODE.LAMBDA, TEST_CODE_URI); + const TEST_RUNTIME = "runtime"; + const TEST_HANDLER = "handler"; + const TEST_REVISION_ID = "revisionId"; + const TEST_ROOT_PATH = "rootPath"; + const TSET_SRC_DIR = "sourceDir"; + const TEST_HIDDEN_NHS_CONFIG = { + deploy_settings: { + [TEST_PROFILE]: { + skill_id: TEST_SKILL_ID, + resources: { + lambda: [], }, - [TEST_REGION_NA]: { - arn: undefined, - codeUri: TEST_CODE_URI, - runtime: undefined, - handler: undefined, - v2CodeUri: `.${path.sep}${TEST_V2_CODE_URI}`, - revisionId: undefined - } + }, + }, + }; + const TEST_ARN = "arn:aws:lambda:us-west-2:123456789012:function:ask-custom-skill-sample-nodejs-fact-default"; + const FIXTURE_RESOURCES_CONFIG_FILE_PATH = path.join( + process.cwd(), + "test", + "unit", + "fixture", + "model", + "regular-proj", + "ask-resources.json", + ); + const FIXTURE_STATES_CONFIG_FILE_PATH = path.join( + process.cwd(), + "test", + "unit", + "fixture", + "model", + "regular-proj", + ".ask", + "ask-states.json", + ); + const TEST_LAMBDAS = [ + { + alexaUsage: ["custom/default"], + codeUri: TEST_CODE_URI, + runtime: TEST_RUNTIME, + handler: TEST_HANDLER, + revisionId: TEST_REVISION_ID, + }, + ]; + const TEST_RESOURCE_MAP = { + [TEST_REGION]: { + arn: TEST_ARN, + codeUri: TEST_CODE_URI, + runtime: TEST_RUNTIME, + handler: TEST_HANDLER, + v2CodeUri: `.${path.sep}${TEST_V2_CODE_URI}`, + revisionId: TEST_REVISION_ID, + }, + [TEST_REGION_NA]: { + arn: undefined, + codeUri: TEST_CODE_URI, + runtime: undefined, + handler: undefined, + v2CodeUri: `.${path.sep}${TEST_V2_CODE_URI}`, + revisionId: undefined, + }, + }; + const TEST_PROTOCOL = "https"; + const TEST_HOST = "git-codecommit.us-west-2.amazonaws.com"; + const TEST_PATH = "v1/repos/11111111-2222-3333-4444-555555555555"; + const formV1Config = (skillId, isHosted, lambdaResources) => { + const result = {deploy_settings: {}, alexaHosted: {}}; + result.deploy_settings[TEST_PROFILE] = { + skill_id: skillId, + resources: { + lambda: lambdaResources, + }, }; - const TEST_PROTOCOL = 'https'; - const TEST_HOST = 'git-codecommit.us-west-2.amazonaws.com'; - const TEST_PATH = 'v1/repos/11111111-2222-3333-4444-555555555555'; - const formV1Config = (skillId, isHosted, lambdaResources) => { - const result = { deploy_settings: {}, alexaHosted: {} }; - result.deploy_settings[TEST_PROFILE] = { - skill_id: skillId, - resources: { - lambda: lambdaResources - } - }; - result.alexaHosted = { - isAlexaHostedSkill: isHosted, - gitCredentialsCache: { - protocol: TEST_PROTOCOL, - host: TEST_HOST, - path: TEST_PATH - } - }; - return result; + result.alexaHosted = { + isAlexaHostedSkill: isHosted, + gitCredentialsCache: { + protocol: TEST_PROTOCOL, + host: TEST_HOST, + path: TEST_PATH, + }, }; - const formSkillJson = (topField, apiCustom) => { - const result = { [topField]: {} }; - result[topField].apis = { - custom: apiCustom - }; - return result; + return result; + }; + const formSkillJson = (topField, apiCustom) => { + const result = {[topField]: {}}; + result[topField].apis = { + custom: apiCustom, }; + return result; + }; - describe('# test helper method - loadV1ProjConfig', () => { - beforeEach(() => { - sinon.stub(fs, 'existsSync').returns(true); - sinon.stub(fs, 'readJSONSync').returns(TEST_HIDDEN_NHS_CONFIG); - }); + describe("# test helper method - loadV1ProjConfig", () => { + beforeEach(() => { + sinon.stub(fs, "existsSync").returns(true); + sinon.stub(fs, "readJSONSync").returns(TEST_HIDDEN_NHS_CONFIG); + }); - afterEach(() => { - sinon.restore(); - }); + afterEach(() => { + sinon.restore(); + }); - it('| file does not exist, expect throw error', () => { - // setup - fs.existsSync.returns(false); - // call & verify - expect(() => helper.loadV1ProjConfig(TEST_ROOT_PATH, TEST_PROFILE)).throw(CLiError, - 'Failed to find ask-cli v1 project. Please make sure this command is called at the root of the skill project.'); - }); + it("| file does not exist, expect throw error", () => { + // setup + fs.existsSync.returns(false); + // call & verify + expect(() => helper.loadV1ProjConfig(TEST_ROOT_PATH, TEST_PROFILE)).throw( + CLiError, + "Failed to find ask-cli v1 project. Please make sure this command is called at the root of the skill project.", + ); + }); - it('| profile does not match, expect throw error', () => { - // setup - const TEST_DIFFERENT_PROFILE = 'different'; - // call & verify - expect(() => helper.loadV1ProjConfig(TEST_ROOT_PATH, TEST_DIFFERENT_PROFILE)).throw(CLiError, - `Profile [${TEST_DIFFERENT_PROFILE}] is not configured in the v1 ask-cli's project. \ -Please check ".ask/config" file and run again with the existing profile.`); - }); + it("| profile does not match, expect throw error", () => { + // setup + const TEST_DIFFERENT_PROFILE = "different"; + // call & verify + expect(() => helper.loadV1ProjConfig(TEST_ROOT_PATH, TEST_DIFFERENT_PROFILE)).throw( + CLiError, + `Profile [${TEST_DIFFERENT_PROFILE}] is not configured in the v1 ask-cli's project. \ +Please check ".ask/config" file and run again with the existing profile.`, + ); + }); - it('| expect idDeployed=false and v1Config get returned successfully', () => { - // call - fs.readJSONSync.returns(formV1Config(' ', false, [])); - const res = helper.loadV1ProjConfig(TEST_ROOT_PATH, TEST_PROFILE); - // verify - expect(res).deep.equal({ - isDeployed: false, - v1Config: formV1Config(' ', false, []) - }); - }); + it("| expect idDeployed=false and v1Config get returned successfully", () => { + // call + fs.readJSONSync.returns(formV1Config(" ", false, [])); + const res = helper.loadV1ProjConfig(TEST_ROOT_PATH, TEST_PROFILE); + // verify + expect(res).deep.equal({ + isDeployed: false, + v1Config: formV1Config(" ", false, []), + }); + }); - it('| expect idDeployed=true and v1Config get returned successfully', () => { - // call - const res = helper.loadV1ProjConfig(TEST_ROOT_PATH, TEST_PROFILE); - // verify - expect(res).deep.equal({ - isDeployed: true, - v1Config: TEST_HIDDEN_NHS_CONFIG - }); - }); + it("| expect idDeployed=true and v1Config get returned successfully", () => { + // call + const res = helper.loadV1ProjConfig(TEST_ROOT_PATH, TEST_PROFILE); + // verify + expect(res).deep.equal({ + isDeployed: true, + v1Config: TEST_HIDDEN_NHS_CONFIG, + }); }); + }); - describe('# test helper method - extractUpgradeInformation', () => { - beforeEach(() => { - sinon.stub(fs, 'existsSync').returns(true); - sinon.stub(fs, 'readJsonSync').returns({}); - }); + describe("# test helper method - extractUpgradeInformation", () => { + beforeEach(() => { + sinon.stub(fs, "existsSync").returns(true); + sinon.stub(fs, "readJsonSync").returns({}); + }); - afterEach(() => { - sinon.restore(); - }); + afterEach(() => { + sinon.restore(); + }); - it('| skill ID does not exist, expect throw error message', () => { - // setup - const TEST_CONFIG_OBJ = formV1Config(' ', false, {}); - // call & verify - expect(() => helper.extractUpgradeInformation(TEST_CONFIG_OBJ, TEST_PROFILE)).throw(CLiError, - `Failed to find skill_id for profile [${TEST_PROFILE}]. \ -If the skill has never been deployed in v1 ask-cli, please start from v2 structure.`); - }); + it("| skill ID does not exist, expect throw error message", () => { + // setup + const TEST_CONFIG_OBJ = formV1Config(" ", false, {}); + // call & verify + expect(() => helper.extractUpgradeInformation(TEST_CONFIG_OBJ, TEST_PROFILE)).throw( + CLiError, + `Failed to find skill_id for profile [${TEST_PROFILE}]. \ +If the skill has never been deployed in v1 ask-cli, please start from v2 structure.`, + ); + }); - it('| skill project is alexa hosted skill, expect result correctly', () => { - // setup - const TEST_CONFIG_OBJ = formV1Config(TEST_SKILL_ID, true, null); - // call - const info = helper.extractUpgradeInformation(TEST_CONFIG_OBJ, TEST_PROFILE); - // verify - expect(info).deep.equal({ - skillId: TEST_SKILL_ID, - isHosted: true, - gitRepoUrl: `${TEST_PROTOCOL}://${TEST_HOST}/${TEST_PATH}` - }); - }); + it("| skill project is alexa hosted skill, expect result correctly", () => { + // setup + const TEST_CONFIG_OBJ = formV1Config(TEST_SKILL_ID, true, null); + // call + const info = helper.extractUpgradeInformation(TEST_CONFIG_OBJ, TEST_PROFILE); + // verify + expect(info).deep.equal({ + skillId: TEST_SKILL_ID, + isHosted: true, + gitRepoUrl: `${TEST_PROTOCOL}://${TEST_HOST}/${TEST_PATH}`, + }); + }); - describe('test helper method - extractUpgradeInformation : _validateLambdaResource', () => { - [ - { - testCase: '| validate lambda resources fails at alexaUsage, expect throw error message', - lambdas: [ - { alexaUsage: [] } - ], - expectError: 'Please make sure your alexaUsage is not empty.' - }, - { - testCase: '| validate lambda resources fails at codeUri, expect throw error message', - lambdas: [ - { - alexaUsage: ['custom/default'], - codeUri: ' ' - } - ], - expectError: 'Please make sure your codeUri is set to the path of your Lambda code.' - }, - { - testCase: '| validate lambda resources fails at runtime, expect throw error message', - lambdas: [ - { - alexaUsage: ['custom/default'], - codeUri: TEST_CODE_URI, - runtime: ' ' - } - ], - expectError: `Please make sure your runtime for codeUri ${TEST_CODE_URI} is set.` - }, - { - testCase: '| validate lambda resources fails at handler, expect throw error message', - lambdas: [ - { - alexaUsage: ['custom/default'], - codeUri: TEST_CODE_URI, - runtime: TEST_RUNTIME, - handler: '' - } - ], - expectError: `Please make sure your handler for codeUri ${TEST_CODE_URI} is set.` - } - ].forEach(({ testCase, lambdas, expectError }) => { - it(testCase, () => { - // setup - const TEST_CONFIG_OBJ = formV1Config(TEST_SKILL_ID, false, lambdas); - // call & verify - expect(() => helper.extractUpgradeInformation(TEST_CONFIG_OBJ, TEST_PROFILE)).throw(CLiError, expectError); - }); - }); - }); + describe("test helper method - extractUpgradeInformation : _validateLambdaResource", () => { + [ + { + testCase: "| validate lambda resources fails at alexaUsage, expect throw error message", + lambdas: [{alexaUsage: []}], + expectError: "Please make sure your alexaUsage is not empty.", + }, + { + testCase: "| validate lambda resources fails at codeUri, expect throw error message", + lambdas: [ + { + alexaUsage: ["custom/default"], + codeUri: " ", + }, + ], + expectError: "Please make sure your codeUri is set to the path of your Lambda code.", + }, + { + testCase: "| validate lambda resources fails at runtime, expect throw error message", + lambdas: [ + { + alexaUsage: ["custom/default"], + codeUri: TEST_CODE_URI, + runtime: " ", + }, + ], + expectError: `Please make sure your runtime for codeUri ${TEST_CODE_URI} is set.`, + }, + { + testCase: "| validate lambda resources fails at handler, expect throw error message", + lambdas: [ + { + alexaUsage: ["custom/default"], + codeUri: TEST_CODE_URI, + runtime: TEST_RUNTIME, + handler: "", + }, + ], + expectError: `Please make sure your handler for codeUri ${TEST_CODE_URI} is set.`, + }, + ].forEach(({testCase, lambdas, expectError}) => { + it(testCase, () => { + // setup + const TEST_CONFIG_OBJ = formV1Config(TEST_SKILL_ID, false, lambdas); + // call & verify + expect(() => helper.extractUpgradeInformation(TEST_CONFIG_OBJ, TEST_PROFILE)).throw(CLiError, expectError); + }); + }); + }); - describe('test helper method - extractUpgradeInformation : _collectLambdaMapFromResource', () => { - let warnStub; - - beforeEach(() => { - warnStub = sinon.stub(); - sinon.stub(Messenger, 'getInstance').returns({ - warn: warnStub - }); - }); - - it('| when no Lambda ARN exists, skip the upgrade with a warning message', () => { - // setup - const TEST_CONFIG_OBJ = formV1Config(TEST_SKILL_ID, false, TEST_LAMBDAS); - // call - const info = helper.extractUpgradeInformation(TEST_CONFIG_OBJ, TEST_PROFILE); - // verify - expect(warnStub.args[0][0]).equal('Skip Lambda resource with alexaUsage "custom/default" since this Lambda is not deployed.'); - expect(info).deep.equal({ - skillId: TEST_SKILL_ID, - lambdaResources: {} - }); - }); - - it('| Lambda ARN exists, multiple codebase for a single region, expect result return', () => { - // setup - const TEST_LAMBDAS_MULTIPLE_CODEBASE = [ - { - alexaUsage: ['custom/default', 'custom/NA'], - arn: TEST_ARN, - codeUri: TEST_CODE_URI, - runtime: TEST_RUNTIME, - handler: TEST_HANDLER, - revisionId: TEST_REVISION_ID - }, - { - alexaUsage: ['custom/default'], - arn: TEST_ARN, - codeUri: TEST_CODE_URI, - runtime: TEST_RUNTIME, - handler: TEST_HANDLER, - revisionId: TEST_REVISION_ID - }, - { - alexaUsage: ['custom/default'], - arn: TEST_ARN, - codeUri: 'codeUri1', - runtime: TEST_RUNTIME, - handler: TEST_HANDLER, - revisionId: TEST_REVISION_ID - } - ]; - const TEST_CONFIG_OBJ = formV1Config(TEST_SKILL_ID, false, TEST_LAMBDAS_MULTIPLE_CODEBASE); - // call - const info = helper.extractUpgradeInformation(TEST_CONFIG_OBJ, TEST_PROFILE); - // verify - expect(warnStub.args[0][0]).equal(`Currently ask-cli requires one Lambda codebase per region. \ + describe("test helper method - extractUpgradeInformation : _collectLambdaMapFromResource", () => { + let warnStub; + + beforeEach(() => { + warnStub = sinon.stub(); + sinon.stub(Messenger, "getInstance").returns({ + warn: warnStub, + }); + }); + + it("| when no Lambda ARN exists, skip the upgrade with a warning message", () => { + // setup + const TEST_CONFIG_OBJ = formV1Config(TEST_SKILL_ID, false, TEST_LAMBDAS); + // call + const info = helper.extractUpgradeInformation(TEST_CONFIG_OBJ, TEST_PROFILE); + // verify + expect(warnStub.args[0][0]).equal('Skip Lambda resource with alexaUsage "custom/default" since this Lambda is not deployed.'); + expect(info).deep.equal({ + skillId: TEST_SKILL_ID, + lambdaResources: {}, + }); + }); + + it("| Lambda ARN exists, multiple codebase for a single region, expect result return", () => { + // setup + const TEST_LAMBDAS_MULTIPLE_CODEBASE = [ + { + alexaUsage: ["custom/default", "custom/NA"], + arn: TEST_ARN, + codeUri: TEST_CODE_URI, + runtime: TEST_RUNTIME, + handler: TEST_HANDLER, + revisionId: TEST_REVISION_ID, + }, + { + alexaUsage: ["custom/default"], + arn: TEST_ARN, + codeUri: TEST_CODE_URI, + runtime: TEST_RUNTIME, + handler: TEST_HANDLER, + revisionId: TEST_REVISION_ID, + }, + { + alexaUsage: ["custom/default"], + arn: TEST_ARN, + codeUri: "codeUri1", + runtime: TEST_RUNTIME, + handler: TEST_HANDLER, + revisionId: TEST_REVISION_ID, + }, + ]; + const TEST_CONFIG_OBJ = formV1Config(TEST_SKILL_ID, false, TEST_LAMBDAS_MULTIPLE_CODEBASE); + // call + const info = helper.extractUpgradeInformation(TEST_CONFIG_OBJ, TEST_PROFILE); + // verify + expect(warnStub.args[0][0]).equal(`Currently ask-cli requires one Lambda codebase per region. \ You have multiple Lambda codebases for region ${TEST_REGION}, we will use "${TEST_CODE_URI}" as the codebase for this region.`); - expect(info).deep.equal({ - skillId: TEST_SKILL_ID, - lambdaResources: TEST_RESOURCE_MAP - }); - }); + expect(info).deep.equal({ + skillId: TEST_SKILL_ID, + lambdaResources: TEST_RESOURCE_MAP, }); + }); }); + }); - describe('# test helper method - previewUpgrade', () => { - const TEST_UPGRADE_INFO = {}; - afterEach(() => { - sinon.restore(); - }); - - it('| user not confirm upgrade, expect result return', (done) => { - // setup - sinon.stub(ui, 'displayPreview'); - sinon.stub(ui, 'confirmPreview').callsArgWith(0, TEST_ERROR); - // call - helper.previewUpgrade(TEST_UPGRADE_INFO, (err, res) => { - // verify - expect(err).equal(TEST_ERROR); - expect(res).equal(null); - done(); - }); - }); + describe("# test helper method - previewUpgrade", () => { + const TEST_UPGRADE_INFO = {}; + afterEach(() => { + sinon.restore(); + }); - it('| user confirm upgrade, expect result return', (done) => { - // setup - sinon.stub(ui, 'displayPreview'); - sinon.stub(ui, 'confirmPreview').callsArgWith(0, null, true); - // call - helper.previewUpgrade(TEST_UPGRADE_INFO, (err, res) => { - // verify - expect(err).equal(null); - expect(res).equal(true); - done(); - }); - }); + it("| user not confirm upgrade, expect result return", (done) => { + // setup + sinon.stub(ui, "displayPreview"); + sinon.stub(ui, "confirmPreview").callsArgWith(0, TEST_ERROR); + // call + helper.previewUpgrade(TEST_UPGRADE_INFO, (err, res) => { + // verify + expect(err).equal(TEST_ERROR); + expect(res).equal(null); + done(); + }); }); - describe('# test helper method - moveOldProjectToLegacyFolder', () => { - const TEST_FILE = 'file'; - const TEST_GIT_FILE = '.git'; - const TEST_OLD_FILES = [TEST_FILE, TEST_GIT_FILE]; + it("| user confirm upgrade, expect result return", (done) => { + // setup + sinon.stub(ui, "displayPreview"); + sinon.stub(ui, "confirmPreview").callsArgWith(0, null, true); + // call + helper.previewUpgrade(TEST_UPGRADE_INFO, (err, res) => { + // verify + expect(err).equal(null); + expect(res).equal(true); + done(); + }); + }); + }); - afterEach(() => { - sinon.restore(); - }); + describe("# test helper method - moveOldProjectToLegacyFolder", () => { + const TEST_FILE = "file"; + const TEST_GIT_FILE = ".git"; + const TEST_OLD_FILES = [TEST_FILE, TEST_GIT_FILE]; - it('| move old project to legacy folder, expect files\' path correctly', () => { - // setup - sinon.stub(fs, 'readdirSync').returns(TEST_OLD_FILES); - sinon.stub(fs, 'ensureDirSync'); - const moveStub = sinon.stub(fs, 'moveSync'); - // call - helper.moveOldProjectToLegacyFolder(TEST_ROOT_PATH); - // verify - expect(moveStub.args[0][0]).eq(TEST_FILE); - expect(moveStub.args[0][1]).eq(path.join(TEST_ROOT_PATH, CONSTANTS.FILE_PATH.LEGACY_PATH, TEST_FILE)); - }); + afterEach(() => { + sinon.restore(); }); - describe('# test helper method - createV2ProjectSkeletonAndLoadModel', () => { - beforeEach(() => { - sinon.stub(path, 'join'); - path.join.withArgs( - TEST_ROOT_PATH, CONSTANTS.FILE_PATH.ASK_RESOURCES_JSON_CONFIG - ).returns(FIXTURE_RESOURCES_CONFIG_FILE_PATH); - path.join.withArgs( - TEST_ROOT_PATH, CONSTANTS.FILE_PATH.HIDDEN_ASK_FOLDER, CONSTANTS.FILE_PATH.ASK_STATES_JSON_CONFIG - ).returns(FIXTURE_STATES_CONFIG_FILE_PATH); - path.join.callThrough(); - }); - - afterEach(() => { - sinon.restore(); - }); + it("| move old project to legacy folder, expect files' path correctly", () => { + // setup + sinon.stub(fs, "readdirSync").returns(TEST_OLD_FILES); + sinon.stub(fs, "ensureDirSync"); + const moveStub = sinon.stub(fs, "moveSync"); + // call + helper.moveOldProjectToLegacyFolder(TEST_ROOT_PATH); + // verify + expect(moveStub.args[0][0]).eq(TEST_FILE); + expect(moveStub.args[0][1]).eq(path.join(TEST_ROOT_PATH, CONSTANTS.FILE_PATH.LEGACY_PATH, TEST_FILE)); + }); + }); + + describe("# test helper method - createV2ProjectSkeletonAndLoadModel", () => { + beforeEach(() => { + sinon.stub(path, "join"); + path.join.withArgs(TEST_ROOT_PATH, CONSTANTS.FILE_PATH.ASK_RESOURCES_JSON_CONFIG).returns(FIXTURE_RESOURCES_CONFIG_FILE_PATH); + path.join + .withArgs(TEST_ROOT_PATH, CONSTANTS.FILE_PATH.HIDDEN_ASK_FOLDER, CONSTANTS.FILE_PATH.ASK_STATES_JSON_CONFIG) + .returns(FIXTURE_STATES_CONFIG_FILE_PATH); + path.join.callThrough(); + }); - it('| crate v2 project skeleton, expect write JSON file correctly', () => { - // setup - const ensureDirStub = sinon.stub(fs, 'ensureDirSync'); - sinon.stub(AskResources, 'withContent'); - sinon.stub(AskStates, 'withContent'); - // call - helper.createV2ProjectSkeletonAndLoadModel(TEST_ROOT_PATH, TEST_SKILL_ID, TEST_PROFILE); - expect(ensureDirStub.args[0][0]).eq(path.join(TEST_ROOT_PATH, CONSTANTS.FILE_PATH.SKILL_PACKAGE.PACKAGE)); - expect(ensureDirStub.args[1][0]).eq(path.join(TEST_ROOT_PATH, CONSTANTS.FILE_PATH.SKILL_CODE.LAMBDA)); - - expect(AskResources.withContent.args[0][0]).eq(FIXTURE_RESOURCES_CONFIG_FILE_PATH); - expect(AskResources.withContent.args[0][1].profiles).deep.equal({ - [TEST_PROFILE]: { - skillMetadata: {}, - code: {} - } - }); - expect(AskStates.withContent.args[0][0]).eq(FIXTURE_STATES_CONFIG_FILE_PATH); - expect(AskStates.withContent.args[0][1].profiles).deep.equal({ - [TEST_PROFILE]: { - skillId: TEST_SKILL_ID, - skillMetadata: {}, - code: {} - } - }); - }); + afterEach(() => { + sinon.restore(); }); - describe('# test helper method - downloadSkillPackage', () => { - beforeEach(() => { - new ResourcesConfig(FIXTURE_RESOURCES_CONFIG_FILE_PATH); - sinon.stub(ResourcesConfig.prototype, 'write'); - }); + it("| crate v2 project skeleton, expect write JSON file correctly", () => { + // setup + const ensureDirStub = sinon.stub(fs, "ensureDirSync"); + sinon.stub(AskResources, "withContent"); + sinon.stub(AskStates, "withContent"); + // call + helper.createV2ProjectSkeletonAndLoadModel(TEST_ROOT_PATH, TEST_SKILL_ID, TEST_PROFILE); + expect(ensureDirStub.args[0][0]).eq(path.join(TEST_ROOT_PATH, CONSTANTS.FILE_PATH.SKILL_PACKAGE.PACKAGE)); + expect(ensureDirStub.args[1][0]).eq(path.join(TEST_ROOT_PATH, CONSTANTS.FILE_PATH.SKILL_CODE.LAMBDA)); + + expect(AskResources.withContent.args[0][0]).eq(FIXTURE_RESOURCES_CONFIG_FILE_PATH); + expect(AskResources.withContent.args[0][1].profiles).deep.equal({ + [TEST_PROFILE]: { + skillMetadata: {}, + code: {}, + }, + }); + expect(AskStates.withContent.args[0][0]).eq(FIXTURE_STATES_CONFIG_FILE_PATH); + expect(AskStates.withContent.args[0][1].profiles).deep.equal({ + [TEST_PROFILE]: { + skillId: TEST_SKILL_ID, + skillMetadata: {}, + code: {}, + }, + }); + }); + }); - afterEach(() => { - sinon.restore(); - ResourcesConfig.dispose(); - }); + describe("# test helper method - downloadSkillPackage", () => { + beforeEach(() => { + new ResourcesConfig(FIXTURE_RESOURCES_CONFIG_FILE_PATH); + sinon.stub(ResourcesConfig.prototype, "write"); + }); - it('| skillMetaController getSkillPackage fails, expect callback error', (done) => { - // setup - sinon.stub(SkillMetadataController.prototype, 'getSkillPackage').callsArgWith(3, TEST_ERROR); - // call - helper.downloadSkillPackage(TEST_ROOT_PATH, TEST_SKILL_ID, TEST_SKILL_STAGE, TEST_PROFILE, TEST_DO_DEBUG, (err) => { - expect(err.includes(TEST_ERROR)).equal(true); - done(); - }); - }); + afterEach(() => { + sinon.restore(); + ResourcesConfig.dispose(); + }); - it('| skillMetaController getSkillPackage passes, hashUtils fails, expect error return', (done) => { - // setup - sinon.stub(SkillMetadataController.prototype, 'getSkillPackage').callsArgWith(3, null); - sinon.stub(hashUtils, 'getHash').callsArgWith(1, TEST_ERROR); - // call - helper.downloadSkillPackage(TEST_ROOT_PATH, TEST_SKILL_ID, TEST_SKILL_STAGE, TEST_PROFILE, TEST_DO_DEBUG, (err) => { - // verify - expect(err).equal(TEST_ERROR); - done(); - }); - }); + it("| skillMetaController getSkillPackage fails, expect callback error", (done) => { + // setup + sinon.stub(SkillMetadataController.prototype, "getSkillPackage").callsArgWith(3, TEST_ERROR); + // call + helper.downloadSkillPackage(TEST_ROOT_PATH, TEST_SKILL_ID, TEST_SKILL_STAGE, TEST_PROFILE, TEST_DO_DEBUG, (err) => { + expect(err.includes(TEST_ERROR)).equal(true); + done(); + }); + }); - it('| hashUtils passes, expect no error return', (done) => { - // setup - const TEST_HASH = 'hash'; - sinon.stub(SkillMetadataController.prototype, 'getSkillPackage').callsArgWith(3, null); - sinon.stub(hashUtils, 'getHash').callsArgWith(1, null, TEST_HASH); - // call - helper.downloadSkillPackage(TEST_ROOT_PATH, TEST_SKILL_ID, TEST_SKILL_STAGE, TEST_PROFILE, TEST_DO_DEBUG, (err) => { - // verify - expect(err).eq(undefined); - expect(ResourcesConfig.getInstance().getSkillMetaSrc(TEST_PROFILE)).equal('./skill-package'); - expect(ResourcesConfig.getInstance().getSkillMetaLastDeployHash(TEST_PROFILE)).equal(TEST_HASH); - expect(ResourcesConfig.prototype.write.callCount).to.equal(1); - done(); - }); - }); + it("| skillMetaController getSkillPackage passes, hashUtils fails, expect error return", (done) => { + // setup + sinon.stub(SkillMetadataController.prototype, "getSkillPackage").callsArgWith(3, null); + sinon.stub(hashUtils, "getHash").callsArgWith(1, TEST_ERROR); + // call + helper.downloadSkillPackage(TEST_ROOT_PATH, TEST_SKILL_ID, TEST_SKILL_STAGE, TEST_PROFILE, TEST_DO_DEBUG, (err) => { + // verify + expect(err).equal(TEST_ERROR); + done(); + }); }); - describe('# test helper method - handleExistingLambdaCode', () => { - beforeEach(() => { - new ResourcesConfig(FIXTURE_RESOURCES_CONFIG_FILE_PATH); - sinon.stub(ResourcesConfig.prototype, 'write'); - }); + it("| hashUtils passes, expect no error return", (done) => { + // setup + const TEST_HASH = "hash"; + sinon.stub(SkillMetadataController.prototype, "getSkillPackage").callsArgWith(3, null); + sinon.stub(hashUtils, "getHash").callsArgWith(1, null, TEST_HASH); + // call + helper.downloadSkillPackage(TEST_ROOT_PATH, TEST_SKILL_ID, TEST_SKILL_STAGE, TEST_PROFILE, TEST_DO_DEBUG, (err) => { + // verify + expect(err).eq(undefined); + expect(ResourcesConfig.getInstance().getSkillMetaSrc(TEST_PROFILE)).equal("./skill-package"); + expect(ResourcesConfig.getInstance().getSkillMetaLastDeployHash(TEST_PROFILE)).equal(TEST_HASH); + expect(ResourcesConfig.prototype.write.callCount).to.equal(1); + done(); + }); + }); + }); - afterEach(() => { - sinon.restore(); - ResourcesConfig.dispose(); - }); + describe("# test helper method - handleExistingLambdaCode", () => { + beforeEach(() => { + new ResourcesConfig(FIXTURE_RESOURCES_CONFIG_FILE_PATH); + sinon.stub(ResourcesConfig.prototype, "write"); + }); - it('| handle lambdaCode and update resources JSON file, expect update correctly', () => { - // setup - const TEST_CONFIG = { - runtime: TEST_RUNTIME, - handler: TEST_HANDLER, - awsRegion: TEST_AWS_REGION, - regionalOverrides: { - NA: { - runtime: undefined, - handler: undefined - } - } - }; - sinon.stub(awsUtil, 'getAWSProfile'); - sinon.stub(awsUtil, 'getCLICompatibleDefaultRegion').returns(TEST_AWS_REGION); - const copyStub = sinon.stub(fs, 'copySync'); - // call - helper.handleExistingLambdaCode(TEST_ROOT_PATH, TEST_RESOURCE_MAP, TEST_PROFILE); - // verify - expect(ResourcesConfig.getInstance().getSkillInfraType(TEST_PROFILE)).deep.equal(CONSTANTS.DEPLOYER_TYPE.LAMBDA.NAME); - expect(ResourcesConfig.getInstance().getSkillInfraUserConfig(TEST_PROFILE)).deep.equal(TEST_CONFIG); - expect(copyStub.args[0][0]).equal(path.join(TEST_ROOT_PATH, CONSTANTS.FILE_PATH.LEGACY_PATH, TEST_CODE_URI)); - expect(copyStub.args[0][1]).equal(path.join(TEST_ROOT_PATH, TEST_V2_CODE_URI)); - expect(ResourcesConfig.getInstance().getSkillInfraDeployState(TEST_PROFILE)[TEST_PROFILE].lambda.arn).deep.equal(TEST_ARN); - expect(ResourcesConfig.prototype.write.callCount).to.equal(1); - }); + afterEach(() => { + sinon.restore(); + ResourcesConfig.dispose(); + }); - it('| handle lambdaCode and update resources JSON file with overwrite, expect, expect update correctly', () => { - // setup - const TEST_RESOURCE_MAP_MULTIPLE_REGION = { - [TEST_REGION]: { - arn: TEST_ARN, - codeUri: TEST_CODE_URI, - runtime: TEST_RUNTIME, - handler: TEST_HANDLER, - v2CodeUri: TEST_V2_CODE_URI, - revisionId: TEST_REVISION_ID - }, - [TEST_REGION_NA]: { - arn: TEST_ARN, - codeUri: TEST_CODE_URI, - runtime: TEST_RUNTIME, - handler: TEST_HANDLER, - v2CodeUri: TEST_V2_CODE_URI, - revisionId: TEST_REVISION_ID - }, - FE: { - arn: TEST_ARN, - codeUri: TEST_CODE_URI, - runtime: 'JAVA', - handler: 'index.js', - v2CodeUri: TEST_V2_CODE_URI, - revisionId: TEST_REVISION_ID - }, - IN: { - arn: TEST_ARN, - codeUri: TEST_CODE_URI, - runtime: 'JAVA', - handler: 'index.js', - v2CodeUri: TEST_V2_CODE_URI, - revisionId: TEST_REVISION_ID - } - }; - // setup - const TEST_CONFIG = { - runtime: TEST_RUNTIME, - handler: TEST_HANDLER, - awsRegion: TEST_AWS_REGION, - regionalOverrides: { - FE: { - handler: 'index.js', - runtime: 'JAVA' - }, - IN: { - handler: 'index.js', - runtime: 'JAVA' - } - } - }; - sinon.stub(awsUtil, 'getAWSProfile'); - sinon.stub(awsUtil, 'getCLICompatibleDefaultRegion').returns(TEST_AWS_REGION); - const copyStub = sinon.stub(fs, 'copySync'); - // call - helper.handleExistingLambdaCode(TEST_ROOT_PATH, TEST_RESOURCE_MAP_MULTIPLE_REGION, TEST_PROFILE); - // verify - expect(ResourcesConfig.getInstance().getSkillInfraType(TEST_PROFILE)).deep.equal(CONSTANTS.DEPLOYER_TYPE.LAMBDA.NAME); - expect(copyStub.args[0][0]).equal(path.join(TEST_ROOT_PATH, CONSTANTS.FILE_PATH.LEGACY_PATH, TEST_CODE_URI)); - expect(copyStub.args[0][1]).equal(path.join(TEST_ROOT_PATH, TEST_V2_CODE_URI)); - expect(ResourcesConfig.getInstance().getSkillInfraDeployState(TEST_PROFILE)[TEST_PROFILE].lambda.arn).deep.equal(TEST_ARN); - expect(ResourcesConfig.getInstance().getSkillInfraUserConfig(TEST_PROFILE)).deep.equal(TEST_CONFIG); - expect(ResourcesConfig.prototype.write.callCount).to.equal(1); - }); + it("| handle lambdaCode and update resources JSON file, expect update correctly", () => { + // setup + const TEST_CONFIG = { + runtime: TEST_RUNTIME, + handler: TEST_HANDLER, + awsRegion: TEST_AWS_REGION, + regionalOverrides: { + NA: { + runtime: undefined, + handler: undefined, + }, + }, + }; + sinon.stub(awsUtil, "getAWSProfile"); + sinon.stub(awsUtil, "getCLICompatibleDefaultRegion").returns(TEST_AWS_REGION); + const copyStub = sinon.stub(fs, "copySync"); + // call + helper.handleExistingLambdaCode(TEST_ROOT_PATH, TEST_RESOURCE_MAP, TEST_PROFILE); + // verify + expect(ResourcesConfig.getInstance().getSkillInfraType(TEST_PROFILE)).deep.equal(CONSTANTS.DEPLOYER_TYPE.LAMBDA.NAME); + expect(ResourcesConfig.getInstance().getSkillInfraUserConfig(TEST_PROFILE)).deep.equal(TEST_CONFIG); + expect(copyStub.args[0][0]).equal(path.join(TEST_ROOT_PATH, CONSTANTS.FILE_PATH.LEGACY_PATH, TEST_CODE_URI)); + expect(copyStub.args[0][1]).equal(path.join(TEST_ROOT_PATH, TEST_V2_CODE_URI)); + expect(ResourcesConfig.getInstance().getSkillInfraDeployState(TEST_PROFILE)[TEST_PROFILE].lambda.arn).deep.equal(TEST_ARN); + expect(ResourcesConfig.prototype.write.callCount).to.equal(1); }); - describe('# test helper method - attemptUpgradeUndeployedProject', () => { - beforeEach(() => { - sinon.stub(fs, 'existsSync'); - fs.existsSync.withArgs(path.join(TEST_ROOT_PATH, CONSTANTS.FILE_PATH.SKILL_PACKAGE.MANIFEST)).returns(true); - fs.existsSync.withArgs(path.join(TEST_ROOT_PATH, 'models')).returns(true); - fs.existsSync.withArgs(path.join(TEST_ROOT_PATH, 'isps')).returns(true); - fs.existsSync.callThrough(); - sinon.stub(fs, 'readJSONSync').returns(formSkillJson('manifest', { endpoint: TEST_ARN })); - sinon.stub(fs, 'removeSync'); - sinon.stub(fs, 'writeJSONSync'); - sinon.stub(fs, 'mkdirpSync'); - sinon.stub(fs, 'moveSync'); - sinon.stub(awsUtil, 'getAWSProfile').returns('doesnt matter'); - sinon.stub(awsUtil, 'getCLICompatibleDefaultRegion').returns(TEST_AWS_REGION); - }); + it("| handle lambdaCode and update resources JSON file with overwrite, expect, expect update correctly", () => { + // setup + const TEST_RESOURCE_MAP_MULTIPLE_REGION = { + [TEST_REGION]: { + arn: TEST_ARN, + codeUri: TEST_CODE_URI, + runtime: TEST_RUNTIME, + handler: TEST_HANDLER, + v2CodeUri: TEST_V2_CODE_URI, + revisionId: TEST_REVISION_ID, + }, + [TEST_REGION_NA]: { + arn: TEST_ARN, + codeUri: TEST_CODE_URI, + runtime: TEST_RUNTIME, + handler: TEST_HANDLER, + v2CodeUri: TEST_V2_CODE_URI, + revisionId: TEST_REVISION_ID, + }, + FE: { + arn: TEST_ARN, + codeUri: TEST_CODE_URI, + runtime: "JAVA", + handler: "index.js", + v2CodeUri: TEST_V2_CODE_URI, + revisionId: TEST_REVISION_ID, + }, + IN: { + arn: TEST_ARN, + codeUri: TEST_CODE_URI, + runtime: "JAVA", + handler: "index.js", + v2CodeUri: TEST_V2_CODE_URI, + revisionId: TEST_REVISION_ID, + }, + }; + // setup + const TEST_CONFIG = { + runtime: TEST_RUNTIME, + handler: TEST_HANDLER, + awsRegion: TEST_AWS_REGION, + regionalOverrides: { + FE: { + handler: "index.js", + runtime: "JAVA", + }, + IN: { + handler: "index.js", + runtime: "JAVA", + }, + }, + }; + sinon.stub(awsUtil, "getAWSProfile"); + sinon.stub(awsUtil, "getCLICompatibleDefaultRegion").returns(TEST_AWS_REGION); + const copyStub = sinon.stub(fs, "copySync"); + // call + helper.handleExistingLambdaCode(TEST_ROOT_PATH, TEST_RESOURCE_MAP_MULTIPLE_REGION, TEST_PROFILE); + // verify + expect(ResourcesConfig.getInstance().getSkillInfraType(TEST_PROFILE)).deep.equal(CONSTANTS.DEPLOYER_TYPE.LAMBDA.NAME); + expect(copyStub.args[0][0]).equal(path.join(TEST_ROOT_PATH, CONSTANTS.FILE_PATH.LEGACY_PATH, TEST_CODE_URI)); + expect(copyStub.args[0][1]).equal(path.join(TEST_ROOT_PATH, TEST_V2_CODE_URI)); + expect(ResourcesConfig.getInstance().getSkillInfraDeployState(TEST_PROFILE)[TEST_PROFILE].lambda.arn).deep.equal(TEST_ARN); + expect(ResourcesConfig.getInstance().getSkillInfraUserConfig(TEST_PROFILE)).deep.equal(TEST_CONFIG); + expect(ResourcesConfig.prototype.write.callCount).to.equal(1); + }); + }); + + describe("# test helper method - attemptUpgradeUndeployedProject", () => { + beforeEach(() => { + sinon.stub(fs, "existsSync"); + fs.existsSync.withArgs(path.join(TEST_ROOT_PATH, CONSTANTS.FILE_PATH.SKILL_PACKAGE.MANIFEST)).returns(true); + fs.existsSync.withArgs(path.join(TEST_ROOT_PATH, "models")).returns(true); + fs.existsSync.withArgs(path.join(TEST_ROOT_PATH, "isps")).returns(true); + fs.existsSync.callThrough(); + sinon.stub(fs, "readJSONSync").returns(formSkillJson("manifest", {endpoint: TEST_ARN})); + sinon.stub(fs, "removeSync"); + sinon.stub(fs, "writeJSONSync"); + sinon.stub(fs, "mkdirpSync"); + sinon.stub(fs, "moveSync"); + sinon.stub(awsUtil, "getAWSProfile").returns("doesnt matter"); + sinon.stub(awsUtil, "getCLICompatibleDefaultRegion").returns(TEST_AWS_REGION); + }); - afterEach(() => { - sinon.restore(); - }); + afterEach(() => { + sinon.restore(); + }); - it('| skill.json file does not exist, expect throw error message', () => { - // setup - fs.existsSync.withArgs(path.join(TEST_ROOT_PATH, CONSTANTS.FILE_PATH.SKILL_PACKAGE.MANIFEST)).returns(false); - // call - try { - helper.attemptUpgradeUndeployedProject(TEST_ROOT_PATH, TEST_HIDDEN_NHS_CONFIG, TEST_PROFILE); - } catch (e) { - // verify - expect(e.message).equal('Unable to upgrade the project. skill.json file must exist.'); - } - }); + it("| skill.json file does not exist, expect throw error message", () => { + // setup + fs.existsSync.withArgs(path.join(TEST_ROOT_PATH, CONSTANTS.FILE_PATH.SKILL_PACKAGE.MANIFEST)).returns(false); + // call + try { + helper.attemptUpgradeUndeployedProject(TEST_ROOT_PATH, TEST_HIDDEN_NHS_CONFIG, TEST_PROFILE); + } catch (e) { + // verify + expect(e.message).equal("Unable to upgrade the project. skill.json file must exist."); + } + }); - it('| skill.json file does not exist, expect throw error message', () => { - // setup - fs.readJSONSync.returns(formSkillJson('skillManifest', {})); - // call - try { - helper.attemptUpgradeUndeployedProject(TEST_ROOT_PATH, TEST_HIDDEN_NHS_CONFIG, TEST_PROFILE); - } catch (e) { - // verify - expect(e.message).equal('Invalid v1 project without "apis.custom.endpoint" field set in skill.json.'); - } - }); + it("| skill.json file does not exist, expect throw error message", () => { + // setup + fs.readJSONSync.returns(formSkillJson("skillManifest", {})); + // call + try { + helper.attemptUpgradeUndeployedProject(TEST_ROOT_PATH, TEST_HIDDEN_NHS_CONFIG, TEST_PROFILE); + } catch (e) { + // verify + expect(e.message).equal('Invalid v1 project without "apis.custom.endpoint" field set in skill.json.'); + } + }); - it('| v1Config does not have lambdaResources, models and isps folder do not exist, expect upgrade succeeds', () => { - // setup - fs.existsSync.withArgs(path.join(TEST_ROOT_PATH, 'models')).returns(false); - fs.existsSync.withArgs(path.join(TEST_ROOT_PATH, 'isps')).returns(false); - const NO_LAMBDA_V1CONFIG = formV1Config(TEST_SKILL_ID, false, null); - // call - helper.attemptUpgradeUndeployedProject(TEST_ROOT_PATH, NO_LAMBDA_V1CONFIG, TEST_PROFILE); - // verify - expect(fs.removeSync.args[0][0]).equal(path.join(TEST_ROOT_PATH, CONSTANTS.FILE_PATH.HIDDEN_ASK_FOLDER)); - expect(fs.removeSync.args[1][0]).equal(path.join(TEST_ROOT_PATH, 'hooks')); - expect(fs.removeSync.args[2][0]).equal(path.join(TEST_ROOT_PATH, CONSTANTS.FILE_PATH.SKILL_PACKAGE.MANIFEST)); - expect(fs.writeJSONSync.args[0][0]).equal(path.join(TEST_ROOT_PATH, CONSTANTS.FILE_PATH.ASK_RESOURCES_JSON_CONFIG)); - expect(fs.writeJSONSync.args[1][0]).equal( - path.join(TEST_ROOT_PATH, CONSTANTS.FILE_PATH.SKILL_PACKAGE.PACKAGE, CONSTANTS.FILE_PATH.SKILL_PACKAGE.MANIFEST) - ); - expect(fs.moveSync.callCount).equal(0); - }); + it("| v1Config does not have lambdaResources, models and isps folder do not exist, expect upgrade succeeds", () => { + // setup + fs.existsSync.withArgs(path.join(TEST_ROOT_PATH, "models")).returns(false); + fs.existsSync.withArgs(path.join(TEST_ROOT_PATH, "isps")).returns(false); + const NO_LAMBDA_V1CONFIG = formV1Config(TEST_SKILL_ID, false, null); + // call + helper.attemptUpgradeUndeployedProject(TEST_ROOT_PATH, NO_LAMBDA_V1CONFIG, TEST_PROFILE); + // verify + expect(fs.removeSync.args[0][0]).equal(path.join(TEST_ROOT_PATH, CONSTANTS.FILE_PATH.HIDDEN_ASK_FOLDER)); + expect(fs.removeSync.args[1][0]).equal(path.join(TEST_ROOT_PATH, "hooks")); + expect(fs.removeSync.args[2][0]).equal(path.join(TEST_ROOT_PATH, CONSTANTS.FILE_PATH.SKILL_PACKAGE.MANIFEST)); + expect(fs.writeJSONSync.args[0][0]).equal(path.join(TEST_ROOT_PATH, CONSTANTS.FILE_PATH.ASK_RESOURCES_JSON_CONFIG)); + expect(fs.writeJSONSync.args[1][0]).equal( + path.join(TEST_ROOT_PATH, CONSTANTS.FILE_PATH.SKILL_PACKAGE.PACKAGE, CONSTANTS.FILE_PATH.SKILL_PACKAGE.MANIFEST), + ); + expect(fs.moveSync.callCount).equal(0); + }); - it('| v1Config has lambdaResources without custom/default, models and isps folder do not exist, expect upgrade succeeds', () => { - // setup - fs.existsSync.withArgs(path.join(TEST_ROOT_PATH, 'models')).returns(false); - fs.existsSync.withArgs(path.join(TEST_ROOT_PATH, 'isps')).returns(false); - const NO_LAMBDA_V1CONFIG = formV1Config(TEST_SKILL_ID, false, [{ alexaUsage: 'custom/NA' }]); - // call - helper.attemptUpgradeUndeployedProject(TEST_ROOT_PATH, NO_LAMBDA_V1CONFIG, TEST_PROFILE); - // verify - expect(fs.removeSync.args[0][0]).equal(path.join(TEST_ROOT_PATH, CONSTANTS.FILE_PATH.HIDDEN_ASK_FOLDER)); - expect(fs.removeSync.args[1][0]).equal(path.join(TEST_ROOT_PATH, 'hooks')); - expect(fs.removeSync.args[2][0]).equal(path.join(TEST_ROOT_PATH, CONSTANTS.FILE_PATH.SKILL_PACKAGE.MANIFEST)); - expect(fs.writeJSONSync.args[0][0]).equal(path.join(TEST_ROOT_PATH, CONSTANTS.FILE_PATH.ASK_RESOURCES_JSON_CONFIG)); - expect(fs.writeJSONSync.args[1][0]).equal( - path.join(TEST_ROOT_PATH, CONSTANTS.FILE_PATH.SKILL_PACKAGE.PACKAGE, CONSTANTS.FILE_PATH.SKILL_PACKAGE.MANIFEST) - ); - expect(fs.moveSync.callCount).equal(0); - }); + it("| v1Config has lambdaResources without custom/default, models and isps folder do not exist, expect upgrade succeeds", () => { + // setup + fs.existsSync.withArgs(path.join(TEST_ROOT_PATH, "models")).returns(false); + fs.existsSync.withArgs(path.join(TEST_ROOT_PATH, "isps")).returns(false); + const NO_LAMBDA_V1CONFIG = formV1Config(TEST_SKILL_ID, false, [{alexaUsage: "custom/NA"}]); + // call + helper.attemptUpgradeUndeployedProject(TEST_ROOT_PATH, NO_LAMBDA_V1CONFIG, TEST_PROFILE); + // verify + expect(fs.removeSync.args[0][0]).equal(path.join(TEST_ROOT_PATH, CONSTANTS.FILE_PATH.HIDDEN_ASK_FOLDER)); + expect(fs.removeSync.args[1][0]).equal(path.join(TEST_ROOT_PATH, "hooks")); + expect(fs.removeSync.args[2][0]).equal(path.join(TEST_ROOT_PATH, CONSTANTS.FILE_PATH.SKILL_PACKAGE.MANIFEST)); + expect(fs.writeJSONSync.args[0][0]).equal(path.join(TEST_ROOT_PATH, CONSTANTS.FILE_PATH.ASK_RESOURCES_JSON_CONFIG)); + expect(fs.writeJSONSync.args[1][0]).equal( + path.join(TEST_ROOT_PATH, CONSTANTS.FILE_PATH.SKILL_PACKAGE.PACKAGE, CONSTANTS.FILE_PATH.SKILL_PACKAGE.MANIFEST), + ); + expect(fs.moveSync.callCount).equal(0); + }); - it('| v1Config has lambdaResources, models and isps folder exist, expect upgrade succeeds', () => { - // setup - fs.readJSONSync.returns(formSkillJson('skillManifest', { - endpoint: { - sourceDir: TSET_SRC_DIR, - uri: TEST_ARN - } - })); - const WITH_LAMBDA_V1CONFIG = formV1Config(TEST_SKILL_ID, false, TEST_LAMBDAS); - // call - helper.attemptUpgradeUndeployedProject(TEST_ROOT_PATH, WITH_LAMBDA_V1CONFIG, TEST_PROFILE); - // verify - expect(fs.removeSync.args[0][0]).equal(path.join(TEST_ROOT_PATH, CONSTANTS.FILE_PATH.HIDDEN_ASK_FOLDER)); - expect(fs.removeSync.args[1][0]).equal(path.join(TEST_ROOT_PATH, 'hooks')); - expect(fs.removeSync.args[2][0]).equal(path.join(TEST_ROOT_PATH, CONSTANTS.FILE_PATH.SKILL_PACKAGE.MANIFEST)); - expect(fs.writeJSONSync.args[0][0]).equal(path.join(TEST_ROOT_PATH, CONSTANTS.FILE_PATH.ASK_RESOURCES_JSON_CONFIG)); - expect(fs.writeJSONSync.args[0][1].profiles[TEST_PROFILE]).deep.equal({ - skillMetadata: { - src: `./${CONSTANTS.FILE_PATH.SKILL_PACKAGE.PACKAGE}` - }, - code: { - default: { - src: TSET_SRC_DIR - } - }, - skillInfrastructure: { - type: CONSTANTS.DEPLOYER_TYPE.LAMBDA.NAME, - userConfig: { - awsRegion: TEST_AWS_REGION, - runtime: TEST_RUNTIME, - handler: TEST_HANDLER - } - } - }); - expect(fs.writeJSONSync.args[1][0]).equal( - path.join(TEST_ROOT_PATH, CONSTANTS.FILE_PATH.SKILL_PACKAGE.PACKAGE, CONSTANTS.FILE_PATH.SKILL_PACKAGE.MANIFEST) - ); - expect(fs.writeJSONSync.args[1][1]).deep.equal({ - manifest: { - apis: { - custom: {} - } - } - }); - expect(fs.moveSync.args[0][1]).equal(path.join(TEST_ROOT_PATH, CONSTANTS.FILE_PATH.SKILL_PACKAGE.PACKAGE, 'interactionModels', 'custom')); - expect(fs.moveSync.args[1][1]).equal(path.join(TEST_ROOT_PATH, CONSTANTS.FILE_PATH.SKILL_PACKAGE.PACKAGE, 'isps')); - }); + it("| v1Config has lambdaResources, models and isps folder exist, expect upgrade succeeds", () => { + // setup + fs.readJSONSync.returns( + formSkillJson("skillManifest", { + endpoint: { + sourceDir: TSET_SRC_DIR, + uri: TEST_ARN, + }, + }), + ); + const WITH_LAMBDA_V1CONFIG = formV1Config(TEST_SKILL_ID, false, TEST_LAMBDAS); + // call + helper.attemptUpgradeUndeployedProject(TEST_ROOT_PATH, WITH_LAMBDA_V1CONFIG, TEST_PROFILE); + // verify + expect(fs.removeSync.args[0][0]).equal(path.join(TEST_ROOT_PATH, CONSTANTS.FILE_PATH.HIDDEN_ASK_FOLDER)); + expect(fs.removeSync.args[1][0]).equal(path.join(TEST_ROOT_PATH, "hooks")); + expect(fs.removeSync.args[2][0]).equal(path.join(TEST_ROOT_PATH, CONSTANTS.FILE_PATH.SKILL_PACKAGE.MANIFEST)); + expect(fs.writeJSONSync.args[0][0]).equal(path.join(TEST_ROOT_PATH, CONSTANTS.FILE_PATH.ASK_RESOURCES_JSON_CONFIG)); + expect(fs.writeJSONSync.args[0][1].profiles[TEST_PROFILE]).deep.equal({ + skillMetadata: { + src: `./${CONSTANTS.FILE_PATH.SKILL_PACKAGE.PACKAGE}`, + }, + code: { + default: { + src: TSET_SRC_DIR, + }, + }, + skillInfrastructure: { + type: CONSTANTS.DEPLOYER_TYPE.LAMBDA.NAME, + userConfig: { + awsRegion: TEST_AWS_REGION, + runtime: TEST_RUNTIME, + handler: TEST_HANDLER, + }, + }, + }); + expect(fs.writeJSONSync.args[1][0]).equal( + path.join(TEST_ROOT_PATH, CONSTANTS.FILE_PATH.SKILL_PACKAGE.PACKAGE, CONSTANTS.FILE_PATH.SKILL_PACKAGE.MANIFEST), + ); + expect(fs.writeJSONSync.args[1][1]).deep.equal({ + manifest: { + apis: { + custom: {}, + }, + }, + }); + expect(fs.moveSync.args[0][1]).equal( + path.join(TEST_ROOT_PATH, CONSTANTS.FILE_PATH.SKILL_PACKAGE.PACKAGE, "interactionModels", "custom"), + ); + expect(fs.moveSync.args[1][1]).equal(path.join(TEST_ROOT_PATH, CONSTANTS.FILE_PATH.SKILL_PACKAGE.PACKAGE, "isps")); }); + }); }); diff --git a/test/unit/commands/util/upgrade-project/hosted-skill-helper-test.js b/test/unit/commands/util/upgrade-project/hosted-skill-helper-test.js index 12b86d48..c72bd546 100644 --- a/test/unit/commands/util/upgrade-project/hosted-skill-helper-test.js +++ b/test/unit/commands/util/upgrade-project/hosted-skill-helper-test.js @@ -1,274 +1,293 @@ -const { expect } = require('chai'); -const fs = require('fs-extra'); -const path = require('path'); -const sinon = require('sinon'); +const {expect} = require("chai"); +const fs = require("fs-extra"); +const path = require("path"); +const sinon = require("sinon"); -const awsUtil = require('@src/clients/aws-client/aws-util'); -const GitClient = require('@src/clients/git-client'); -const hostedSkillHelper = require('@src/commands/util/upgrade-project/hosted-skill-helper'); -const HostedSkillController = require('@src/controllers/hosted-skill-controller'); -const SkillMetadataController = require('@src/controllers/skill-metadata-controller'); -const CliError = require('@src/exceptions/cli-error'); -const ResourcesConfig = require('@src/model/resources-config'); -const AskResources = require('@src/model/resources-config/ask-resources'); -const AskStates = require('@src/model/resources-config/ask-states'); -const CONSTANTS = require('@src/utils/constants'); +const awsUtil = require("../../../../../lib/clients/aws-client/aws-util"); +const GitClient = require("../../../../../lib/clients/git-client"); +const hostedSkillHelper = require("../../../../../lib/commands/util/upgrade-project/hosted-skill-helper"); +const HostedSkillController = require("../../../../../lib/controllers/hosted-skill-controller"); +const SkillMetadataController = require("../../../../../lib/controllers/skill-metadata-controller"); +const CliError = require("../../../../../lib/exceptions/cli-error"); +const ResourcesConfig = require("../../../../../lib/model/resources-config"); +const AskResources = require("../../../../../lib/model/resources-config/ask-resources"); +const AskStates = require("../../../../../lib/model/resources-config/ask-states"); +const CONSTANTS = require("../../../../../lib/utils/constants"); -describe('Commands upgrade-project test - hosted skill helper test', () => { - const FIXTURE_RESOURCES_CONFIG_FILE_PATH = path.join(process.cwd(), 'test', 'unit', 'fixture', 'model', 'hosted-proj', 'ask-resources.json'); - const FIXTURE_STATES_CONFIG_FILE_PATH = path.join(process.cwd(), 'test', 'unit', 'fixture', 'model', 'regular-proj', '.ask', 'ask-states.json'); - const TEST_ERROR = 'testError'; - const TEST_PROFILE = 'default'; - const TEST_AWS_REGION = 'us-west-2'; - const TEST_DO_DEBUG = false; - const TEST_SKILL_ID = 'skillId'; - const TEST_SKILL_STAGE = 'development'; - const TEST_ROOT_PATH = 'rootPath'; - const TEST_PROJECT_PATH = 'TEST_PROJECT_PATH'; - const TEST_REPO_URL = 'repo_url'; - const TEST_VERBOSITY_OPTIONS = { - showOutput: false, - showCommand: false, - showStdErr: false, - workingDir: TEST_PROJECT_PATH - }; +describe("Commands upgrade-project test - hosted skill helper test", () => { + const FIXTURE_RESOURCES_CONFIG_FILE_PATH = path.join( + process.cwd(), + "test", + "unit", + "fixture", + "model", + "hosted-proj", + "ask-resources.json", + ); + const FIXTURE_STATES_CONFIG_FILE_PATH = path.join( + process.cwd(), + "test", + "unit", + "fixture", + "model", + "regular-proj", + ".ask", + "ask-states.json", + ); + const TEST_ERROR = "testError"; + const TEST_PROFILE = "default"; + const TEST_AWS_REGION = "us-west-2"; + const TEST_DO_DEBUG = false; + const TEST_SKILL_ID = "skillId"; + const TEST_SKILL_STAGE = "development"; + const TEST_ROOT_PATH = "rootPath"; + const TEST_PROJECT_PATH = "TEST_PROJECT_PATH"; + const TEST_REPO_URL = "repo_url"; + const TEST_VERBOSITY_OPTIONS = { + showOutput: false, + showCommand: false, + showStdErr: false, + workingDir: TEST_PROJECT_PATH, + }; - describe('# test helper method - checkIfDevBranchClean', () => { - let gitClient; - let commitDiffStub; - beforeEach(() => { - gitClient = new GitClient(TEST_PROJECT_PATH, TEST_VERBOSITY_OPTIONS); - commitDiffStub = sinon.stub(gitClient, 'countCommitDifference'); - }); + describe("# test helper method - checkIfDevBranchClean", () => { + let gitClient; + let commitDiffStub; + beforeEach(() => { + gitClient = new GitClient(TEST_PROJECT_PATH, TEST_VERBOSITY_OPTIONS); + commitDiffStub = sinon.stub(gitClient, "countCommitDifference"); + }); - afterEach(() => { - sinon.restore(); - }); + afterEach(() => { + sinon.restore(); + }); - it('| dev branch short status is not clean, expect error thrown', () => { - // setup - const TEST_OUTPUT = 'M models/en-US.json'; - sinon.stub(gitClient, 'checkoutBranch'); - sinon.stub(gitClient, 'shortStatus').returns(TEST_OUTPUT); - // call & verify - expect(() => hostedSkillHelper.checkIfDevBranchClean(gitClient)) - .throw(CliError, `Commit the following files in the dev branch before upgrading project:\n${TEST_OUTPUT}`); - }); + it("| dev branch short status is not clean, expect error thrown", () => { + // setup + const TEST_OUTPUT = "M models/en-US.json"; + sinon.stub(gitClient, "checkoutBranch"); + sinon.stub(gitClient, "shortStatus").returns(TEST_OUTPUT); + // call & verify + expect(() => hostedSkillHelper.checkIfDevBranchClean(gitClient)).throw( + CliError, + `Commit the following files in the dev branch before upgrading project:\n${TEST_OUTPUT}`, + ); + }); - it('| origin branch commits difference is not zero , expect error thrown', () => { - // setup - sinon.stub(gitClient, 'checkoutBranch'); - sinon.stub(gitClient, 'shortStatus').returns(''); - commitDiffStub.onCall(0).returns('1'); - commitDiffStub.onCall(1).returns('1'); - // call & verify - expect(() => hostedSkillHelper.checkIfDevBranchClean(gitClient)) - .throw('Upgrade project failed. Your branch is ahead of origin/dev by 1 commit(s), ' - + 'Please follow the project upgrade instruction from ' - + 'https://github.com/alexa/ask-cli/blob/develop/docs/Upgrade-Project-From-V1.md#upgrade-steps ' - + 'to clean your working branch before upgrading project.'); - }); + it("| origin branch commits difference is not zero , expect error thrown", () => { + // setup + sinon.stub(gitClient, "checkoutBranch"); + sinon.stub(gitClient, "shortStatus").returns(""); + commitDiffStub.onCall(0).returns("1"); + commitDiffStub.onCall(1).returns("1"); + // call & verify + expect(() => hostedSkillHelper.checkIfDevBranchClean(gitClient)).throw( + "Upgrade project failed. Your branch is ahead of origin/dev by 1 commit(s), " + + "Please follow the project upgrade instruction from " + + "https://github.com/alexa/ask-cli/blob/develop/docs/Upgrade-Project-From-V1.md#upgrade-steps " + + "to clean your working branch before upgrading project.", + ); + }); - it('| master branch commits difference is not zero , expect error thrown', () => { - // setup - sinon.stub(gitClient, 'checkoutBranch'); - sinon.stub(gitClient, 'shortStatus').returns(''); - commitDiffStub.onCall(0).returns('0'); - commitDiffStub.onCall(1).returns('1'); - // call & verify - expect(() => hostedSkillHelper.checkIfDevBranchClean(gitClient)) - .throw('Upgrade project failed. Your branch is ahead of master by 1 commit(s), ' - + 'Please follow the project upgrade instruction from ' - + 'https://github.com/alexa/ask-cli/blob/develop/docs/Upgrade-Project-From-V1.md#upgrade-steps ' - + 'to clean your working branch before upgrading project.'); - }); + it("| master branch commits difference is not zero , expect error thrown", () => { + // setup + sinon.stub(gitClient, "checkoutBranch"); + sinon.stub(gitClient, "shortStatus").returns(""); + commitDiffStub.onCall(0).returns("0"); + commitDiffStub.onCall(1).returns("1"); + // call & verify + expect(() => hostedSkillHelper.checkIfDevBranchClean(gitClient)).throw( + "Upgrade project failed. Your branch is ahead of master by 1 commit(s), " + + "Please follow the project upgrade instruction from " + + "https://github.com/alexa/ask-cli/blob/develop/docs/Upgrade-Project-From-V1.md#upgrade-steps " + + "to clean your working branch before upgrading project.", + ); + }); - it('| origin and master branch commits difference is zero , expect noe error thrown', () => { - // setup - sinon.stub(gitClient, 'checkoutBranch'); - sinon.stub(gitClient, 'shortStatus').returns(''); - commitDiffStub.onCall(0).returns('0'); - commitDiffStub.onCall(1).returns('0'); - // call - hostedSkillHelper.checkIfDevBranchClean(gitClient); - }); + it("| origin and master branch commits difference is zero , expect noe error thrown", () => { + // setup + sinon.stub(gitClient, "checkoutBranch"); + sinon.stub(gitClient, "shortStatus").returns(""); + commitDiffStub.onCall(0).returns("0"); + commitDiffStub.onCall(1).returns("0"); + // call + hostedSkillHelper.checkIfDevBranchClean(gitClient); }); + }); - describe('# test helper method - createV2ProjectSkeletonAndLoadModel', () => { - beforeEach(() => { - sinon.stub(path, 'join'); - path.join.withArgs( - TEST_ROOT_PATH, CONSTANTS.FILE_PATH.ASK_RESOURCES_JSON_CONFIG - ).returns(FIXTURE_RESOURCES_CONFIG_FILE_PATH); - path.join.withArgs( - TEST_ROOT_PATH, CONSTANTS.FILE_PATH.HIDDEN_ASK_FOLDER, CONSTANTS.FILE_PATH.ASK_STATES_JSON_CONFIG - ).returns(FIXTURE_STATES_CONFIG_FILE_PATH); - path.join.callThrough(); - }); + describe("# test helper method - createV2ProjectSkeletonAndLoadModel", () => { + beforeEach(() => { + sinon.stub(path, "join"); + path.join.withArgs(TEST_ROOT_PATH, CONSTANTS.FILE_PATH.ASK_RESOURCES_JSON_CONFIG).returns(FIXTURE_RESOURCES_CONFIG_FILE_PATH); + path.join + .withArgs(TEST_ROOT_PATH, CONSTANTS.FILE_PATH.HIDDEN_ASK_FOLDER, CONSTANTS.FILE_PATH.ASK_STATES_JSON_CONFIG) + .returns(FIXTURE_STATES_CONFIG_FILE_PATH); + path.join.callThrough(); + }); - afterEach(() => { - sinon.restore(); - }); + afterEach(() => { + sinon.restore(); + }); - it('| crate v2 project skeleton, expect write JSON file correctly', () => { - // setup - const ensureDirStub = sinon.stub(fs, 'ensureDirSync'); - sinon.stub(AskResources, 'withContent'); - sinon.stub(AskStates, 'withContent'); - // call - hostedSkillHelper.createV2ProjectSkeletonAndLoadModel(TEST_ROOT_PATH, TEST_SKILL_ID, TEST_PROFILE); - expect(ensureDirStub.args[0][0]).eq(path.join(TEST_ROOT_PATH, CONSTANTS.FILE_PATH.SKILL_PACKAGE.PACKAGE)); - expect(ensureDirStub.args[1][0]).eq(path.join(TEST_ROOT_PATH, CONSTANTS.FILE_PATH.SKILL_CODE.LAMBDA)); - expect(AskResources.withContent.args[0][0]).eq(FIXTURE_RESOURCES_CONFIG_FILE_PATH); - expect(AskResources.withContent.args[0][1].profiles).deep.equal({ - [TEST_PROFILE]: {} - }); - expect(AskStates.withContent.args[0][0]).eq(FIXTURE_STATES_CONFIG_FILE_PATH); - expect(AskStates.withContent.args[0][1].profiles).deep.equal({ - [TEST_PROFILE]: { - skillId: TEST_SKILL_ID - } - }); - }); + it("| crate v2 project skeleton, expect write JSON file correctly", () => { + // setup + const ensureDirStub = sinon.stub(fs, "ensureDirSync"); + sinon.stub(AskResources, "withContent"); + sinon.stub(AskStates, "withContent"); + // call + hostedSkillHelper.createV2ProjectSkeletonAndLoadModel(TEST_ROOT_PATH, TEST_SKILL_ID, TEST_PROFILE); + expect(ensureDirStub.args[0][0]).eq(path.join(TEST_ROOT_PATH, CONSTANTS.FILE_PATH.SKILL_PACKAGE.PACKAGE)); + expect(ensureDirStub.args[1][0]).eq(path.join(TEST_ROOT_PATH, CONSTANTS.FILE_PATH.SKILL_CODE.LAMBDA)); + expect(AskResources.withContent.args[0][0]).eq(FIXTURE_RESOURCES_CONFIG_FILE_PATH); + expect(AskResources.withContent.args[0][1].profiles).deep.equal({ + [TEST_PROFILE]: {}, + }); + expect(AskStates.withContent.args[0][0]).eq(FIXTURE_STATES_CONFIG_FILE_PATH); + expect(AskStates.withContent.args[0][1].profiles).deep.equal({ + [TEST_PROFILE]: { + skillId: TEST_SKILL_ID, + }, + }); }); + }); - describe('# test helper method - downloadSkillPackage', () => { - beforeEach(() => { - new ResourcesConfig(FIXTURE_RESOURCES_CONFIG_FILE_PATH); - }); + describe("# test helper method - downloadSkillPackage", () => { + beforeEach(() => { + new ResourcesConfig(FIXTURE_RESOURCES_CONFIG_FILE_PATH); + }); - afterEach(() => { - sinon.restore(); - ResourcesConfig.dispose(); - }); + afterEach(() => { + sinon.restore(); + ResourcesConfig.dispose(); + }); - it('| skillMetaController getSkillPackage fails, expect callback error', (done) => { - // setup - sinon.stub(SkillMetadataController.prototype, 'getSkillPackage').callsArgWith(3, TEST_ERROR); - // call - hostedSkillHelper.downloadSkillPackage(TEST_ROOT_PATH, TEST_SKILL_ID, TEST_SKILL_STAGE, TEST_PROFILE, TEST_DO_DEBUG, (err) => { - expect(err).equal(TEST_ERROR); - done(); - }); - }); + it("| skillMetaController getSkillPackage fails, expect callback error", (done) => { + // setup + sinon.stub(SkillMetadataController.prototype, "getSkillPackage").callsArgWith(3, TEST_ERROR); + // call + hostedSkillHelper.downloadSkillPackage(TEST_ROOT_PATH, TEST_SKILL_ID, TEST_SKILL_STAGE, TEST_PROFILE, TEST_DO_DEBUG, (err) => { + expect(err).equal(TEST_ERROR); + done(); + }); + }); - it('| skillMetaController getSkillPackage passes, hashUtils fails, expect no error return', (done) => { - // setup - sinon.stub(SkillMetadataController.prototype, 'getSkillPackage').callsArgWith(3, null); - // call - hostedSkillHelper.downloadSkillPackage(TEST_ROOT_PATH, TEST_SKILL_ID, TEST_SKILL_STAGE, TEST_PROFILE, TEST_DO_DEBUG, (err) => { - // verify - expect(err).equal(undefined); - done(); - }); - }); + it("| skillMetaController getSkillPackage passes, hashUtils fails, expect no error return", (done) => { + // setup + sinon.stub(SkillMetadataController.prototype, "getSkillPackage").callsArgWith(3, null); + // call + hostedSkillHelper.downloadSkillPackage(TEST_ROOT_PATH, TEST_SKILL_ID, TEST_SKILL_STAGE, TEST_PROFILE, TEST_DO_DEBUG, (err) => { + // verify + expect(err).equal(undefined); + done(); + }); }); + }); - describe('# test helper method - handleExistingLambdaCode', () => { - beforeEach(() => { - new ResourcesConfig(FIXTURE_RESOURCES_CONFIG_FILE_PATH); - }); + describe("# test helper method - handleExistingLambdaCode", () => { + beforeEach(() => { + new ResourcesConfig(FIXTURE_RESOURCES_CONFIG_FILE_PATH); + }); - afterEach(() => { - sinon.restore(); - ResourcesConfig.dispose(); - }); + afterEach(() => { + sinon.restore(); + ResourcesConfig.dispose(); + }); - it('| handle lambdaCode and update resources JSON file, expect update correctly', () => { - // setup - sinon.stub(awsUtil, 'getAWSProfile'); - sinon.stub(awsUtil, 'getCLICompatibleDefaultRegion').returns(TEST_AWS_REGION); - const copyStub = sinon.stub(fs, 'copySync'); - // call - hostedSkillHelper.handleExistingLambdaCode(TEST_ROOT_PATH, TEST_REPO_URL, TEST_PROFILE); - // verify - expect(ResourcesConfig.getInstance().getSkillInfraType(TEST_PROFILE)).equal(CONSTANTS.DEPLOYER_TYPE.HOSTED.NAME); - expect(copyStub.args[0][0]).equal(path.join(TEST_ROOT_PATH, CONSTANTS.FILE_PATH.LEGACY_PATH, CONSTANTS.FILE_PATH.SKILL_CODE.LAMBDA)); - expect(copyStub.args[0][1]).equal(path.join(TEST_ROOT_PATH, CONSTANTS.FILE_PATH.SKILL_CODE.LAMBDA)); - }); + it("| handle lambdaCode and update resources JSON file, expect update correctly", () => { + // setup + sinon.stub(awsUtil, "getAWSProfile"); + sinon.stub(awsUtil, "getCLICompatibleDefaultRegion").returns(TEST_AWS_REGION); + const copyStub = sinon.stub(fs, "copySync"); + // call + hostedSkillHelper.handleExistingLambdaCode(TEST_ROOT_PATH, TEST_REPO_URL, TEST_PROFILE); + // verify + expect(ResourcesConfig.getInstance().getSkillInfraType(TEST_PROFILE)).equal(CONSTANTS.DEPLOYER_TYPE.HOSTED.NAME); + expect(copyStub.args[0][0]).equal(path.join(TEST_ROOT_PATH, CONSTANTS.FILE_PATH.LEGACY_PATH, CONSTANTS.FILE_PATH.SKILL_CODE.LAMBDA)); + expect(copyStub.args[0][1]).equal(path.join(TEST_ROOT_PATH, CONSTANTS.FILE_PATH.SKILL_CODE.LAMBDA)); }); + }); - describe('# test helper method - postUpgradeGitSetup', () => { - let gitClient; - beforeEach(() => { - gitClient = new GitClient(TEST_PROJECT_PATH, TEST_VERBOSITY_OPTIONS); - }); + describe("# test helper method - postUpgradeGitSetup", () => { + let gitClient; + beforeEach(() => { + gitClient = new GitClient(TEST_PROJECT_PATH, TEST_VERBOSITY_OPTIONS); + }); - afterEach(() => { - sinon.restore(); - }); + afterEach(() => { + sinon.restore(); + }); - it('| set Git Credential Helper fails, expect error thrown', (done) => { - // setup - sinon.stub(gitClient, 'configureCredentialHelper').throws(new CliError(TEST_ERROR)); - // call - hostedSkillHelper.postUpgradeGitSetup(TEST_PROFILE, TEST_DO_DEBUG, gitClient, TEST_REPO_URL, TEST_SKILL_ID, (err) => { - // verify - expect(err.message).equal(TEST_ERROR); - done(); - }); - }); + it("| set Git Credential Helper fails, expect error thrown", (done) => { + // setup + sinon.stub(gitClient, "configureCredentialHelper").throws(new CliError(TEST_ERROR)); + // call + hostedSkillHelper.postUpgradeGitSetup(TEST_PROFILE, TEST_DO_DEBUG, gitClient, TEST_REPO_URL, TEST_SKILL_ID, (err) => { + // verify + expect(err.message).equal(TEST_ERROR); + done(); + }); + }); - it('| set Master As Default fails, expect error thrown', (done) => { - // setup - sinon.stub(gitClient, 'configureCredentialHelper'); - sinon.stub(gitClient, 'checkoutBranch'); - sinon.stub(gitClient, 'merge'); - sinon.stub(gitClient, 'deleteBranch').throws(new CliError(TEST_ERROR)); - // call - hostedSkillHelper.postUpgradeGitSetup(TEST_PROFILE, TEST_DO_DEBUG, gitClient, TEST_REPO_URL, TEST_SKILL_ID, (err) => { - // verify - expect(err.message).equal(TEST_ERROR); - done(); - }); - }); + it("| set Master As Default fails, expect error thrown", (done) => { + // setup + sinon.stub(gitClient, "configureCredentialHelper"); + sinon.stub(gitClient, "checkoutBranch"); + sinon.stub(gitClient, "merge"); + sinon.stub(gitClient, "deleteBranch").throws(new CliError(TEST_ERROR)); + // call + hostedSkillHelper.postUpgradeGitSetup(TEST_PROFILE, TEST_DO_DEBUG, gitClient, TEST_REPO_URL, TEST_SKILL_ID, (err) => { + // verify + expect(err.message).equal(TEST_ERROR); + done(); + }); + }); - it('| update git ignore file, expect error thrown', (done) => { - // setup - sinon.stub(gitClient, 'configureCredentialHelper'); - sinon.stub(gitClient, 'checkoutBranch'); - sinon.stub(gitClient, 'merge'); - sinon.stub(gitClient, 'deleteBranch'); - sinon.stub(gitClient, 'setupGitIgnore').throws(new CliError(TEST_ERROR)); - // call - hostedSkillHelper.postUpgradeGitSetup(TEST_PROFILE, TEST_DO_DEBUG, gitClient, TEST_REPO_URL, TEST_SKILL_ID, (err) => { - // verify - expect(gitClient.setupGitIgnore.args[0][0]).deep.equal(['ask-resources.json', '.ask/']); - expect(err.message).equal(TEST_ERROR); - done(); - }); - }); + it("| update git ignore file, expect error thrown", (done) => { + // setup + sinon.stub(gitClient, "configureCredentialHelper"); + sinon.stub(gitClient, "checkoutBranch"); + sinon.stub(gitClient, "merge"); + sinon.stub(gitClient, "deleteBranch"); + sinon.stub(gitClient, "setupGitIgnore").throws(new CliError(TEST_ERROR)); + // call + hostedSkillHelper.postUpgradeGitSetup(TEST_PROFILE, TEST_DO_DEBUG, gitClient, TEST_REPO_URL, TEST_SKILL_ID, (err) => { + // verify + expect(gitClient.setupGitIgnore.args[0][0]).deep.equal(["ask-resources.json", ".ask/"]); + expect(err.message).equal(TEST_ERROR); + done(); + }); + }); - it('| set pre push hook script fails, expect error thrown', (done) => { - // setup - sinon.stub(gitClient, 'configureCredentialHelper'); - sinon.stub(gitClient, 'checkoutBranch'); - sinon.stub(gitClient, 'merge'); - sinon.stub(gitClient, 'deleteBranch'); - sinon.stub(gitClient, 'setupGitIgnore'); - sinon.stub(HostedSkillController.prototype, 'downloadAskScripts').callsArgWith(1, TEST_ERROR); - // call - hostedSkillHelper.postUpgradeGitSetup(TEST_PROFILE, TEST_DO_DEBUG, gitClient, TEST_REPO_URL, TEST_SKILL_ID, (err) => { - // verify - expect(err).equal(TEST_ERROR); - done(); - }); - }); + it("| set pre push hook script fails, expect error thrown", (done) => { + // setup + sinon.stub(gitClient, "configureCredentialHelper"); + sinon.stub(gitClient, "checkoutBranch"); + sinon.stub(gitClient, "merge"); + sinon.stub(gitClient, "deleteBranch"); + sinon.stub(gitClient, "setupGitIgnore"); + sinon.stub(HostedSkillController.prototype, "downloadAskScripts").callsArgWith(1, TEST_ERROR); + // call + hostedSkillHelper.postUpgradeGitSetup(TEST_PROFILE, TEST_DO_DEBUG, gitClient, TEST_REPO_URL, TEST_SKILL_ID, (err) => { + // verify + expect(err).equal(TEST_ERROR); + done(); + }); + }); - it('| post Upgrade Git Setup succeeds, expect no error thrown', (done) => { - // setup - sinon.stub(gitClient, 'configureCredentialHelper'); - sinon.stub(gitClient, 'checkoutBranch'); - sinon.stub(gitClient, 'merge'); - sinon.stub(gitClient, 'deleteBranch'); - sinon.stub(gitClient, 'setupGitIgnore'); - sinon.stub(HostedSkillController.prototype, 'downloadAskScripts').callsArgWith(1, null); - // call - hostedSkillHelper.postUpgradeGitSetup(TEST_PROFILE, TEST_DO_DEBUG, gitClient, TEST_REPO_URL, TEST_SKILL_ID, (err) => { - // verify - expect(err).equal(null); - done(); - }); - }); + it("| post Upgrade Git Setup succeeds, expect no error thrown", (done) => { + // setup + sinon.stub(gitClient, "configureCredentialHelper"); + sinon.stub(gitClient, "checkoutBranch"); + sinon.stub(gitClient, "merge"); + sinon.stub(gitClient, "deleteBranch"); + sinon.stub(gitClient, "setupGitIgnore"); + sinon.stub(HostedSkillController.prototype, "downloadAskScripts").callsArgWith(1, null); + // call + hostedSkillHelper.postUpgradeGitSetup(TEST_PROFILE, TEST_DO_DEBUG, gitClient, TEST_REPO_URL, TEST_SKILL_ID, (err) => { + // verify + expect(err).equal(null); + done(); + }); }); + }); }); diff --git a/test/unit/commands/util/upgrade-project/index-test.js b/test/unit/commands/util/upgrade-project/index-test.js deleted file mode 100644 index fce4e373..00000000 --- a/test/unit/commands/util/upgrade-project/index-test.js +++ /dev/null @@ -1,495 +0,0 @@ -const { expect } = require('chai'); -const path = require('path'); -const sinon = require('sinon'); - -const UpgradeProjectCommand = require('@src/commands/util/upgrade-project/index'); -const helper = require('@src/commands/util/upgrade-project/helper'); -const hostedSkillHelper = require('@src/commands/util/upgrade-project/hosted-skill-helper'); -const optionModel = require('@src/commands/option-model'); -const CLiError = require('@src/exceptions/cli-error'); -const Messenger = require('@src/view/messenger'); -const profileHelper = require('@src/utils/profile-helper'); -const CONSTANTS = require('@src/utils/constants'); - -describe('Commands upgrade project test - command class test', () => { - const FIXTURE_HOSTED_SKILL_RESOURCES_CONFIG = path.join(process.cwd(), 'test', 'unit', 'fixture', 'model', 'hosted-proj', 'ask-resources.json'); - const TEST_PROFILE = 'default'; - const TEST_ERROR = 'upgrade project error'; - const TEST_SKILL_ID = 'skillId'; - const TEST_V1_CONFIG = {}; - let infoStub; - let errorStub; - let warnStub; - - beforeEach(() => { - infoStub = sinon.stub(); - errorStub = sinon.stub(); - warnStub = sinon.stub(); - sinon.stub(Messenger, 'getInstance').returns({ - info: infoStub, - error: errorStub, - warn: warnStub - }); - }); - - afterEach(() => { - sinon.restore(); - }); - - it('| validate command information is set correctly', () => { - const instance = new UpgradeProjectCommand(optionModel); - expect(instance.name()).equal('upgrade-project'); - expect(instance.description()).equal('upgrade the v1 ask-cli skill project to v2 structure'); - expect(instance.requiredOptions()).deep.equal([]); - expect(instance.optionalOptions()).deep.equal(['profile', 'debug']); - }); - - describe('validate command handle', () => { - const TEST_CMD = { - profile: TEST_PROFILE - }; - - describe('command handle - pre upgrade check', () => { - let instance; - - beforeEach(() => { - instance = new UpgradeProjectCommand(optionModel); - sinon.stub(profileHelper, 'runtimeProfile').returns(TEST_PROFILE); - sinon.stub(helper, 'loadV1ProjConfig').returns({ - isDeployed: true, - v1Config: TEST_V1_CONFIG - }); - sinon.stub(helper, 'attemptUpgradeUndeployedProject'); - }); - - afterEach(() => { - sinon.restore(); - }); - - it('| when profile is not correct, expect throw error', (done) => { - // setup - profileHelper.runtimeProfile.throws(new Error(TEST_ERROR)); - // call - instance.handle(TEST_CMD, (err) => { - // verify - expect(err.message).equal(TEST_ERROR); - expect(errorStub.args[0][0].message).equal(TEST_ERROR); - expect(infoStub.callCount).equal(0); - expect(warnStub.callCount).equal(0); - done(); - }); - }); - - it('| when loadV1ProjConfig throws, expect error displayed', (done) => { - // setup - helper.loadV1ProjConfig.throws(new Error(TEST_ERROR)); - // call - instance.handle(TEST_CMD, (err) => { - // verify - expect(err.message).equal(TEST_ERROR); - expect(errorStub.args[0][0].message).equal(TEST_ERROR); - expect(infoStub.callCount).equal(0); - expect(warnStub.callCount).equal(0); - done(); - }); - }); - - it('| when attemptUpgradeUndeployedProject throws, expect error displayed', (done) => { - // setup - helper.loadV1ProjConfig.returns({ isDeployed: false }); - helper.attemptUpgradeUndeployedProject.throws(new Error(TEST_ERROR)); - // call - instance.handle(TEST_CMD, (err) => { - // verify - expect(err.message).equal(TEST_ERROR); - expect(errorStub.args[0][0].message).equal(TEST_ERROR); - expect(infoStub.callCount).equal(0); - expect(warnStub.callCount).equal(0); - done(); - }); - }); - - it('| when project is undeployed project, expect project will get updated directly', (done) => { - // setup - helper.loadV1ProjConfig.returns({ isDeployed: false }); - // call - instance.handle(TEST_CMD, (err) => { - // verify - expect(err).equal(undefined); - expect(infoStub.args[0][0]).equal('Template project migration finished.'); - expect(errorStub.callCount).equal(0); - expect(warnStub.callCount).equal(0); - done(); - }); - }); - - it('| when extract upgrade information fails, expect throw error', (done) => { - // setup - sinon.stub(helper, 'extractUpgradeInformation').throws(new CLiError(TEST_ERROR)); - // call - instance.handle(TEST_CMD, (err) => { - // verify - expect(err.message).equal(TEST_ERROR); - expect(errorStub.args[0][0].message).equal(TEST_ERROR); - expect(infoStub.callCount).equal(0); - expect(warnStub.callCount).equal(0); - done(); - }); - }); - - it('| helper preview upgrade fails, expect throw error', (done) => { - // setup - sinon.stub(helper, 'extractUpgradeInformation'); - sinon.stub(helper, 'previewUpgrade').callsArgWith(1, TEST_ERROR); - // call - instance.handle(TEST_CMD, (err) => { - // verify - expect(err).equal(TEST_ERROR); - expect(errorStub.args[0][0]).equal(TEST_ERROR); - expect(infoStub.callCount).equal(0); - expect(warnStub.callCount).equal(0); - done(); - }); - }); - - it('| helper preview Upgrade without previewConfirm, expect throw information', (done) => { - // setup - sinon.stub(helper, 'extractUpgradeInformation'); - sinon.stub(helper, 'previewUpgrade').callsArgWith(1, null, null); - // call - instance.handle(TEST_CMD, (err) => { - // verify - expect(err).equal(undefined); - expect(infoStub.args[0][0]).equal('Command upgrade-project aborted.'); - expect(errorStub.callCount).equal(0); - expect(warnStub.callCount).equal(0); - done(); - }); - }); - }); - - describe('command handle - create V2 hosted skill project', () => { - let instance; - - beforeEach(() => { - instance = new UpgradeProjectCommand(optionModel); - sinon.stub(profileHelper, 'runtimeProfile').returns(TEST_PROFILE); - sinon.stub(helper, 'loadV1ProjConfig').returns({ - isDeployed: true, - v1Config: TEST_V1_CONFIG - }); - }); - - afterEach(() => { - sinon.restore(); - }); - - it('| hostedSkillHelper check If Dev Branch Clean fails, expect throw error', (done) => { - // setup - const TEST_USER_INPUT = { - isHosted: true, - skillId: TEST_SKILL_ID - }; - sinon.stub(helper, 'extractUpgradeInformation').returns(TEST_USER_INPUT); - sinon.stub(helper, 'previewUpgrade').callsArgWith(1, null, true); - sinon.stub(hostedSkillHelper, 'checkIfDevBranchClean').throws(new CLiError(TEST_ERROR)); - // call - instance.handle(TEST_CMD, (err) => { - // verify - expect(err.message).equal(TEST_ERROR); - expect(errorStub.args[0][0].message).equal(TEST_ERROR); - expect(infoStub.callCount).equal(0); - expect(warnStub.callCount).equal(0); - done(); - }); - }); - - it('| helper move old project to legacy folder fails, expect throw error', (done) => { - // setup - const TEST_USER_INPUT = { - isHosted: true, - skillId: TEST_SKILL_ID - }; - sinon.stub(helper, 'extractUpgradeInformation').returns(TEST_USER_INPUT); - sinon.stub(helper, 'previewUpgrade').callsArgWith(1, null, true); - sinon.stub(hostedSkillHelper, 'checkIfDevBranchClean'); - sinon.stub(helper, 'moveOldProjectToLegacyFolder').throws(new CLiError(TEST_ERROR)); - // call - instance.handle(TEST_CMD, (err) => { - // verify - expect(err.message).equal(TEST_ERROR); - expect(errorStub.args[0][0].message).equal(TEST_ERROR); - expect(infoStub.callCount).equal(0); - expect(warnStub.callCount).equal(0); - done(); - }); - }); - - it('| hostedSkillHelper create V2 project skeleton fails, expect throw error', (done) => { - // setup - const TEST_USER_INPUT = { - isHosted: true, - skillId: TEST_SKILL_ID - }; - sinon.stub(helper, 'extractUpgradeInformation').returns(TEST_USER_INPUT); - sinon.stub(helper, 'previewUpgrade').callsArgWith(1, null, true); - sinon.stub(hostedSkillHelper, 'checkIfDevBranchClean'); - sinon.stub(helper, 'moveOldProjectToLegacyFolder'); - sinon.stub(hostedSkillHelper, 'createV2ProjectSkeletonAndLoadModel').throws(new CLiError(TEST_ERROR)); - // call - instance.handle(TEST_CMD, (err) => { - // verify - expect(err.message).equal(TEST_ERROR); - expect(errorStub.args[0][0].message).equal(TEST_ERROR); - expect(infoStub.callCount).equal(0); - expect(warnStub.callCount).equal(0); - done(); - }); - }); - - it('| hostedSkillHelper download skill package fails, expect throw error', (done) => { - // setup - const TEST_USER_INPUT = { - isHosted: true, - skillId: TEST_SKILL_ID - }; - sinon.stub(helper, 'extractUpgradeInformation').returns(TEST_USER_INPUT); - sinon.stub(helper, 'previewUpgrade').callsArgWith(1, null, true); - sinon.stub(hostedSkillHelper, 'checkIfDevBranchClean'); - sinon.stub(helper, 'moveOldProjectToLegacyFolder'); - sinon.stub(hostedSkillHelper, 'createV2ProjectSkeletonAndLoadModel'); - sinon.stub(path, 'join').withArgs( - process.cwd(), CONSTANTS.FILE_PATH.ASK_RESOURCES_JSON_CONFIG - ).returns(FIXTURE_HOSTED_SKILL_RESOURCES_CONFIG); - path.join.callThrough(); - sinon.stub(hostedSkillHelper, 'downloadSkillPackage').callsArgWith(5, TEST_ERROR); - // call - instance.handle(TEST_CMD, (err) => { - // verify - expect(err).equal(TEST_ERROR); - expect(errorStub.args[0][0]).equal(TEST_ERROR); - expect(infoStub.callCount).equal(0); - expect(warnStub.callCount).equal(0); - done(); - }); - }); - - it('| hostedSkillHelper handle existing Lambda code fails, expect throw error', (done) => { - // setup - const TEST_USER_INPUT = { - isHosted: true, - skillId: TEST_SKILL_ID - }; - sinon.stub(helper, 'extractUpgradeInformation').returns(TEST_USER_INPUT); - sinon.stub(helper, 'previewUpgrade').callsArgWith(1, null, true); - sinon.stub(hostedSkillHelper, 'checkIfDevBranchClean'); - sinon.stub(hostedSkillHelper, 'postUpgradeGitSetup'); - sinon.stub(helper, 'moveOldProjectToLegacyFolder'); - sinon.stub(hostedSkillHelper, 'createV2ProjectSkeletonAndLoadModel'); - sinon.stub(path, 'join').withArgs( - process.cwd(), CONSTANTS.FILE_PATH.ASK_RESOURCES_JSON_CONFIG - ).returns(FIXTURE_HOSTED_SKILL_RESOURCES_CONFIG); - path.join.callThrough(); - sinon.stub(hostedSkillHelper, 'downloadSkillPackage').callsArgWith(5, null); - sinon.stub(hostedSkillHelper, 'handleExistingLambdaCode').throws(new CLiError(TEST_ERROR)); - // call - instance.handle(TEST_CMD, (err) => { - // verify - expect(err.message).equal(TEST_ERROR); - expect(errorStub.args[0][0].message).equal(TEST_ERROR); - expect(infoStub.callCount).equal(0); - expect(warnStub.callCount).equal(0); - done(); - }); - }); - - it('| hostedSkillHelper post Upgrade Git Setup fails , expect no error thrown', (done) => { - // setup - const TEST_USER_INPUT = { - isHosted: true, - skillId: TEST_SKILL_ID - }; - sinon.stub(helper, 'extractUpgradeInformation').returns(TEST_USER_INPUT); - sinon.stub(helper, 'previewUpgrade').callsArgWith(1, null, true); - sinon.stub(hostedSkillHelper, 'checkIfDevBranchClean'); - sinon.stub(helper, 'moveOldProjectToLegacyFolder'); - sinon.stub(hostedSkillHelper, 'createV2ProjectSkeletonAndLoadModel'); - sinon.stub(path, 'join').returns(FIXTURE_HOSTED_SKILL_RESOURCES_CONFIG); - sinon.stub(hostedSkillHelper, 'downloadSkillPackage').callsArgWith(5, null); - sinon.stub(hostedSkillHelper, 'handleExistingLambdaCode'); - sinon.stub(hostedSkillHelper, 'postUpgradeGitSetup').callsArgWith(5, TEST_ERROR); - // call - instance.handle(TEST_CMD, (err) => { - // verify - expect(err).equal(TEST_ERROR); - expect(errorStub.args[0][0]).equal(TEST_ERROR); - expect(infoStub.callCount).equal(0); - expect(warnStub.callCount).equal(0); - done(); - }); - }); - - it('| hosted skill project migration succeeds , expect no error thrown', (done) => { - // setup - const TEST_USER_INPUT = { - isHosted: true, - skillId: TEST_SKILL_ID - }; - sinon.stub(helper, 'extractUpgradeInformation').returns(TEST_USER_INPUT); - sinon.stub(helper, 'previewUpgrade').callsArgWith(1, null, true); - sinon.stub(hostedSkillHelper, 'checkIfDevBranchClean'); - sinon.stub(helper, 'moveOldProjectToLegacyFolder'); - sinon.stub(hostedSkillHelper, 'createV2ProjectSkeletonAndLoadModel'); - sinon.stub(path, 'join').withArgs( - process.cwd(), CONSTANTS.FILE_PATH.ASK_RESOURCES_JSON_CONFIG - ).returns(FIXTURE_HOSTED_SKILL_RESOURCES_CONFIG); - path.join.callThrough(); - sinon.stub(hostedSkillHelper, 'downloadSkillPackage').callsArgWith(5, null); - sinon.stub(hostedSkillHelper, 'handleExistingLambdaCode'); - sinon.stub(hostedSkillHelper, 'postUpgradeGitSetup').callsArgWith(5, null); - // call - instance.handle(TEST_CMD, (err) => { - // verify - expect(err).equal(undefined); - expect(infoStub.args[0][0]).equal('Project migration finished.'); - expect(errorStub.callCount).equal(0); - expect(warnStub.callCount).equal(0); - done(); - }); - }); - }); - - describe('command handle - create V2 Non hosted skill project', () => { - let instance; - - beforeEach(() => { - instance = new UpgradeProjectCommand(optionModel); - sinon.stub(profileHelper, 'runtimeProfile').returns(TEST_PROFILE); - sinon.stub(helper, 'loadV1ProjConfig').returns({ - isDeployed: true, - v1Config: TEST_V1_CONFIG - }); - }); - - afterEach(() => { - sinon.restore(); - }); - - it('| helper move old project to legacy folder fails, expect throw error', (done) => { - // setup - const TEST_USER_INPUT = { - skillId: TEST_SKILL_ID - }; - sinon.stub(helper, 'extractUpgradeInformation').returns(TEST_USER_INPUT); - sinon.stub(helper, 'previewUpgrade').callsArgWith(1, null, true); - sinon.stub(helper, 'moveOldProjectToLegacyFolder').throws(new CLiError(TEST_ERROR)); - // call - instance.handle(TEST_CMD, (err) => { - // verify - expect(err.message).equal(TEST_ERROR); - expect(errorStub.args[0][0].message).equal(TEST_ERROR); - expect(infoStub.callCount).equal(0); - expect(warnStub.callCount).equal(0); - done(); - }); - }); - - it('| helper create V2 project skeleton fails, expect throw error', (done) => { - // setup - const TEST_USER_INPUT = { - skillId: TEST_SKILL_ID - }; - sinon.stub(helper, 'extractUpgradeInformation').returns(TEST_USER_INPUT); - sinon.stub(helper, 'previewUpgrade').callsArgWith(1, null, true); - sinon.stub(helper, 'moveOldProjectToLegacyFolder'); - sinon.stub(helper, 'createV2ProjectSkeletonAndLoadModel').throws(new CLiError(TEST_ERROR)); - // call - instance.handle(TEST_CMD, (err) => { - // verify - expect(err.message).equal(TEST_ERROR); - expect(errorStub.args[0][0].message).equal(TEST_ERROR); - expect(infoStub.callCount).equal(0); - expect(warnStub.callCount).equal(0); - done(); - }); - }); - - it('| helper download skill package fails, expect throw error', (done) => { - // setup - const TEST_USER_INPUT = { - skillId: TEST_SKILL_ID - }; - sinon.stub(helper, 'extractUpgradeInformation').returns(TEST_USER_INPUT); - sinon.stub(helper, 'previewUpgrade').callsArgWith(1, null, true); - sinon.stub(helper, 'moveOldProjectToLegacyFolder'); - sinon.stub(helper, 'createV2ProjectSkeletonAndLoadModel'); - sinon.stub(path, 'join').withArgs( - process.cwd(), CONSTANTS.FILE_PATH.ASK_RESOURCES_JSON_CONFIG - ).returns(FIXTURE_HOSTED_SKILL_RESOURCES_CONFIG); - path.join.callThrough(); - sinon.stub(helper, 'downloadSkillPackage').callsArgWith(5, TEST_ERROR); - // call - instance.handle(TEST_CMD, (err) => { - // verify - expect(err).equal(TEST_ERROR); - expect(errorStub.args[0][0]).equal(TEST_ERROR); - expect(infoStub.callCount).equal(0); - expect(warnStub.callCount).equal(0); - done(); - }); - }); - - it('| hostedSkillHelper handle existing Lambda code fails, expect throw error', (done) => { - // setup - const TEST_USER_INPUT = { - skillId: TEST_SKILL_ID - }; - sinon.stub(helper, 'extractUpgradeInformation').returns(TEST_USER_INPUT); - sinon.stub(helper, 'previewUpgrade').callsArgWith(1, null, true); - sinon.stub(helper, 'moveOldProjectToLegacyFolder'); - sinon.stub(helper, 'createV2ProjectSkeletonAndLoadModel'); - sinon.stub(path, 'join').withArgs( - process.cwd(), CONSTANTS.FILE_PATH.ASK_RESOURCES_JSON_CONFIG - ).returns(FIXTURE_HOSTED_SKILL_RESOURCES_CONFIG); - path.join.callThrough(); - sinon.stub(helper, 'downloadSkillPackage').callsArgWith(5, null); - sinon.stub(helper, 'handleExistingLambdaCode').throws(new CLiError(TEST_ERROR)); - // call - instance.handle(TEST_CMD, (err) => { - // verify - expect(err.message).equal(TEST_ERROR); - expect(errorStub.args[0][0].message).equal(TEST_ERROR); - expect(infoStub.callCount).equal(0); - expect(warnStub.callCount).equal(0); - done(); - }); - }); - - it('| hosted skill project migration succeeds , expect no error thrown', (done) => { - // setup - const TEST_USER_INPUT = { - skillId: TEST_SKILL_ID - }; - sinon.stub(helper, 'extractUpgradeInformation').returns(TEST_USER_INPUT); - sinon.stub(helper, 'previewUpgrade').callsArgWith(1, null, true); - sinon.stub(helper, 'moveOldProjectToLegacyFolder'); - sinon.stub(helper, 'createV2ProjectSkeletonAndLoadModel'); - sinon.stub(path, 'join').withArgs( - process.cwd(), CONSTANTS.FILE_PATH.ASK_RESOURCES_JSON_CONFIG - ).returns(FIXTURE_HOSTED_SKILL_RESOURCES_CONFIG); - path.join.callThrough(); - sinon.stub(helper, 'downloadSkillPackage').callsArgWith(5, null); - sinon.stub(helper, 'handleExistingLambdaCode'); - // call - instance.handle(TEST_CMD, (err) => { - // verify - expect(err).equal(undefined); - expect(infoStub.args[0][0]).equal('Project migration finished.'); - expect(errorStub.callCount).equal(0); - expect(warnStub.callCount).equal(0); - done(); - }); - }); - }); - }); -}); diff --git a/test/unit/commands/util/upgrade-project/index-test.ts b/test/unit/commands/util/upgrade-project/index-test.ts new file mode 100644 index 00000000..51b86886 --- /dev/null +++ b/test/unit/commands/util/upgrade-project/index-test.ts @@ -0,0 +1,468 @@ +import {expect} from "chai"; +import path from "path"; +import sinon from "sinon"; +import UpgradeProjectCommand from "../../../../../lib/commands/util/upgrade-project/index"; +import helper from "../../../../../lib/commands/util/upgrade-project/helper"; +import hostedSkillHelper from "../../../../../lib/commands/util/upgrade-project/hosted-skill-helper"; +import optionModel from "../../../../../lib/commands/option-model.json"; +import CLiError from "../../../../../lib/exceptions/cli-error"; +import Messenger from "../../../../../lib/view/messenger"; +import profileHelper from "../../../../../lib/utils/profile-helper"; +import CONSTANTS from "../../../../../lib/utils/constants"; +import {OptionModel} from "../../../../../lib/commands/option-validator"; + +describe("Commands upgrade project test - command class test", () => { + const FIXTURE_HOSTED_SKILL_RESOURCES_CONFIG = path.join( + process.cwd(), + "test", + "unit", + "fixture", + "model", + "hosted-proj", + "ask-resources.json", + ); + const TEST_PROFILE = "default"; + const TEST_ERROR = "upgrade project error"; + const TEST_SKILL_ID = "skillId"; + const TEST_V1_CONFIG = {}; + let infoStub: sinon.SinonStub; + let errorStub: sinon.SinonStub; + let warnStub: sinon.SinonStub; + + beforeEach(() => { + infoStub = sinon.stub(); + errorStub = sinon.stub(); + warnStub = sinon.stub(); + sinon.stub(Messenger, "getInstance").returns({ + info: infoStub, + error: errorStub, + warn: warnStub, + }); + }); + + afterEach(() => { + sinon.restore(); + }); + + it("| validate command information is set correctly", () => { + const instance = new UpgradeProjectCommand(optionModel as OptionModel); + expect(instance.name()).equal("upgrade-project"); + expect(instance.description()).equal("upgrade the v1 ask-cli skill project to v2 structure"); + expect(instance.requiredOptions()).deep.equal([]); + expect(instance.optionalOptions()).deep.equal(["profile", "debug"]); + }); + + describe("validate command handle", () => { + const TEST_CMD = { + profile: TEST_PROFILE, + }; + + describe("command handle - pre upgrade check", () => { + let instance: UpgradeProjectCommand; + let profileHelperRuntimeProfileStub: sinon.SinonStub; + let helperLoadV1ProjConfigStub: sinon.SinonStub; + let helperAttemptUpgradeUndeployedProjectStub: sinon.SinonStub; + + beforeEach(() => { + instance = new UpgradeProjectCommand(optionModel as OptionModel); + profileHelperRuntimeProfileStub = sinon.stub(profileHelper, "runtimeProfile").returns(TEST_PROFILE); + helperLoadV1ProjConfigStub = sinon.stub(helper, "loadV1ProjConfig").returns({ + isDeployed: true, + v1Config: TEST_V1_CONFIG, + }); + helperAttemptUpgradeUndeployedProjectStub = sinon.stub(helper, "attemptUpgradeUndeployedProject"); + }); + + afterEach(() => { + sinon.restore(); + }); + + it("| when profile is not correct, expect throw error", async () => { + // setup + profileHelperRuntimeProfileStub.throws(new Error(TEST_ERROR)); + // call + await expect(instance.handle(TEST_CMD)).rejectedWith(TEST_ERROR); + // verify + expect(errorStub).calledOnceWith(sinon.match({message: TEST_ERROR})); + expect(infoStub).not.called; + expect(warnStub).not.called; + }); + + it("| when loadV1ProjConfig throws, expect error displayed", async () => { + // setup + helperLoadV1ProjConfigStub.throws(new Error(TEST_ERROR)); + // call + await expect(instance.handle(TEST_CMD)).rejectedWith(TEST_ERROR); + // verify + expect(errorStub).calledOnceWith(sinon.match({message: TEST_ERROR})); + expect(infoStub).not.called; + expect(warnStub).not.called; + }); + + it("| when attemptUpgradeUndeployedProject throws, expect error displayed", async () => { + // setup + helperLoadV1ProjConfigStub.returns({isDeployed: false}); + helperAttemptUpgradeUndeployedProjectStub.throws(new Error(TEST_ERROR)); + // call + await expect(instance.handle(TEST_CMD)).rejectedWith(TEST_ERROR); + // verify + expect(errorStub).calledOnceWith(sinon.match({message: TEST_ERROR})); + expect(infoStub).not.called; + expect(warnStub).not.called; + }); + + it("| when project is undeployed project, expect project will get updated directly", async () => { + // setup + helperLoadV1ProjConfigStub.returns({isDeployed: false}); + // call + await instance.handle(TEST_CMD); + // verify + expect(infoStub).calledOnceWith("Template project migration finished."); + expect(errorStub).not.called; + expect(warnStub).not.called; + }); + + it("| when extract upgrade information fails, expect throw error", async () => { + // setup + sinon.stub(helper, "extractUpgradeInformation").throws(new CLiError(TEST_ERROR)); + // call + await expect(instance.handle(TEST_CMD)).rejectedWith(TEST_ERROR); + // verify + expect(errorStub).calledOnceWith(sinon.match({message: TEST_ERROR})); + expect(infoStub).not.called; + expect(warnStub).not.called; + }); + + it("| helper preview upgrade fails, expect throw error", async () => { + // setup + sinon.stub(helper, "extractUpgradeInformation"); + sinon.stub(helper, "previewUpgrade").callsArgWith(1, TEST_ERROR); + // call + await expect(instance.handle(TEST_CMD)).rejectedWith(TEST_ERROR); + // verify + expect(errorStub).calledOnceWith(TEST_ERROR); + expect(infoStub).not.called; + expect(warnStub).not.called; + }); + + it("| helper preview Upgrade without previewConfirm, expect throw information", async () => { + // setup + sinon.stub(helper, "extractUpgradeInformation"); + sinon.stub(helper, "previewUpgrade").callsArgWith(1, null, null); + // call + await instance.handle(TEST_CMD); + // verify + expect(infoStub).calledOnceWith("Command upgrade-project aborted."); + expect(errorStub).not.called; + expect(warnStub).not.called; + }); + }); + + describe("command handle - create V2 hosted skill project", () => { + let instance: UpgradeProjectCommand; + + beforeEach(() => { + instance = new UpgradeProjectCommand(optionModel as OptionModel); + sinon.stub(profileHelper, "runtimeProfile").returns(TEST_PROFILE); + sinon.stub(helper, "loadV1ProjConfig").returns({ + isDeployed: true, + v1Config: TEST_V1_CONFIG, + }); + }); + + afterEach(() => { + sinon.restore(); + }); + + it("| hostedSkillHelper check If Dev Branch Clean fails, expect throw error", async () => { + // setup + const TEST_USER_INPUT = { + isHosted: true, + skillId: TEST_SKILL_ID, + gitRepoUrl: undefined, + lambdaResources: {}, + } as any; + sinon.stub(helper, "extractUpgradeInformation").returns(TEST_USER_INPUT); + sinon.stub(helper, "previewUpgrade").callsArgWith(1, null, true); + sinon.stub(hostedSkillHelper, "checkIfDevBranchClean").throws(new CLiError(TEST_ERROR)); + // call + await expect(instance.handle(TEST_CMD)).rejectedWith(TEST_ERROR); + // verify + expect(errorStub).calledOnceWith(sinon.match({message: TEST_ERROR})); + expect(infoStub).not.called; + expect(warnStub).not.called; + }); + + it("| helper move old project to legacy folder fails, expect throw error", async () => { + // setup + const TEST_USER_INPUT = { + isHosted: true, + skillId: TEST_SKILL_ID, + gitRepoUrl: "", + }; + sinon.stub(helper, "extractUpgradeInformation").returns(TEST_USER_INPUT); + sinon.stub(helper, "previewUpgrade").callsArgWith(1, null, true); + sinon.stub(hostedSkillHelper, "checkIfDevBranchClean"); + sinon.stub(helper, "moveOldProjectToLegacyFolder").throws(new CLiError(TEST_ERROR)); + // call + await expect(instance.handle(TEST_CMD)).rejectedWith(TEST_ERROR); + // verify + expect(errorStub).calledOnceWith(sinon.match({message: TEST_ERROR})); + expect(infoStub).not.called; + expect(warnStub).not.called; + }); + + it("| hostedSkillHelper create V2 project skeleton fails, expect throw error", async () => { + // setup + const TEST_USER_INPUT = { + isHosted: true, + skillId: TEST_SKILL_ID, + gitRepoUrl: "", + }; + sinon.stub(helper, "extractUpgradeInformation").returns(TEST_USER_INPUT); + sinon.stub(helper, "previewUpgrade").callsArgWith(1, null, true); + sinon.stub(hostedSkillHelper, "checkIfDevBranchClean"); + sinon.stub(helper, "moveOldProjectToLegacyFolder"); + sinon.stub(hostedSkillHelper, "createV2ProjectSkeletonAndLoadModel").throws(new CLiError(TEST_ERROR)); + // call + await expect(instance.handle(TEST_CMD)).rejectedWith(TEST_ERROR); + // verify + expect(errorStub).calledOnceWith(sinon.match({message: TEST_ERROR})); + expect(infoStub).not.called; + expect(warnStub).not.called; + }); + + it("| hostedSkillHelper download skill package fails, expect throw error", async () => { + // setup + const TEST_USER_INPUT = { + isHosted: true, + skillId: TEST_SKILL_ID, + gitRepoUrl: "", + }; + sinon.stub(helper, "extractUpgradeInformation").returns(TEST_USER_INPUT); + sinon.stub(helper, "previewUpgrade").callsArgWith(1, null, true); + sinon.stub(hostedSkillHelper, "checkIfDevBranchClean"); + sinon.stub(helper, "moveOldProjectToLegacyFolder"); + sinon.stub(hostedSkillHelper, "createV2ProjectSkeletonAndLoadModel"); + const pathStub = sinon + .stub(path, "join") + .withArgs(process.cwd(), CONSTANTS.FILE_PATH.ASK_RESOURCES_JSON_CONFIG) + .returns(FIXTURE_HOSTED_SKILL_RESOURCES_CONFIG); + pathStub.callThrough(); + sinon.stub(hostedSkillHelper, "downloadSkillPackage").callsArgWith(5, TEST_ERROR); + // call + await expect(instance.handle(TEST_CMD)).rejectedWith(TEST_ERROR); + // verify + expect(errorStub).calledOnceWith(TEST_ERROR); + expect(infoStub).not.called; + expect(warnStub).not.called; + }); + + it("| hostedSkillHelper handle existing Lambda code fails, expect throw error", async () => { + // setup + const TEST_USER_INPUT = { + isHosted: true, + skillId: TEST_SKILL_ID, + gitRepoUrl: "", + }; + sinon.stub(helper, "extractUpgradeInformation").returns(TEST_USER_INPUT); + sinon.stub(helper, "previewUpgrade").callsArgWith(1, null, true); + sinon.stub(hostedSkillHelper, "checkIfDevBranchClean"); + sinon.stub(hostedSkillHelper, "postUpgradeGitSetup"); + sinon.stub(helper, "moveOldProjectToLegacyFolder"); + sinon.stub(hostedSkillHelper, "createV2ProjectSkeletonAndLoadModel"); + const pathStub = sinon + .stub(path, "join") + .withArgs(process.cwd(), CONSTANTS.FILE_PATH.ASK_RESOURCES_JSON_CONFIG) + .returns(FIXTURE_HOSTED_SKILL_RESOURCES_CONFIG); + pathStub.callThrough(); + sinon.stub(hostedSkillHelper, "downloadSkillPackage").callsArgWith(5, null); + sinon.stub(hostedSkillHelper, "handleExistingLambdaCode").throws(new CLiError(TEST_ERROR)); + // call + await expect(instance.handle(TEST_CMD)).rejectedWith(TEST_ERROR); + // verify + expect(errorStub).calledOnceWith(sinon.match({message: TEST_ERROR})); + expect(infoStub).not.called; + expect(warnStub).not.called; + }); + + it("| hostedSkillHelper post Upgrade Git Setup fails , expect no error thrown", async () => { + // setup + const TEST_USER_INPUT = { + isHosted: true, + skillId: TEST_SKILL_ID, + gitRepoUrl: "", + }; + sinon.stub(helper, "extractUpgradeInformation").returns(TEST_USER_INPUT); + sinon.stub(helper, "previewUpgrade").callsArgWith(1, null, true); + sinon.stub(hostedSkillHelper, "checkIfDevBranchClean"); + sinon.stub(helper, "moveOldProjectToLegacyFolder"); + sinon.stub(hostedSkillHelper, "createV2ProjectSkeletonAndLoadModel"); + sinon.stub(path, "join").returns(FIXTURE_HOSTED_SKILL_RESOURCES_CONFIG); + sinon.stub(hostedSkillHelper, "downloadSkillPackage").callsArgWith(5, null); + sinon.stub(hostedSkillHelper, "handleExistingLambdaCode"); + sinon.stub(hostedSkillHelper, "postUpgradeGitSetup").callsArgWith(5, TEST_ERROR); + // call + await expect(instance.handle(TEST_CMD)).rejectedWith(TEST_ERROR); + // verify + expect(errorStub).calledOnceWith(TEST_ERROR); + expect(infoStub).not.called; + expect(warnStub).not.called; + }); + + it("| hosted skill project migration succeeds , expect no error thrown", async () => { + // setup + const TEST_USER_INPUT = { + isHosted: true, + skillId: TEST_SKILL_ID, + gitRepoUrl: "", + }; + sinon.stub(helper, "extractUpgradeInformation").returns(TEST_USER_INPUT); + sinon.stub(helper, "previewUpgrade").callsArgWith(1, null, true); + sinon.stub(hostedSkillHelper, "checkIfDevBranchClean"); + sinon.stub(helper, "moveOldProjectToLegacyFolder"); + sinon.stub(hostedSkillHelper, "createV2ProjectSkeletonAndLoadModel"); + const pathStub = sinon + .stub(path, "join") + .withArgs(process.cwd(), CONSTANTS.FILE_PATH.ASK_RESOURCES_JSON_CONFIG) + .returns(FIXTURE_HOSTED_SKILL_RESOURCES_CONFIG); + pathStub.callThrough(); + sinon.stub(hostedSkillHelper, "downloadSkillPackage").callsArgWith(5, null); + sinon.stub(hostedSkillHelper, "handleExistingLambdaCode"); + sinon.stub(hostedSkillHelper, "postUpgradeGitSetup").callsArgWith(5, null); + // call + await instance.handle(TEST_CMD); + // verify + expect(infoStub).calledOnceWith("Project migration finished."); + expect(errorStub).not.called; + expect(warnStub).not.called; + }); + }); + + describe("command handle - create V2 Non hosted skill project", () => { + let instance: UpgradeProjectCommand; + + beforeEach(() => { + instance = new UpgradeProjectCommand(optionModel as OptionModel); + sinon.stub(profileHelper, "runtimeProfile").returns(TEST_PROFILE); + sinon.stub(helper, "loadV1ProjConfig").returns({ + isDeployed: true, + v1Config: TEST_V1_CONFIG, + }); + }); + + afterEach(() => { + sinon.restore(); + }); + + it("| helper move old project to legacy folder fails, expect throw error", async () => { + // setup + const TEST_USER_INPUT = { + skillId: TEST_SKILL_ID, + lambdaResources: undefined, + } as any; + sinon.stub(helper, "extractUpgradeInformation").returns(TEST_USER_INPUT); + sinon.stub(helper, "previewUpgrade").callsArgWith(1, null, true); + sinon.stub(helper, "moveOldProjectToLegacyFolder").throws(new CLiError(TEST_ERROR)); + // call + await expect(instance.handle(TEST_CMD)).rejectedWith(TEST_ERROR); + // verify + expect(errorStub).calledOnceWith(sinon.match({message: TEST_ERROR})); + expect(infoStub).not.called; + expect(warnStub).not.called; + }); + + it("| helper create V2 project skeleton fails, expect throw error", async () => { + // setup + const TEST_USER_INPUT = { + skillId: TEST_SKILL_ID, + lambdaResources: undefined, + } as any; + sinon.stub(helper, "extractUpgradeInformation").returns(TEST_USER_INPUT); + sinon.stub(helper, "previewUpgrade").callsArgWith(1, null, true); + sinon.stub(helper, "moveOldProjectToLegacyFolder"); + sinon.stub(helper, "createV2ProjectSkeletonAndLoadModel").throws(new CLiError(TEST_ERROR)); + // call + await expect(instance.handle(TEST_CMD)).rejectedWith(TEST_ERROR); + // verify + expect(errorStub).calledOnceWith(sinon.match({message: TEST_ERROR})); + expect(infoStub).not.called; + expect(warnStub).not.called; + }); + + it("| helper download skill package fails, expect throw error", async () => { + // setup + const TEST_USER_INPUT = { + skillId: TEST_SKILL_ID, + lambdaResources: undefined, + } as any; + sinon.stub(helper, "extractUpgradeInformation").returns(TEST_USER_INPUT); + sinon.stub(helper, "previewUpgrade").callsArgWith(1, null, true); + sinon.stub(helper, "moveOldProjectToLegacyFolder"); + sinon.stub(helper, "createV2ProjectSkeletonAndLoadModel"); + const pathStub = sinon + .stub(path, "join") + .withArgs(process.cwd(), CONSTANTS.FILE_PATH.ASK_RESOURCES_JSON_CONFIG) + .returns(FIXTURE_HOSTED_SKILL_RESOURCES_CONFIG); + pathStub.callThrough(); + sinon.stub(helper, "downloadSkillPackage").callsArgWith(5, TEST_ERROR); + // call + await expect(instance.handle(TEST_CMD)).rejectedWith(TEST_ERROR); + // verify + expect(errorStub).calledOnceWith(TEST_ERROR); + expect(infoStub).not.called; + expect(warnStub).not.called; + }); + + it("| hostedSkillHelper handle existing Lambda code fails, expect throw error", async () => { + // setup + const TEST_USER_INPUT = { + skillId: TEST_SKILL_ID, + lambdaResources: undefined, + } as any; + sinon.stub(helper, "extractUpgradeInformation").returns(TEST_USER_INPUT); + sinon.stub(helper, "previewUpgrade").callsArgWith(1, null, true); + sinon.stub(helper, "moveOldProjectToLegacyFolder"); + sinon.stub(helper, "createV2ProjectSkeletonAndLoadModel"); + const pathStub = sinon + .stub(path, "join") + .withArgs(process.cwd(), CONSTANTS.FILE_PATH.ASK_RESOURCES_JSON_CONFIG) + .returns(FIXTURE_HOSTED_SKILL_RESOURCES_CONFIG); + pathStub.callThrough(); + sinon.stub(helper, "downloadSkillPackage").callsArgWith(5, null); + sinon.stub(helper, "handleExistingLambdaCode").throws(new CLiError(TEST_ERROR)); + // call + await expect(instance.handle(TEST_CMD)).rejectedWith(TEST_ERROR); + // verify + expect(errorStub).calledOnceWith(sinon.match({message: TEST_ERROR})); + expect(infoStub).not.called; + expect(warnStub).not.called; + }); + + it("| hosted skill project migration succeeds , expect no error thrown", async () => { + // setup + const TEST_USER_INPUT = { + skillId: TEST_SKILL_ID, + lambdaResources: undefined, + } as any; + sinon.stub(helper, "extractUpgradeInformation").returns(TEST_USER_INPUT); + sinon.stub(helper, "previewUpgrade").callsArgWith(1, null, true); + sinon.stub(helper, "moveOldProjectToLegacyFolder"); + sinon.stub(helper, "createV2ProjectSkeletonAndLoadModel"); + const pathStub = sinon + .stub(path, "join") + .withArgs(process.cwd(), CONSTANTS.FILE_PATH.ASK_RESOURCES_JSON_CONFIG) + .returns(FIXTURE_HOSTED_SKILL_RESOURCES_CONFIG); + pathStub.callThrough(); + sinon.stub(helper, "downloadSkillPackage").callsArgWith(5, null); + sinon.stub(helper, "handleExistingLambdaCode"); + // call + await instance.handle(TEST_CMD); + // verify + expect(infoStub).calledOnceWith("Project migration finished."); + expect(errorStub).not.called; + expect(warnStub).not.called; + }); + }); + }); +}); diff --git a/test/unit/commands/util/upgrade-project/ui-test.js b/test/unit/commands/util/upgrade-project/ui-test.js index aca24ba0..879538ec 100644 --- a/test/unit/commands/util/upgrade-project/ui-test.js +++ b/test/unit/commands/util/upgrade-project/ui-test.js @@ -1,159 +1,159 @@ -const { expect } = require('chai'); -const inquirer = require('inquirer'); -const path = require('path'); -const sinon = require('sinon'); +const {expect} = require("chai"); +const inquirer = require("inquirer"); +const path = require("path"); +const sinon = require("sinon"); -const Messenger = require('@src/view/messenger'); -const CONSTANTS = require('@src/utils/constants'); +const Messenger = require("../../../../../lib/view/messenger"); +const CONSTANTS = require("../../../../../lib/utils/constants"); -const ui = require('@src/commands/util/upgrade-project/ui'); +const ui = require("../../../../../lib/commands/util/upgrade-project/ui"); function validateInquirerConfig(stub, expectedConfig) { - const { message, type, defaultValue, choices } = expectedConfig; - expect(stub.message).equal(message); - expect(stub.type).equal(type); - if (defaultValue) { - expect(stub.default).equal(defaultValue); - } - if (choices) { - expect(stub.choices).deep.equal(choices); - } + const {message, type, defaultValue, choices} = expectedConfig; + expect(stub.message).equal(message); + expect(stub.type).equal(type); + if (defaultValue) { + expect(stub.default).equal(defaultValue); + } + if (choices) { + expect(stub.choices).deep.equal(choices); + } } -describe('Commands upgrade-project test - UI test', () => { - const TEST_ERROR = 'upgrade-project error'; - const TEST_REGION = 'default'; - const TEST_REGION_NA = 'NA'; - const TEST_CODE_URI = 'codeUri'; - const TEST_V2_CODE_URI = `${CONSTANTS.FILE_PATH.SKILL_CODE.LAMBDA}/${TEST_CODE_URI}`; - const TEST_RUNTIME = 'runtime'; - const TEST_HANDLER = 'handler'; - const TEST_REVISION_ID = 'revisionId'; - const TEST_ARN = 'arn:aws:lambda:us-west-2:123456789012:function:ask-custom-skill-sample-nodejs-fact-default'; +describe("Commands upgrade-project test - UI test", () => { + const TEST_ERROR = "upgrade-project error"; + const TEST_REGION = "default"; + const TEST_REGION_NA = "NA"; + const TEST_CODE_URI = "codeUri"; + const TEST_V2_CODE_URI = `${CONSTANTS.FILE_PATH.SKILL_CODE.LAMBDA}/${TEST_CODE_URI}`; + const TEST_RUNTIME = "runtime"; + const TEST_HANDLER = "handler"; + const TEST_REVISION_ID = "revisionId"; + const TEST_ARN = "arn:aws:lambda:us-west-2:123456789012:function:ask-custom-skill-sample-nodejs-fact-default"; - new Messenger({}); - let infoStub; + new Messenger({}); + let infoStub; - describe('# validate ui.displayPreview', () => { - const TEST_SKILL_ID = 'skillId'; - const TEST_UPDATE_PREVIEW_PART_1 = `Preview of the upgrade result from v1 to v2: + describe("# validate ui.displayPreview", () => { + const TEST_SKILL_ID = "skillId"; + const TEST_UPDATE_PREVIEW_PART_1 = `Preview of the upgrade result from v1 to v2: - The original v1 skill project will be entirely moved to .${path.sep}${CONSTANTS.FILE_PATH.LEGACY_PATH}${path.sep} - JSON files for Skill ID ${TEST_SKILL_ID} (such as skill.json) will be moved to .${path.sep}${CONSTANTS.FILE_PATH.SKILL_PACKAGE.PACKAGE}${path.sep} `; - beforeEach(() => { - infoStub = sinon.stub(); - sinon.stub(Messenger, 'getInstance').returns({ - info: infoStub - }); - }); + beforeEach(() => { + infoStub = sinon.stub(); + sinon.stub(Messenger, "getInstance").returns({ + info: infoStub, + }); + }); - afterEach(() => { - sinon.restore(); - }); + afterEach(() => { + sinon.restore(); + }); - it('| Preview hosted skill project display', () => { - // setup - const TEST_USER_INPUT = { - skillId: TEST_SKILL_ID, - isHosted: true - }; - const TEST_PART_2 = `- Existing Lambda codebase will be moved into "${CONSTANTS.FILE_PATH.SKILL_CODE.LAMBDA}" folder`; - // call - ui.displayPreview(TEST_USER_INPUT); - // verify - expect(infoStub.args[0][0]).equal(TEST_UPDATE_PREVIEW_PART_1 + TEST_PART_2); - }); + it("| Preview hosted skill project display", () => { + // setup + const TEST_USER_INPUT = { + skillId: TEST_SKILL_ID, + isHosted: true, + }; + const TEST_PART_2 = `- Existing Lambda codebase will be moved into "${CONSTANTS.FILE_PATH.SKILL_CODE.LAMBDA}" folder`; + // call + ui.displayPreview(TEST_USER_INPUT); + // verify + expect(infoStub.args[0][0]).equal(TEST_UPDATE_PREVIEW_PART_1 + TEST_PART_2); + }); - it('| Preview no lambda project display', () => { - // setup - const TEST_USER_INPUT = { - skillId: TEST_SKILL_ID, - isHosted: false - }; - const TEST_PART_2 = '- No existing Lambda in the v1 "lambda" resource thus no action for Lambda codebase.'; - // call - ui.displayPreview(TEST_USER_INPUT); - // verify - expect(infoStub.args[0][0]).equal(TEST_UPDATE_PREVIEW_PART_1 + TEST_PART_2); - }); + it("| Preview no lambda project display", () => { + // setup + const TEST_USER_INPUT = { + skillId: TEST_SKILL_ID, + isHosted: false, + }; + const TEST_PART_2 = '- No existing Lambda in the v1 "lambda" resource thus no action for Lambda codebase.'; + // call + ui.displayPreview(TEST_USER_INPUT); + // verify + expect(infoStub.args[0][0]).equal(TEST_UPDATE_PREVIEW_PART_1 + TEST_PART_2); + }); - it('| Preview multiple regions project display', () => { - // setup - const TEST_USER_INPUT = { - skillId: TEST_SKILL_ID, - isHosted: false, - lambdaResources: { - [TEST_REGION]: { - arn: TEST_ARN, - codeUri: TEST_CODE_URI, - runtime: TEST_RUNTIME, - handler: TEST_HANDLER, - v2CodeUri: `.${path.sep}${TEST_V2_CODE_URI}`, - revisionId: TEST_REVISION_ID - }, - [TEST_REGION_NA]: { - codeUri: TEST_CODE_URI, - runtime: TEST_RUNTIME, - handler: TEST_HANDLER, - v2CodeUri: `.${path.sep}${TEST_V2_CODE_URI}`, - revisionId: TEST_REVISION_ID - } - } - }; - const TEST_PART_2 = `- Existing Lambda codebase will be moved into "${CONSTANTS.FILE_PATH.SKILL_CODE.LAMBDA}" folder`; - const TEST_PART_2_1 = `\n - Region ${TEST_REGION}: v1 "${TEST_CODE_URI}"\ + it("| Preview multiple regions project display", () => { + // setup + const TEST_USER_INPUT = { + skillId: TEST_SKILL_ID, + isHosted: false, + lambdaResources: { + [TEST_REGION]: { + arn: TEST_ARN, + codeUri: TEST_CODE_URI, + runtime: TEST_RUNTIME, + handler: TEST_HANDLER, + v2CodeUri: `.${path.sep}${TEST_V2_CODE_URI}`, + revisionId: TEST_REVISION_ID, + }, + [TEST_REGION_NA]: { + codeUri: TEST_CODE_URI, + runtime: TEST_RUNTIME, + handler: TEST_HANDLER, + v2CodeUri: `.${path.sep}${TEST_V2_CODE_URI}`, + revisionId: TEST_REVISION_ID, + }, + }, + }; + const TEST_PART_2 = `- Existing Lambda codebase will be moved into "${CONSTANTS.FILE_PATH.SKILL_CODE.LAMBDA}" folder`; + const TEST_PART_2_1 = `\n - Region ${TEST_REGION}: v1 "${TEST_CODE_URI}"\ -> v2 ".${path.sep}${TEST_V2_CODE_URI}" for existing Lambda ARN ${TEST_ARN}`; - const TEST_PART_2_2 = `\n - Region ${TEST_REGION_NA}: v1 "${TEST_CODE_URI}"\ + const TEST_PART_2_2 = `\n - Region ${TEST_REGION_NA}: v1 "${TEST_CODE_URI}"\ -> v2 ".${path.sep}${TEST_V2_CODE_URI}" and will create new Lambda`; - // call - ui.displayPreview(TEST_USER_INPUT); - // verify - expect(infoStub.args[0][0]).equal(TEST_UPDATE_PREVIEW_PART_1 + TEST_PART_2 + TEST_PART_2_1 + TEST_PART_2_2); - }); + // call + ui.displayPreview(TEST_USER_INPUT); + // verify + expect(infoStub.args[0][0]).equal(TEST_UPDATE_PREVIEW_PART_1 + TEST_PART_2 + TEST_PART_2_1 + TEST_PART_2_2); }); + }); - describe('# validate ui.displayPreview', () => { - beforeEach(() => { - sinon.stub(inquirer, 'prompt'); - }); + describe("# validate ui.displayPreview", () => { + beforeEach(() => { + sinon.stub(inquirer, "prompt"); + }); - afterEach(() => { - sinon.restore(); - }); + afterEach(() => { + sinon.restore(); + }); - it('| confirm preview from user but error happens', (done) => { - // setup - inquirer.prompt.rejects(TEST_ERROR); - // call - ui.confirmPreview((err, response) => { - // verify - validateInquirerConfig(inquirer.prompt.args[0][0], { - message: 'Do you want to execute the upgrade based on the preview above? ', - type: 'confirm', - default: true, - }); - expect(err.name).equal(TEST_ERROR); - expect(response).equal(undefined); - done(); - }); + it("| confirm preview from user but error happens", (done) => { + // setup + inquirer.prompt.rejects(TEST_ERROR); + // call + ui.confirmPreview((err, response) => { + // verify + validateInquirerConfig(inquirer.prompt.args[0][0], { + message: "Do you want to execute the upgrade based on the preview above? ", + type: "confirm", + default: true, }); + expect(err.name).equal(TEST_ERROR); + expect(response).equal(undefined); + done(); + }); + }); - it('| confirm overwrite from user inputs', (done) => { - // setup - inquirer.prompt.resolves({ confirmPreview: true }); - // call - ui.confirmPreview((err, response) => { - // verify - validateInquirerConfig(inquirer.prompt.args[0][0], { - message: 'Do you want to execute the upgrade based on the preview above? ', - type: 'confirm', - default: true, - }); - expect(err).equal(null); - expect(response).equal(true); - done(); - }); + it("| confirm overwrite from user inputs", (done) => { + // setup + inquirer.prompt.resolves({confirmPreview: true}); + // call + ui.confirmPreview((err, response) => { + // verify + validateInquirerConfig(inquirer.prompt.args[0][0], { + message: "Do you want to execute the upgrade based on the preview above? ", + type: "confirm", + default: true, }); + expect(err).equal(null); + expect(response).equal(true); + done(); + }); }); + }); }); diff --git a/test/unit/commands/util/util-commander-test.ts b/test/unit/commands/util/util-commander-test.ts new file mode 100644 index 00000000..88514c11 --- /dev/null +++ b/test/unit/commands/util/util-commander-test.ts @@ -0,0 +1,36 @@ +import {commander} from "../../../../lib/commands/util/util-commander"; +import UpdateProjectCommand from "../../../../lib/commands/util/upgrade-project"; +import sinon from "sinon"; +import Messenger from "../../../../lib/view/messenger"; +import httpClient from "../../../../lib/clients/http-client"; + +/** + * Simple test which loads the util commander while running tests. + * This was previously not done and could fail due to changes. + */ +describe("Util Commander Test", () => { + let errorStub, warnStub, infoStub; + + beforeEach(() => { + errorStub = sinon.stub(); + warnStub = sinon.stub(); + infoStub = sinon.stub(); + sinon.stub(Messenger, "getInstance").returns({ + info: infoStub, + warn: warnStub, + error: errorStub, + dispose: sinon.stub(), + }); + sinon.stub(process, "exit"); + sinon.stub(httpClient, "request").yields({statusCode: 200}); + }); + + it("loads and runs a command", async () => { + sinon.stub(UpdateProjectCommand.prototype, "handle").resolves(); + await commander.parseAsync(["something", "something", "upgrade-project"]); + }); + + afterEach(() => { + sinon.restore(); + }); +}); diff --git a/test/unit/controller/authorization-controller/index-test.js b/test/unit/controller/authorization-controller/index-test.js index 025a7934..51faae43 100644 --- a/test/unit/controller/authorization-controller/index-test.js +++ b/test/unit/controller/authorization-controller/index-test.js @@ -1,496 +1,496 @@ -const { expect } = require('chai'); -const sinon = require('sinon'); -const queryString = require('querystring'); -const portscanner = require('portscanner'); -const proxyquire = require('proxyquire'); -const url = require('url'); - -const httpClient = require('@src/clients/http-client'); -const LWAClient = require('@src/clients/lwa-auth-code-client'); -const AuthorizationController = require('@src/controllers/authorization-controller'); -const messages = require('@src/controllers/authorization-controller/messages'); -const AppConfig = require('@src/model/app-config'); -const CONSTANTS = require('@src/utils/constants'); -const LocalHostServer = require('@src/utils/local-host-server'); -const Messenger = require('@src/view/messenger'); -const SpinnerView = require('@src/view/spinner-view'); - - -describe('Controller test - Authorization controller test', () => { - const DEFAULT_CLIENT_ID = CONSTANTS.LWA.CLI_INTERNAL_ONLY_LWA_CLIENT.CLIENT_ID; - const DEFAULT_SCOPE = CONSTANTS.LWA.DEFAULT_SCOPES; - const authorizePath = CONSTANTS.LWA.DEFAULT_AUTHORIZE_PATH; - const authorizeHost = CONSTANTS.LWA.DEFAULT_AUTHORIZE_HOST; - const TEST_TOKEN = 'testToken'; - const TEST_STATE = 'state'; - const TEST_PROFILE = 'testProfile'; - const TEST_ENVIRONMENT_PROFILE = CONSTANTS.PLACEHOLDER.ENVIRONMENT_VAR.PROFILE_NAME; - const TEST_DO_DEBUG = false; - const TEST_NEED_BROWSER = false; - const TEST_ERROR_MESSAGE = 'errorMessage'; - const TEST_AUTH_CODE = 'authCode'; - const TEST_PORT = CONSTANTS.LWA.LOCAL_PORT; - const TEST_ALREADY_EXPIRED_DATE = new Date(); - TEST_ALREADY_EXPIRED_DATE.setFullYear(TEST_ALREADY_EXPIRED_DATE.getFullYear() - 1); - const TEST_ALREADY_EXPIRED_AT = TEST_ALREADY_EXPIRED_DATE.toISOString(); - const TEST_RESPONSE = { - body: { - access_token: 'access_token', - refresh_token: 'refresh_token', - expires_in: 3600, - expires_at: TEST_ALREADY_EXPIRED_AT - } - }; - const currentDatePlusHalfAnHour = new Date(new Date(Date.now()).getTime() + (0.5 * 60 * 60 * 1000)).toISOString(); - const VALID_ACCESS_TOKEN = { - access_token: 'accessToken', - refresh_token: 'refreshToken', - token_type: 'bearer', - expires_in: 3600, - expires_at: currentDatePlusHalfAnHour - }; - const TEST_CONFIG = { - askProfile: TEST_PROFILE, - needBrowser: TEST_NEED_BROWSER, - doDebug: TEST_DO_DEBUG, - auth_client_type: 'LWA', +const {expect} = require("chai"); +const sinon = require("sinon"); +const queryString = require("querystring"); +const portscanner = require("portscanner"); +const proxyquire = require("proxyquire"); +const url = require("url"); + +const httpClient = require("../../../../lib/clients/http-client"); +const LWAClient = require("../../../../lib/clients/lwa-auth-code-client"); +const AuthorizationController = require("../../../../lib/controllers/authorization-controller"); +const messages = require("../../../../lib/controllers/authorization-controller/messages"); +const AppConfig = require("../../../../lib/model/app-config"); +const CONSTANTS = require("../../../../lib/utils/constants"); +const LocalHostServer = require("../../../../lib/utils/local-host-server"); +const Messenger = require("../../../../lib/view/messenger"); +const SpinnerView = require("../../../../lib/view/spinner-view"); + +describe("Controller test - Authorization controller test", () => { + const DEFAULT_CLIENT_ID = CONSTANTS.LWA.CLI_INTERNAL_ONLY_LWA_CLIENT.CLIENT_ID; + const DEFAULT_SCOPE = CONSTANTS.LWA.DEFAULT_SCOPES; + const authorizePath = CONSTANTS.LWA.DEFAULT_AUTHORIZE_PATH; + const authorizeHost = CONSTANTS.LWA.DEFAULT_AUTHORIZE_HOST; + const TEST_TOKEN = "testToken"; + const TEST_STATE = "state"; + const TEST_PROFILE = "testProfile"; + const TEST_ENVIRONMENT_PROFILE = CONSTANTS.PLACEHOLDER.ENVIRONMENT_VAR.PROFILE_NAME; + const TEST_DO_DEBUG = false; + const TEST_NEED_BROWSER = false; + const TEST_ERROR_MESSAGE = "errorMessage"; + const TEST_AUTH_CODE = "authCode"; + const TEST_PORT = CONSTANTS.LWA.LOCAL_PORT; + const TEST_ALREADY_EXPIRED_DATE = new Date(); + TEST_ALREADY_EXPIRED_DATE.setFullYear(TEST_ALREADY_EXPIRED_DATE.getFullYear() - 1); + const TEST_ALREADY_EXPIRED_AT = TEST_ALREADY_EXPIRED_DATE.toISOString(); + const TEST_RESPONSE = { + body: { + access_token: "access_token", + refresh_token: "refresh_token", + expires_in: 3600, + expires_at: TEST_ALREADY_EXPIRED_AT, + }, + }; + const currentDatePlusHalfAnHour = new Date(new Date(Date.now()).getTime() + 0.5 * 60 * 60 * 1000).toISOString(); + const VALID_ACCESS_TOKEN = { + access_token: "accessToken", + refresh_token: "refreshToken", + token_type: "bearer", + expires_in: 3600, + expires_at: currentDatePlusHalfAnHour, + }; + const TEST_CONFIG = { + askProfile: TEST_PROFILE, + needBrowser: TEST_NEED_BROWSER, + doDebug: TEST_DO_DEBUG, + auth_client_type: "LWA", + state: TEST_STATE, + }; + + describe("# test _getAuthClientInstance", () => { + it("| returns undefined", () => { + // setup + const authorizationController = new AuthorizationController({auth_client_type: "UNKNOWN"}); + + // call and verify + expect(authorizationController.oauthClient).eq(undefined); + }); + }); + + describe("# test getAuthorizeUrl", () => { + it("| returns valid authorization url", () => { + // setup + const authorizationController = new AuthorizationController(TEST_CONFIG); + const queryParams = { + response_type: "code", + client_id: DEFAULT_CLIENT_ID, state: TEST_STATE, - }; - - describe('# test _getAuthClientInstance', () => { - it('| returns undefined', () => { - // setup - const authorizationController = new AuthorizationController({ auth_client_type: 'UNKNOWN' }); + scope: DEFAULT_SCOPE, + }; + const uri = `${authorizeHost}${authorizePath}?${queryString.stringify(queryParams)}`; - // call and verify - expect(authorizationController.oauthClient).eq(undefined); - }); + const authUrl = authorizationController.getAuthorizeUrl(); + // call and verify + expect(authUrl).eq(uri); }); + }); - describe('# test getAuthorizeUrl', () => { - it('| returns valid authorization url', () => { - // setup - const authorizationController = new AuthorizationController(TEST_CONFIG); - const queryParams = { - response_type: 'code', - client_id: DEFAULT_CLIENT_ID, - state: TEST_STATE, - scope: DEFAULT_SCOPE - }; - const uri = `${authorizeHost}${authorizePath}?${queryString.stringify(queryParams)}`; - - const authUrl = authorizationController.getAuthorizeUrl(); - // call and verify - expect(authUrl).eq(uri); - }); + describe("# test getAccessTokenUsingAuthCode", () => { + beforeEach(() => { + sinon.stub(httpClient, "request"); }); - describe('# test getAccessTokenUsingAuthCode', () => { - beforeEach(() => { - sinon.stub(httpClient, 'request'); - }); + it("| returns valid access token", (done) => { + // setup + httpClient.request.callsArgWith(3, null, TEST_RESPONSE); + const authorizationController = new AuthorizationController(TEST_CONFIG); + + // call + authorizationController.getAccessTokenUsingAuthCode(TEST_AUTH_CODE, (error, accessToken) => { + // verify + expect(error).eq(null); + expect(accessToken.access_token).to.eq(TEST_RESPONSE.body.access_token); + done(); + }); + }); - it('| returns valid access token', (done) => { - // setup - httpClient.request.callsArgWith(3, null, TEST_RESPONSE); - const authorizationController = new AuthorizationController(TEST_CONFIG); - - // call - authorizationController.getAccessTokenUsingAuthCode(TEST_AUTH_CODE, (error, accessToken) => { - // verify - expect(error).eq(null); - expect(accessToken.access_token).to.eq(TEST_RESPONSE.body.access_token); - done(); - }); - }); + it("| returns error", (done) => { + // setup + httpClient.request.callsArgWith(3, TEST_ERROR_MESSAGE); + const authorizationController = new AuthorizationController(TEST_CONFIG); + + // call + authorizationController.getAccessTokenUsingAuthCode(TEST_AUTH_CODE, (error, response) => { + // verify + expect(error).eq(TEST_ERROR_MESSAGE); + expect(response).eq(TEST_ERROR_MESSAGE); + done(); + }); + }); - it('| returns error', (done) => { - // setup - httpClient.request.callsArgWith(3, TEST_ERROR_MESSAGE); - const authorizationController = new AuthorizationController(TEST_CONFIG); - - // call - authorizationController.getAccessTokenUsingAuthCode(TEST_AUTH_CODE, (error, response) => { - // verify - expect(error).eq(TEST_ERROR_MESSAGE); - expect(response).eq(TEST_ERROR_MESSAGE); - done(); - }); - }); + afterEach(() => { + sinon.restore(); + }); + }); + + describe("# test tokenRefreshAndRead", () => { + let getTokenStub; + const TEST_ENV_ACCESS_TOKEN = "envAccessToken"; + const TEST_ENV_REFRESH_TOKEN = "envRefreshToken"; + const authorizationController = new AuthorizationController(TEST_CONFIG); + + beforeEach(() => { + getTokenStub = sinon.stub(); + sinon.stub(AppConfig, "getInstance").returns({ + getToken: getTokenStub, + }); + sinon.stub(httpClient, "request"); + }); - afterEach(() => { - sinon.restore(); - }); + afterEach(() => { + sinon.restore(); + delete process.env.ASK_REFRESH_TOKEN; + delete process.env.ASK_ACCESS_TOKEN; }); - describe('# test tokenRefreshAndRead', () => { - let getTokenStub; - const TEST_ENV_ACCESS_TOKEN = 'envAccessToken'; - const TEST_ENV_REFRESH_TOKEN = 'envRefreshToken'; - const authorizationController = new AuthorizationController(TEST_CONFIG); - - beforeEach(() => { - getTokenStub = sinon.stub(); - sinon.stub(AppConfig, 'getInstance').returns({ - getToken: getTokenStub - }); - sinon.stub(httpClient, 'request'); + describe("# returns valid token", () => { + it("| non-environment profile, expired access token", (done) => { + // setup + getTokenStub.withArgs(TEST_PROFILE).returns(TEST_RESPONSE.body); + sinon + .stub(AuthorizationController.prototype, "_getRefreshTokenAndUpdateConfig") + .callsArgWith(2, null, VALID_ACCESS_TOKEN.access_token); + + // call + authorizationController.tokenRefreshAndRead(TEST_PROFILE, (error, accessToken) => { + // verify + expect(error).eq(null); + expect(accessToken).to.equal(VALID_ACCESS_TOKEN.access_token); + done(); }); - - afterEach(() => { - sinon.restore(); - delete process.env.ASK_REFRESH_TOKEN; - delete process.env.ASK_ACCESS_TOKEN; + }); + + it("| non-environment profile, valid access token", (done) => { + // setup + getTokenStub.withArgs(TEST_PROFILE).returns(VALID_ACCESS_TOKEN); + + // call + authorizationController.tokenRefreshAndRead(TEST_PROFILE, (error, accessToken) => { + // verify + expect(error).eq(null); + expect(accessToken).to.deep.eq(VALID_ACCESS_TOKEN.access_token); + done(); }); - - describe('# returns valid token', () => { - it('| non-environment profile, expired access token', (done) => { - // setup - getTokenStub.withArgs(TEST_PROFILE).returns(TEST_RESPONSE.body); - sinon.stub(AuthorizationController.prototype, '_getRefreshTokenAndUpdateConfig') - .callsArgWith(2, null, VALID_ACCESS_TOKEN.access_token); - - // call - authorizationController.tokenRefreshAndRead(TEST_PROFILE, (error, accessToken) => { - // verify - expect(error).eq(null); - expect(accessToken).to.equal(VALID_ACCESS_TOKEN.access_token); - done(); - }); - }); - - it('| non-environment profile, valid access token', (done) => { - // setup - getTokenStub.withArgs(TEST_PROFILE).returns(VALID_ACCESS_TOKEN); - - // call - authorizationController.tokenRefreshAndRead(TEST_PROFILE, (error, accessToken) => { - // verify - expect(error).eq(null); - expect(accessToken).to.deep.eq(VALID_ACCESS_TOKEN.access_token); - done(); - }); - }); - - it('| environment profile, valid refresh token', (done) => { - // setup - process.env.ASK_REFRESH_TOKEN = TEST_ENV_REFRESH_TOKEN; - sinon.stub(AuthorizationController.prototype, '_getRefreshTokenAndUpdateConfig').callsArgWith(2, null, VALID_ACCESS_TOKEN); - httpClient.request.callsArgWith(3, null, TEST_RESPONSE); - - // call - authorizationController.tokenRefreshAndRead(TEST_ENVIRONMENT_PROFILE, (error, accessToken) => { - // verify - expect(error).eq(null); - expect(accessToken).to.deep.eq(TEST_RESPONSE.body.access_token); - done(); - }); - }); - - it('| environment profile, invalid refresh token, valid access token', (done) => { - // setup - process.env.ASK_ACCESS_TOKEN = TEST_ENV_ACCESS_TOKEN; - // call - authorizationController.tokenRefreshAndRead(TEST_ENVIRONMENT_PROFILE, (error, accessToken) => { - // verify - expect(error).eq(null); - expect(accessToken).to.deep.eq(TEST_ENV_ACCESS_TOKEN); - done(); - }); - }); + }); + + it("| environment profile, valid refresh token", (done) => { + // setup + process.env.ASK_REFRESH_TOKEN = TEST_ENV_REFRESH_TOKEN; + sinon.stub(AuthorizationController.prototype, "_getRefreshTokenAndUpdateConfig").callsArgWith(2, null, VALID_ACCESS_TOKEN); + httpClient.request.callsArgWith(3, null, TEST_RESPONSE); + + // call + authorizationController.tokenRefreshAndRead(TEST_ENVIRONMENT_PROFILE, (error, accessToken) => { + // verify + expect(error).eq(null); + expect(accessToken).to.deep.eq(TEST_RESPONSE.body.access_token); + done(); }); - - describe('# returns error', () => { - it('| non-environment profile, expired access token, _getRefreshTokenAndUpdateConfig fails', (done) => { - // setup - getTokenStub.withArgs(TEST_PROFILE).returns(TEST_RESPONSE.body); - sinon.stub(AuthorizationController.prototype, '_getRefreshTokenAndUpdateConfig').callsArgWith(2, TEST_ERROR_MESSAGE); - - // call - authorizationController.tokenRefreshAndRead(TEST_PROFILE, (error, response) => { - // verify - expect(error).eq(TEST_ERROR_MESSAGE); - expect(response).eq(TEST_ERROR_MESSAGE); - done(); - }); - }); - - it('| environment profile, valid refresh token, refreshing token fails', (done) => { - // setup - process.env.ASK_REFRESH_TOKEN = TEST_ENV_REFRESH_TOKEN; - sinon.stub(AuthorizationController.prototype, '_getRefreshTokenAndUpdateConfig').callsArgWith(2, null, VALID_ACCESS_TOKEN); - httpClient.request.callsArgWith(3, TEST_ERROR_MESSAGE); - - // call - authorizationController.tokenRefreshAndRead(TEST_ENVIRONMENT_PROFILE, (error, accessToken) => { - // verify - expect(error).eq(TEST_ERROR_MESSAGE); - expect(accessToken).eq(undefined); - done(); - }); - }); - - it('| environment profile, invalid refresh token, invalid access token', (done) => { - // call - authorizationController.tokenRefreshAndRead(TEST_ENVIRONMENT_PROFILE, (error, accessToken) => { - // verify - expect(error).eq(messages.ASK_ENV_VARIABLES_ERROR_MESSAGE); - expect(accessToken).eq(undefined); - done(); - }); - }); + }); + + it("| environment profile, invalid refresh token, valid access token", (done) => { + // setup + process.env.ASK_ACCESS_TOKEN = TEST_ENV_ACCESS_TOKEN; + // call + authorizationController.tokenRefreshAndRead(TEST_ENVIRONMENT_PROFILE, (error, accessToken) => { + // verify + expect(error).eq(null); + expect(accessToken).to.deep.eq(TEST_ENV_ACCESS_TOKEN); + done(); }); + }); }); - describe('# test _getRefreshTokenAndUpdateConfig', () => { - let setTokenStub, writeStub; - const authorizationController = new AuthorizationController(TEST_CONFIG); - - beforeEach(() => { - setTokenStub = sinon.stub(); - writeStub = sinon.stub(); - sinon.stub(AppConfig, 'getInstance').returns({ - setToken: setTokenStub, - write: writeStub - }); - sinon.stub(httpClient, 'request'); + describe("# returns error", () => { + it("| non-environment profile, expired access token, _getRefreshTokenAndUpdateConfig fails", (done) => { + // setup + getTokenStub.withArgs(TEST_PROFILE).returns(TEST_RESPONSE.body); + sinon.stub(AuthorizationController.prototype, "_getRefreshTokenAndUpdateConfig").callsArgWith(2, TEST_ERROR_MESSAGE); + + // call + authorizationController.tokenRefreshAndRead(TEST_PROFILE, (error, response) => { + // verify + expect(error).eq(TEST_ERROR_MESSAGE); + expect(response).eq(TEST_ERROR_MESSAGE); + done(); }); - - afterEach(() => { - sinon.restore(); + }); + + it("| environment profile, valid refresh token, refreshing token fails", (done) => { + // setup + process.env.ASK_REFRESH_TOKEN = TEST_ENV_REFRESH_TOKEN; + sinon.stub(AuthorizationController.prototype, "_getRefreshTokenAndUpdateConfig").callsArgWith(2, null, VALID_ACCESS_TOKEN); + httpClient.request.callsArgWith(3, TEST_ERROR_MESSAGE); + + // call + authorizationController.tokenRefreshAndRead(TEST_ENVIRONMENT_PROFILE, (error, accessToken) => { + // verify + expect(error).eq(TEST_ERROR_MESSAGE); + expect(accessToken).eq(undefined); + done(); }); - - it('| returns valid access token and updates config', (done) => { - // setup - httpClient.request.callsArgWith(3, null, TEST_RESPONSE); - - // call - authorizationController._getRefreshTokenAndUpdateConfig(TEST_PROFILE, TEST_TOKEN, (error, accessToken) => { - // verify - expect(setTokenStub.args[0][0]).eq(TEST_PROFILE); - expect(setTokenStub.args[0][1].access_token).to.eq(TEST_RESPONSE.body.access_token); - expect(setTokenStub.args[0][1].refresh_token).to.eq(TEST_RESPONSE.body.refresh_token); - expect(setTokenStub.args[0][1].expires_in).to.eq(TEST_RESPONSE.body.expires_in); - expect(error).eq(null); - expect(accessToken).to.deep.eq(TEST_RESPONSE.body.access_token); - done(); - }); + }); + + it("| environment profile, invalid refresh token, invalid access token", (done) => { + // call + authorizationController.tokenRefreshAndRead(TEST_ENVIRONMENT_PROFILE, (error, accessToken) => { + // verify + expect(error).eq(messages.ASK_ENV_VARIABLES_ERROR_MESSAGE); + expect(accessToken).eq(undefined); + done(); }); + }); + }); + }); + + describe("# test _getRefreshTokenAndUpdateConfig", () => { + let setTokenStub, writeStub; + const authorizationController = new AuthorizationController(TEST_CONFIG); + + beforeEach(() => { + setTokenStub = sinon.stub(); + writeStub = sinon.stub(); + sinon.stub(AppConfig, "getInstance").returns({ + setToken: setTokenStub, + write: writeStub, + }); + sinon.stub(httpClient, "request"); + }); - it('| returns error', (done) => { - // setup - httpClient.request.callsArgWith(3, TEST_ERROR_MESSAGE); - - // call - authorizationController._getRefreshTokenAndUpdateConfig(TEST_PROFILE, TEST_TOKEN, (error, response) => { - // verify - expect(error).eq(TEST_ERROR_MESSAGE); - expect(response).eq(undefined); - done(); - }); - }); + afterEach(() => { + sinon.restore(); }); - describe('# test getTokensByListeningOnPort', () => { - let proxyHelper, openStub, infoStub; - - beforeEach(() => { - sinon.stub(httpClient, 'request'); - sinon.stub(portscanner, 'checkPortStatus'); - infoStub = sinon.stub(); - sinon.stub(Messenger, 'getInstance').returns({ - info: infoStub - }); - openStub = sinon.stub(); - proxyHelper = proxyquire('@src/controllers/authorization-controller', { - open: openStub - }); - }); + it("| returns valid access token and updates config", (done) => { + // setup + httpClient.request.callsArgWith(3, null, TEST_RESPONSE); + + // call + authorizationController._getRefreshTokenAndUpdateConfig(TEST_PROFILE, TEST_TOKEN, (error, accessToken) => { + // verify + expect(setTokenStub.args[0][0]).eq(TEST_PROFILE); + expect(setTokenStub.args[0][1].access_token).to.eq(TEST_RESPONSE.body.access_token); + expect(setTokenStub.args[0][1].refresh_token).to.eq(TEST_RESPONSE.body.refresh_token); + expect(setTokenStub.args[0][1].expires_in).to.eq(TEST_RESPONSE.body.expires_in); + expect(error).eq(null); + expect(accessToken).to.deep.eq(TEST_RESPONSE.body.access_token); + done(); + }); + }); - afterEach(() => { - sinon.restore(); - }); + it("| returns error", (done) => { + // setup + httpClient.request.callsArgWith(3, TEST_ERROR_MESSAGE); + + // call + authorizationController._getRefreshTokenAndUpdateConfig(TEST_PROFILE, TEST_TOKEN, (error, response) => { + // verify + expect(error).eq(TEST_ERROR_MESSAGE); + expect(response).eq(undefined); + done(); + }); + }); + }); + + describe("# test getTokensByListeningOnPort", () => { + let proxyHelper, openStub, infoStub; + + beforeEach(() => { + sinon.stub(httpClient, "request"); + sinon.stub(portscanner, "checkPortStatus"); + infoStub = sinon.stub(); + sinon.stub(Messenger, "getInstance").returns({ + info: infoStub, + }); + openStub = sinon.stub(); + proxyHelper = proxyquire("../../../../lib/controllers/authorization-controller", { + open: openStub, + }); + }); - it('| returns error, from postScanner library', (done) => { - // setup - const authorizationController = new AuthorizationController(TEST_CONFIG); - portscanner.checkPortStatus.callsArgWith(1, TEST_ERROR_MESSAGE); - - // call - authorizationController.getTokensByListeningOnPort((error, response) => { - // verify - expect(error).eq(TEST_ERROR_MESSAGE); - expect(response).eq(undefined); - done(); - }); - }); + afterEach(() => { + sinon.restore(); + }); - it('| returns error, port is open', (done) => { - // setup - const authorizationController = new AuthorizationController(TEST_CONFIG); - portscanner.checkPortStatus.callsArgWith(1, null, 'open'); - - // call - authorizationController.getTokensByListeningOnPort((error, response) => { - // verify - expect(error).eq(messages.PORT_OCCUPIED_WARN_MESSAGE); - expect(response).eq(undefined); - done(); - }); - }); + it("| returns error, from postScanner library", (done) => { + // setup + const authorizationController = new AuthorizationController(TEST_CONFIG); + portscanner.checkPortStatus.callsArgWith(1, TEST_ERROR_MESSAGE); + + // call + authorizationController.getTokensByListeningOnPort((error, response) => { + // verify + expect(error).eq(TEST_ERROR_MESSAGE); + expect(response).eq(undefined); + done(); + }); + }); - it('| returns error, port is open but listening response on port fails', (done) => { - // setup - sinon.stub(proxyHelper.prototype, '_listenResponseFromLWA').callsArgWith(1, TEST_ERROR_MESSAGE); - portscanner.checkPortStatus.callsArgWith(1, null, 'closed'); - proxyHelper.prototype.oauthClient = new LWAClient(TEST_CONFIG); - // call - proxyHelper.prototype.getTokensByListeningOnPort((error, response) => { - // verify - expect(infoStub.args[0][0]).eq(messages.AUTH_MESSAGE); - expect(error).eq(TEST_ERROR_MESSAGE); - expect(response).eq(undefined); - done(); - }); - }); + it("| returns error, port is open", (done) => { + // setup + const authorizationController = new AuthorizationController(TEST_CONFIG); + portscanner.checkPortStatus.callsArgWith(1, null, "open"); + + // call + authorizationController.getTokensByListeningOnPort((error, response) => { + // verify + expect(error).eq(messages.PORT_OCCUPIED_WARN_MESSAGE); + expect(response).eq(undefined); + done(); + }); + }); - it('| returns error, port is open but LWA client getAccessToken fails', (done) => { - // setup - sinon.stub(proxyHelper.prototype, '_listenResponseFromLWA').callsArgWith(1, null, TEST_AUTH_CODE); - portscanner.checkPortStatus.callsArgWith(1, null, 'closed'); - proxyHelper.prototype.oauthClient = new LWAClient(TEST_CONFIG); - httpClient.request.callsArgWith(3, TEST_ERROR_MESSAGE); - // call - proxyHelper.prototype.getTokensByListeningOnPort((error, response) => { - // verify - expect(infoStub.args[0][0]).eq(messages.AUTH_MESSAGE); - expect(error).eq(TEST_ERROR_MESSAGE); - expect(response).eq(TEST_ERROR_MESSAGE); - done(); - }); - }); + it("| returns error, port is open but listening response on port fails", (done) => { + // setup + sinon.stub(proxyHelper.prototype, "_listenResponseFromLWA").callsArgWith(1, TEST_ERROR_MESSAGE); + portscanner.checkPortStatus.callsArgWith(1, null, "closed"); + proxyHelper.prototype.oauthClient = new LWAClient(TEST_CONFIG); + // call + proxyHelper.prototype.getTokensByListeningOnPort((error, response) => { + // verify + expect(infoStub.args[0][0]).eq(messages.AUTH_MESSAGE); + expect(error).eq(TEST_ERROR_MESSAGE); + expect(response).eq(undefined); + done(); + }); + }); - it('| returns valid token', (done) => { - // setup - sinon.stub(proxyHelper.prototype, '_listenResponseFromLWA').callsArgWith(1, null, TEST_AUTH_CODE); - portscanner.checkPortStatus.callsArgWith(1, null, 'closed'); - proxyHelper.prototype.oauthClient = new LWAClient(TEST_CONFIG); - httpClient.request.callsArgWith(3, null, TEST_RESPONSE); - // call - proxyHelper.prototype.getTokensByListeningOnPort((error, accessToken) => { - // verify - expect(infoStub.args[0][0]).eq(messages.AUTH_MESSAGE); - expect(error).eq(null); - expect(accessToken.access_token).to.eq(TEST_RESPONSE.body.access_token); - expect(accessToken.refresh_token).to.eq(TEST_RESPONSE.body.refresh_token); - expect(accessToken.expires_in).to.eq(TEST_RESPONSE.body.expires_in); - done(); - }); - }); + it("| returns error, port is open but LWA client getAccessToken fails", (done) => { + // setup + sinon.stub(proxyHelper.prototype, "_listenResponseFromLWA").callsArgWith(1, null, TEST_AUTH_CODE); + portscanner.checkPortStatus.callsArgWith(1, null, "closed"); + proxyHelper.prototype.oauthClient = new LWAClient(TEST_CONFIG); + httpClient.request.callsArgWith(3, TEST_ERROR_MESSAGE); + // call + proxyHelper.prototype.getTokensByListeningOnPort((error, response) => { + // verify + expect(infoStub.args[0][0]).eq(messages.AUTH_MESSAGE); + expect(error).eq(TEST_ERROR_MESSAGE); + expect(response).eq(TEST_ERROR_MESSAGE); + done(); + }); }); - describe('# test _listenResponseFromLWA', () => { - const authorizationController = new AuthorizationController(TEST_CONFIG); + it("| returns valid token", (done) => { + // setup + sinon.stub(proxyHelper.prototype, "_listenResponseFromLWA").callsArgWith(1, null, TEST_AUTH_CODE); + portscanner.checkPortStatus.callsArgWith(1, null, "closed"); + proxyHelper.prototype.oauthClient = new LWAClient(TEST_CONFIG); + httpClient.request.callsArgWith(3, null, TEST_RESPONSE); + // call + proxyHelper.prototype.getTokensByListeningOnPort((error, accessToken) => { + // verify + expect(infoStub.args[0][0]).eq(messages.AUTH_MESSAGE); + expect(error).eq(null); + expect(accessToken.access_token).to.eq(TEST_RESPONSE.body.access_token); + expect(accessToken.refresh_token).to.eq(TEST_RESPONSE.body.refresh_token); + expect(accessToken.expires_in).to.eq(TEST_RESPONSE.body.expires_in); + done(); + }); + }); + }); - afterEach(() => { - sinon.restore(); - }); + describe("# test _listenResponseFromLWA", () => { + const authorizationController = new AuthorizationController(TEST_CONFIG); - it('| should create a server and start spinner to indicate listening on port', () => { - // setup - const socket = { - unref: () => {} - }; - const createStub = sinon.stub(LocalHostServer.prototype, 'create'); - const listenStub = sinon.stub(LocalHostServer.prototype, 'listen').callsArgWith(0); - const spinnerStartStub = sinon.stub(SpinnerView.prototype, 'start'); - const registerEventStub = sinon.stub(LocalHostServer.prototype, 'registerEvent').callsArgWith(1, socket); - - // call - authorizationController._listenResponseFromLWA(TEST_PORT, () => {}); - - // verify - expect(registerEventStub.callCount).eq(1); - expect(spinnerStartStub.args[0][0]).eq(` Listening on http://localhost:${TEST_PORT}...`); - expect(spinnerStartStub.callCount).eq(1); - expect(listenStub.callCount).eq(1); - expect(createStub.callCount).eq(1); - }); + afterEach(() => { + sinon.restore(); + }); - it('| local host server returns error', (done) => { - // setup - sinon.stub(LocalHostServer.prototype, 'listen'); - sinon.stub(LocalHostServer.prototype, 'registerEvent'); - const requestDestroyStub = sinon.stub(); - const request = { - url: '/cb?error', - socket: { - destroy: requestDestroyStub - } - }; - const endStub = sinon.stub(); - const response = { - on: sinon.stub().callsArgWith(1), - end: endStub - }; - const spinnerTerminateStub = sinon.stub(SpinnerView.prototype, 'terminate'); - const requestQuery = { - query: { - error: 'error', - error_description: 'errorDescription' - } - }; - sinon.stub(url, 'parse').returns(requestQuery); - const serverDestroyStub = sinon.stub(LocalHostServer.prototype, 'destroy'); - sinon.stub(LocalHostServer.prototype, 'create').callsArgWith(0, request, response); - // call - authorizationController._listenResponseFromLWA(TEST_PORT, (err) => { - // verify - const EXPECTED_ERR_MESSAGE = `Error: ${requestQuery.query.error}\nReason: ${requestQuery.query.error_description}`; - expect(spinnerTerminateStub.callCount).eq(1); - expect(serverDestroyStub.callCount).eq(1); - expect(endStub.callCount).eq(1); - expect(endStub.args[0][0].includes(EXPECTED_ERR_MESSAGE)).equal(true); - expect(err).eq(EXPECTED_ERR_MESSAGE); - done(); - }); - }); + it("| should create a server and start spinner to indicate listening on port", () => { + // setup + const socket = { + unref: () => {}, + }; + const createStub = sinon.stub(LocalHostServer.prototype, "create"); + const listenStub = sinon.stub(LocalHostServer.prototype, "listen").callsArgWith(0); + const spinnerStartStub = sinon.stub(SpinnerView.prototype, "start"); + const registerEventStub = sinon.stub(LocalHostServer.prototype, "registerEvent").callsArgWith(1, socket); + + // call + authorizationController._listenResponseFromLWA(TEST_PORT, () => {}); + + // verify + expect(registerEventStub.callCount).eq(1); + expect(spinnerStartStub.args[0][0]).eq(` Listening on http://localhost:${TEST_PORT}...`); + expect(spinnerStartStub.callCount).eq(1); + expect(listenStub.callCount).eq(1); + expect(createStub.callCount).eq(1); + }); - it('| local server returns valid authCode', (done) => { - // setup - sinon.stub(LocalHostServer.prototype, 'listen'); - sinon.stub(LocalHostServer.prototype, 'registerEvent'); - const requestDestroyStub = sinon.stub(); - const request = { - url: '/cb?code', - socket: { - destroy: requestDestroyStub - } - }; - const endStub = sinon.stub(); - const response = { - on: sinon.stub().callsArgWith(1), - end: endStub - }; - sinon.stub(SpinnerView.prototype, 'terminate'); - const requestQuery = { - query: { - code: TEST_AUTH_CODE - } - }; - sinon.stub(url, 'parse').returns(requestQuery); - sinon.stub(LocalHostServer.prototype, 'destroy'); - sinon.stub(LocalHostServer.prototype, 'create').callsArgWith(0, request, response); - - // call - authorizationController._listenResponseFromLWA(TEST_PORT, (err, authCode) => { - // verify - expect(endStub.callCount).eq(1); - expect(endStub.args[0][0]).eq(messages.ASK_SIGN_IN_SUCCESS_MESSAGE); - expect(err).eq(null); - expect(authCode).eq(TEST_AUTH_CODE); - done(); - }); - }); + it("| local host server returns error", (done) => { + // setup + sinon.stub(LocalHostServer.prototype, "listen"); + sinon.stub(LocalHostServer.prototype, "registerEvent"); + const requestDestroyStub = sinon.stub(); + const request = { + url: "/cb?error", + socket: { + destroy: requestDestroyStub, + }, + }; + const endStub = sinon.stub(); + const response = { + on: sinon.stub().callsArgWith(1), + end: endStub, + }; + const spinnerTerminateStub = sinon.stub(SpinnerView.prototype, "terminate"); + const requestQuery = { + query: { + error: "error", + error_description: "errorDescription", + }, + }; + sinon.stub(url, "parse").returns(requestQuery); + const serverDestroyStub = sinon.stub(LocalHostServer.prototype, "destroy"); + sinon.stub(LocalHostServer.prototype, "create").callsArgWith(0, request, response); + // call + authorizationController._listenResponseFromLWA(TEST_PORT, (err) => { + // verify + const EXPECTED_ERR_MESSAGE = `Error: ${requestQuery.query.error}\nReason: ${requestQuery.query.error_description}`; + expect(spinnerTerminateStub.callCount).eq(1); + expect(serverDestroyStub.callCount).eq(1); + expect(endStub.callCount).eq(1); + expect(endStub.args[0][0].includes(EXPECTED_ERR_MESSAGE)).equal(true); + expect(err).eq(EXPECTED_ERR_MESSAGE); + done(); + }); + }); + + it("| local server returns valid authCode", (done) => { + // setup + sinon.stub(LocalHostServer.prototype, "listen"); + sinon.stub(LocalHostServer.prototype, "registerEvent"); + const requestDestroyStub = sinon.stub(); + const request = { + url: "/cb?code", + socket: { + destroy: requestDestroyStub, + }, + }; + const endStub = sinon.stub(); + const response = { + on: sinon.stub().callsArgWith(1), + end: endStub, + }; + sinon.stub(SpinnerView.prototype, "terminate"); + const requestQuery = { + query: { + code: TEST_AUTH_CODE, + }, + }; + sinon.stub(url, "parse").returns(requestQuery); + sinon.stub(LocalHostServer.prototype, "destroy"); + sinon.stub(LocalHostServer.prototype, "create").callsArgWith(0, request, response); + + // call + authorizationController._listenResponseFromLWA(TEST_PORT, (err, authCode) => { + // verify + expect(endStub.callCount).eq(1); + expect(endStub.args[0][0]).eq(messages.ASK_SIGN_IN_SUCCESS_MESSAGE); + expect(err).eq(null); + expect(authCode).eq(TEST_AUTH_CODE); + done(); + }); }); + }); }); diff --git a/test/unit/controller/code-builder-test.js b/test/unit/controller/code-builder-test.js index 37527d84..e09e5c63 100644 --- a/test/unit/controller/code-builder-test.js +++ b/test/unit/controller/code-builder-test.js @@ -1,88 +1,84 @@ -const { expect } = require('chai'); -const sinon = require('sinon'); -const fs = require('fs-extra'); -const path = require('path'); -const ZipOnlyBuildFlow = require('@src/builtins/build-flows/zip-only'); -const NodeJsNpmBuildFlow = require('@src/builtins/build-flows/nodejs-npm'); -const CodeBuilder = require('@src/controllers/skill-code-controller/code-builder'); +const {expect} = require("chai"); +const sinon = require("sinon"); +const fs = require("fs-extra"); +const path = require("path"); +const ZipOnlyBuildFlow = require("../../../lib/builtins/build-flows/zip-only"); +const NodeJsNpmBuildFlow = require("../../../lib/builtins/build-flows/nodejs-npm"); +const CodeBuilder = require("../../../lib/controllers/skill-code-controller/code-builder"); -describe('Controller test - CodeBuilder test', () => { - const config = { - src: 'src', - build: 'buildFile', - doDebug: false - }; - let selectBuildFlowClassStub; - beforeEach(() => { - sinon.stub(fs, 'ensureDirSync'); - sinon.stub(fs, 'emptyDirSync'); - sinon.stub(fs, 'copySync'); - sinon.stub(path, 'resolve'); - }); +describe("Controller test - CodeBuilder test", () => { + const config = { + src: "src", + build: "buildFile", + doDebug: false, + }; + let selectBuildFlowClassStub; + beforeEach(() => { + sinon.stub(fs, "ensureDirSync"); + sinon.stub(fs, "emptyDirSync"); + sinon.stub(fs, "copySync"); + sinon.stub(path, "resolve"); + }); - describe('# inspect correctness for constructor', () => { - it('| initiate CodeBuilder', () => { - selectBuildFlowClassStub = sinon.stub(CodeBuilder.prototype, '_selectBuildFlowClass'); - const codeBuilder = new CodeBuilder(config); + describe("# inspect correctness for constructor", () => { + it("| initiate CodeBuilder", () => { + selectBuildFlowClassStub = sinon.stub(CodeBuilder.prototype, "_selectBuildFlowClass"); + const codeBuilder = new CodeBuilder(config); - expect(codeBuilder).to.be.instanceOf(CodeBuilder); - expect(codeBuilder.src).equal(config.src); - expect(codeBuilder.build).deep.equal(config.build); - expect(codeBuilder.doDebug).equal(config.doDebug); - expect(selectBuildFlowClassStub.callCount).equal(1); - }); + expect(codeBuilder).to.be.instanceOf(CodeBuilder); + expect(codeBuilder.src).equal(config.src); + expect(codeBuilder.build).deep.equal(config.build); + expect(codeBuilder.doDebug).equal(config.doDebug); + expect(selectBuildFlowClassStub.callCount).equal(1); }); + }); - describe('# inspect correctness of execute method', () => { - it('| should execute zip only build flow when no other build flow is found', (done) => { - sinon.stub(path, 'join'); - sinon.stub(fs, 'existsSync').returns(false); - const executeStub = sinon.stub(ZipOnlyBuildFlow.prototype, 'execute').yields(); - const codeBuilder = new CodeBuilder(config); + describe("# inspect correctness of execute method", () => { + it("| should execute zip only build flow when no other build flow is found", (done) => { + sinon.stub(path, "join"); + sinon.stub(fs, "existsSync").returns(false); + const executeStub = sinon.stub(ZipOnlyBuildFlow.prototype, "execute").yields(); + const codeBuilder = new CodeBuilder(config); - codeBuilder.execute((err, res) => { - expect(err).eql(undefined); - expect(res).eql(undefined); - expect(codeBuilder.BuildFlowClass.name).equal('ZipOnlyBuildFlow'); - expect(executeStub.callCount).equal(1); - done(); - }); - }); + codeBuilder.execute((err, res) => { + expect(err).eql(undefined); + expect(res).eql(undefined); + expect(codeBuilder.BuildFlowClass.name).equal("ZipOnlyBuildFlow"); + expect(executeStub.callCount).equal(1); + done(); + }); + }); - it('| should execute node js npm build flow', (done) => { - sinon.stub(path, 'join') - .returns('some-file') - .withArgs(sinon.match.any, sinon.match('package.json')).returns('package.json'); - sinon.stub(fs, 'existsSync') - .returns(false) - .withArgs(sinon.match('package.json')).returns(true); - const executeStub = sinon.stub(NodeJsNpmBuildFlow.prototype, 'execute').yields(); - const codeBuilder = new CodeBuilder(config); + it("| should execute node js npm build flow", (done) => { + sinon.stub(path, "join").returns("some-file").withArgs(sinon.match.any, sinon.match("package.json")).returns("package.json"); + sinon.stub(fs, "existsSync").returns(false).withArgs(sinon.match("package.json")).returns(true); + const executeStub = sinon.stub(NodeJsNpmBuildFlow.prototype, "execute").yields(); + const codeBuilder = new CodeBuilder(config); - codeBuilder.execute((err, res) => { - expect(err).eql(undefined); - expect(res).eql(undefined); - expect(codeBuilder.BuildFlowClass.name).equal('NodeJsNpmBuildFlow'); - expect(executeStub.callCount).equal(1); - done(); - }); - }); + codeBuilder.execute((err, res) => { + expect(err).eql(undefined); + expect(res).eql(undefined); + expect(codeBuilder.BuildFlowClass.name).equal("NodeJsNpmBuildFlow"); + expect(executeStub.callCount).equal(1); + done(); + }); + }); - it('| should throw error when unable to set up build folder', (done) => { - const error = 'someError'; - sinon.stub(CodeBuilder.prototype, '_selectBuildFlowClass'); - sinon.stub(CodeBuilder.prototype, '_setUpBuildFolder').throws(new Error(error)); - const codeBuilder = new CodeBuilder(config); + it("| should throw error when unable to set up build folder", (done) => { + const error = "someError"; + sinon.stub(CodeBuilder.prototype, "_selectBuildFlowClass"); + sinon.stub(CodeBuilder.prototype, "_setUpBuildFolder").throws(new Error(error)); + const codeBuilder = new CodeBuilder(config); - codeBuilder.execute((err, res) => { - expect(err.message).eql(error); - expect(res).eql(undefined); - done(); - }); - }); + codeBuilder.execute((err, res) => { + expect(err.message).eql(error); + expect(res).eql(undefined); + done(); + }); }); + }); - afterEach(() => { - sinon.restore(); - }); + afterEach(() => { + sinon.restore(); + }); }); diff --git a/test/unit/controller/deploy-delegate-test.js b/test/unit/controller/deploy-delegate-test.js index 8549385f..26ddd558 100644 --- a/test/unit/controller/deploy-delegate-test.js +++ b/test/unit/controller/deploy-delegate-test.js @@ -1,267 +1,269 @@ -const { expect } = require('chai'); -const sinon = require('sinon'); -const path = require('path'); -const DeployDelegate = require('@src/controllers/skill-infrastructure-controller/deploy-delegate'); +const {expect} = require("chai"); +const sinon = require("sinon"); +const path = require("path"); +const DeployDelegate = require("../../../lib/controllers/skill-infrastructure-controller/deploy-delegate"); -describe('Controller test - DeployDelegate test', () => { - const TEST_REPORTER = {}; - const TEST_BUILTIN_TYPE = '@ask-cli/cfn-deployer'; - const TEST_INSTANCE = { - bootstrap: () => 'bootstrap', - invoke: () => 'invoke' - }; - const TEST_WORKSPACE = 'workspace'; - const TEST_OPTIONS = { - workspacePath: TEST_WORKSPACE - }; +describe("Controller test - DeployDelegate test", () => { + const TEST_REPORTER = {}; + const TEST_BUILTIN_TYPE = "@ask-cli/cfn-deployer"; + const TEST_INSTANCE = { + bootstrap: () => "bootstrap", + invoke: () => "invoke", + }; + const TEST_WORKSPACE = "workspace"; + const TEST_OPTIONS = { + workspacePath: TEST_WORKSPACE, + }; - describe('# inspect correctness for constructor', () => { - it('| initiate as a DeployDelegate class', () => { - const deployDelegate = new DeployDelegate(TEST_BUILTIN_TYPE, TEST_INSTANCE); - expect(deployDelegate).to.be.instanceOf(DeployDelegate); - expect(deployDelegate.type).equal(TEST_BUILTIN_TYPE); - expect(deployDelegate.instance).deep.equal(TEST_INSTANCE); - }); + describe("# inspect correctness for constructor", () => { + it("| initiate as a DeployDelegate class", () => { + const deployDelegate = new DeployDelegate(TEST_BUILTIN_TYPE, TEST_INSTANCE); + expect(deployDelegate).to.be.instanceOf(DeployDelegate); + expect(deployDelegate.type).equal(TEST_BUILTIN_TYPE); + expect(deployDelegate.instance).deep.equal(TEST_INSTANCE); + }); - it('| validate deploy delegate required instance field throws exception', () => { - try { - new DeployDelegate(TEST_BUILTIN_TYPE, null); - } catch (e) { - expect(e.message).equal('[Error]: Invalid deploy delegate. Failed to load the target module.'); - } - }); + it("| validate deploy delegate required instance field throws exception", () => { + try { + new DeployDelegate(TEST_BUILTIN_TYPE, null); + } catch (e) { + expect(e.message).equal("[Error]: Invalid deploy delegate. Failed to load the target module."); + } + }); - it('| validate deploy delegate required methods "bootstrap" throws exception', () => { - try { - new DeployDelegate(TEST_BUILTIN_TYPE, { invoke: () => 'invoke' }); - } catch (e) { - expect(e.message).equal('[Error]: Invalid deploy delegate. The class of the deploy delegate must contain "bootstrap" method.'); - } - }); + it('| validate deploy delegate required methods "bootstrap" throws exception', () => { + try { + new DeployDelegate(TEST_BUILTIN_TYPE, {invoke: () => "invoke"}); + } catch (e) { + expect(e.message).equal('[Error]: Invalid deploy delegate. The class of the deploy delegate must contain "bootstrap" method.'); + } + }); - it('| validate deploy delegate required methods "invoke" throws exception', () => { - try { - new DeployDelegate(TEST_BUILTIN_TYPE, { bootstrap: () => 'bootstrap' }); - } catch (e) { - expect(e.message).equal('[Error]: Invalid deploy delegate. The class of the deploy delegate must contain "invoke" method.'); - } - }); + it('| validate deploy delegate required methods "invoke" throws exception', () => { + try { + new DeployDelegate(TEST_BUILTIN_TYPE, {bootstrap: () => "bootstrap"}); + } catch (e) { + expect(e.message).equal('[Error]: Invalid deploy delegate. The class of the deploy delegate must contain "invoke" method.'); + } }); + }); - describe('# test class method: bootstrap', () => { - beforeEach(() => { - sinon.stub(path, 'join'); - }); + describe("# test class method: bootstrap", () => { + beforeEach(() => { + sinon.stub(path, "join"); + }); - afterEach(() => { - sinon.restore(); - }); + afterEach(() => { + sinon.restore(); + }); - it('| bootstrap not able to start because instance does not exist', (done) => { - // setup - const deployDelegate = new DeployDelegate(TEST_BUILTIN_TYPE, TEST_INSTANCE); - deployDelegate.instance = null; - // call - deployDelegate.bootstrap(TEST_OPTIONS, (err, res) => { - // verify - expect(err).equal('[Fatal]: Please instantiate the DeployDelegate class before using.'); - expect(res).equal(undefined); - done(); - }); - }); + it("| bootstrap not able to start because instance does not exist", (done) => { + // setup + const deployDelegate = new DeployDelegate(TEST_BUILTIN_TYPE, TEST_INSTANCE); + deployDelegate.instance = null; + // call + deployDelegate.bootstrap(TEST_OPTIONS, (err, res) => { + // verify + expect(err).equal("[Fatal]: Please instantiate the DeployDelegate class before using."); + expect(res).equal(undefined); + done(); + }); + }); - it('| bootstrap is called successfully', (done) => { - // setup - const stub = sinon.stub(); - stub.callsArgWith(1, null); - const deployDelegate = new DeployDelegate(TEST_BUILTIN_TYPE, { - bootstrap: stub, - invoke: () => 'invoke' - }); - // call - deployDelegate.bootstrap(TEST_OPTIONS, (err) => { - // verify - expect(err).equal(null); - expect(stub.args[0][0]).deep.equal(TEST_OPTIONS); - done(); - }); - }); + it("| bootstrap is called successfully", (done) => { + // setup + const stub = sinon.stub(); + stub.callsArgWith(1, null); + const deployDelegate = new DeployDelegate(TEST_BUILTIN_TYPE, { + bootstrap: stub, + invoke: () => "invoke", + }); + // call + deployDelegate.bootstrap(TEST_OPTIONS, (err) => { + // verify + expect(err).equal(null); + expect(stub.args[0][0]).deep.equal(TEST_OPTIONS); + done(); + }); }); + }); - describe('# test class method: invoke', () => { - beforeEach(() => { - sinon.stub(path, 'join'); - }); + describe("# test class method: invoke", () => { + beforeEach(() => { + sinon.stub(path, "join"); + }); - afterEach(() => { - sinon.restore(); - }); + afterEach(() => { + sinon.restore(); + }); - it('| invoke not able to start because instance does not exist', (done) => { - // setup - const deployDelegate = new DeployDelegate(TEST_BUILTIN_TYPE, TEST_INSTANCE); - deployDelegate.instance = null; - // call - deployDelegate.invoke(TEST_REPORTER, TEST_OPTIONS, (err, res) => { - // verify - expect(err).equal('[Fatal]: Please instantiate the DeployDelegate class before using.'); - expect(res).equal(undefined); - done(); - }); - }); + it("| invoke not able to start because instance does not exist", (done) => { + // setup + const deployDelegate = new DeployDelegate(TEST_BUILTIN_TYPE, TEST_INSTANCE); + deployDelegate.instance = null; + // call + deployDelegate.invoke(TEST_REPORTER, TEST_OPTIONS, (err, res) => { + // verify + expect(err).equal("[Fatal]: Please instantiate the DeployDelegate class before using."); + expect(res).equal(undefined); + done(); + }); + }); - it('| invoke is called successfully', (done) => { - // setup - const stub = sinon.stub(); - stub.callsArgWith(2, null); - const deployDelegate = new DeployDelegate(TEST_BUILTIN_TYPE, { - bootstrap: () => 'bootstrap', - invoke: stub - }); - // call - deployDelegate.invoke(TEST_REPORTER, TEST_OPTIONS, (err) => { - // verify - expect(err).equal(null); - expect(stub.args[0][1]).deep.equal(TEST_OPTIONS); - done(); - }); - }); + it("| invoke is called successfully", (done) => { + // setup + const stub = sinon.stub(); + stub.callsArgWith(2, null); + const deployDelegate = new DeployDelegate(TEST_BUILTIN_TYPE, { + bootstrap: () => "bootstrap", + invoke: stub, + }); + // call + deployDelegate.invoke(TEST_REPORTER, TEST_OPTIONS, (err) => { + // verify + expect(err).equal(null); + expect(stub.args[0][1]).deep.equal(TEST_OPTIONS); + done(); + }); }); + }); - describe('# test class method: validateDeployDelegateResponse', () => { - beforeEach(() => { - sinon.stub(path, 'join'); - }); + describe("# test class method: validateDeployDelegateResponse", () => { + beforeEach(() => { + sinon.stub(path, "join"); + }); - afterEach(() => { - sinon.restore(); - }); + afterEach(() => { + sinon.restore(); + }); - it('| deploy result is not truthy value, expect error thrown', () => { - // setup - const TEST_DEPLOY_RESULT = null; - const deployDelegate = new DeployDelegate(TEST_BUILTIN_TYPE, TEST_INSTANCE); - // call - try { - deployDelegate.validateDeployDelegateResponse(TEST_DEPLOY_RESULT); - } catch (e) { - // verify - expect(e.message).equal('[Error]: Deploy result should not be empty.'); - } - }); + it("| deploy result is not truthy value, expect error thrown", () => { + // setup + const TEST_DEPLOY_RESULT = null; + const deployDelegate = new DeployDelegate(TEST_BUILTIN_TYPE, TEST_INSTANCE); + // call + try { + deployDelegate.validateDeployDelegateResponse(TEST_DEPLOY_RESULT); + } catch (e) { + // verify + expect(e.message).equal("[Error]: Deploy result should not be empty."); + } + }); - it('| deploy result misses endpoint field, expect error thrown', () => { - // setup - const TEST_DEPLOY_RESULT = { - default: {} - }; - const deployDelegate = new DeployDelegate(TEST_BUILTIN_TYPE, TEST_INSTANCE); - // call - try { - deployDelegate.validateDeployDelegateResponse(TEST_DEPLOY_RESULT); - } catch (e) { - // verify - expect(e.message).equal('[Error]: Invalid response from deploy delegate. "endpoint" field must exist in the response.'); - } - }); + it("| deploy result misses endpoint field, expect error thrown", () => { + // setup + const TEST_DEPLOY_RESULT = { + default: {}, + }; + const deployDelegate = new DeployDelegate(TEST_BUILTIN_TYPE, TEST_INSTANCE); + // call + try { + deployDelegate.validateDeployDelegateResponse(TEST_DEPLOY_RESULT); + } catch (e) { + // verify + expect(e.message).equal('[Error]: Invalid response from deploy delegate. "endpoint" field must exist in the response.'); + } + }); - it('| deploy result misses endpoint.uri field, expect error thrown', () => { - // setup - const TEST_DEPLOY_RESULT = { - default: { - endpoint: {} - } - }; - const deployDelegate = new DeployDelegate(TEST_BUILTIN_TYPE, TEST_INSTANCE); - // call - try { - deployDelegate.validateDeployDelegateResponse(TEST_DEPLOY_RESULT); - } catch (e) { - // verify - expect(e.message).equal('[Error]: Invalid response from deploy delegate. "uri" field must exist in the "endpoint" field in the response.'); - } - }); + it("| deploy result misses endpoint.uri field, expect error thrown", () => { + // setup + const TEST_DEPLOY_RESULT = { + default: { + endpoint: {}, + }, + }; + const deployDelegate = new DeployDelegate(TEST_BUILTIN_TYPE, TEST_INSTANCE); + // call + try { + deployDelegate.validateDeployDelegateResponse(TEST_DEPLOY_RESULT); + } catch (e) { + // verify + expect(e.message).equal( + '[Error]: Invalid response from deploy delegate. "uri" field must exist in the "endpoint" field in the response.', + ); + } + }); - it('| deploy result misses deployState field, expect error thrown', () => { - // setup - const TEST_DEPLOY_RESULT = { - default: { - endpoint: { - uri: 'uri' - } - } - }; - const deployDelegate = new DeployDelegate(TEST_BUILTIN_TYPE, TEST_INSTANCE); - // call - try { - deployDelegate.validateDeployDelegateResponse(TEST_DEPLOY_RESULT); - } catch (e) { - // verify - expect(e.message).equal('[Error]: Invalid response from deploy delegate. "deployState" field must exist in the response.'); - } - }); + it("| deploy result misses deployState field, expect error thrown", () => { + // setup + const TEST_DEPLOY_RESULT = { + default: { + endpoint: { + uri: "uri", + }, + }, + }; + const deployDelegate = new DeployDelegate(TEST_BUILTIN_TYPE, TEST_INSTANCE); + // call + try { + deployDelegate.validateDeployDelegateResponse(TEST_DEPLOY_RESULT); + } catch (e) { + // verify + expect(e.message).equal('[Error]: Invalid response from deploy delegate. "deployState" field must exist in the response.'); + } + }); - it('| deploy result is valid, expect no error thrown', () => { - // setup - const TEST_DEPLOY_RESULT = { - default: { - endpoint: { - uri: 'uri' - }, - deployState: {} - } - }; - const deployDelegate = new DeployDelegate(TEST_BUILTIN_TYPE, TEST_INSTANCE); - // call - try { - deployDelegate.validateDeployDelegateResponse(TEST_DEPLOY_RESULT); - } catch (e) { - // verify - expect(e).equal(null); - } - }); + it("| deploy result is valid, expect no error thrown", () => { + // setup + const TEST_DEPLOY_RESULT = { + default: { + endpoint: { + uri: "uri", + }, + deployState: {}, + }, + }; + const deployDelegate = new DeployDelegate(TEST_BUILTIN_TYPE, TEST_INSTANCE); + // call + try { + deployDelegate.validateDeployDelegateResponse(TEST_DEPLOY_RESULT); + } catch (e) { + // verify + expect(e).equal(null); + } }); + }); - describe('# test factory method: loadDeployDelegate', () => { - const TEST_INVALID_TYPE = 'invalid'; + describe("# test factory method: loadDeployDelegate", () => { + const TEST_INVALID_TYPE = "invalid"; - afterEach(() => { - sinon.restore(); - }); + afterEach(() => { + sinon.restore(); + }); - it('| when type is not recognized expect throws error', (done) => { - // call - DeployDelegate.load(TEST_INVALID_TYPE, (err, res) => { - // verify - expect(err).equal(`[Error]: Skill infrastructure type "${TEST_INVALID_TYPE}" is not recognized by ask-cli.`); - expect(res).equal(undefined); - done(); - }); - }); + it("| when type is not recognized expect throws error", (done) => { + // call + DeployDelegate.load(TEST_INVALID_TYPE, (err, res) => { + // verify + expect(err).equal(`[Error]: Skill infrastructure type "${TEST_INVALID_TYPE}" is not recognized by ask-cli.`); + expect(res).equal(undefined); + done(); + }); + }); - it('| when type is cli builtin type but fail to pass the validation', (done) => { - // setup - const stubPath = path.join(__dirname, '..', 'fixture', 'controller', 'invalid-deploy-delegate-instance'); - sinon.stub(path, 'join').returns(stubPath); - // call - DeployDelegate.load(TEST_BUILTIN_TYPE, (err, res) => { - // verify - expect(err.startsWith(`[Error]: Built-in skill infrastructure type "${TEST_BUILTIN_TYPE}" failed to load.\n`)).equal(true); - expect(res).equal(undefined); - done(); - }); - }); + it("| when type is cli builtin type but fail to pass the validation", (done) => { + // setup + const stubPath = path.join(__dirname, "..", "fixture", "controller", "invalid-deploy-delegate-instance"); + sinon.stub(path, "join").returns(stubPath); + // call + DeployDelegate.load(TEST_BUILTIN_TYPE, (err, res) => { + // verify + expect(err.startsWith(`[Error]: Built-in skill infrastructure type "${TEST_BUILTIN_TYPE}" failed to load.\n`)).equal(true); + expect(res).equal(undefined); + done(); + }); + }); - it('| when type is cli builtin type callback with deploy delegate instance', (done) => { - // setup - const stubPath = path.join(__dirname, '..', 'fixture', 'controller', 'valid-deploy-delegate-instance'); - sinon.stub(path, 'join').returns(stubPath); - DeployDelegate.load(TEST_BUILTIN_TYPE, (err, res) => { - // verify - expect(err).equal(null); - expect(res).to.be.instanceOf(DeployDelegate); - done(); - }); - }); + it("| when type is cli builtin type callback with deploy delegate instance", (done) => { + // setup + const stubPath = path.join(__dirname, "..", "fixture", "controller", "valid-deploy-delegate-instance"); + sinon.stub(path, "join").returns(stubPath); + DeployDelegate.load(TEST_BUILTIN_TYPE, (err, res) => { + // verify + expect(err).equal(null); + expect(res).to.be.instanceOf(DeployDelegate); + done(); + }); }); + }); }); diff --git a/test/unit/controller/dialog-controller/index-test.js b/test/unit/controller/dialog-controller/index-test.js deleted file mode 100644 index 277bb9c5..00000000 --- a/test/unit/controller/dialog-controller/index-test.js +++ /dev/null @@ -1,454 +0,0 @@ -const chalk = require('chalk'); -const { expect } = require('chai'); -const fs = require('fs-extra'); -const sinon = require('sinon'); - -const DialogController = require('@src/controllers/dialog-controller'); -const DialogReplView = require('@src/view/dialog-repl-view'); -const Messenger = require('@src/view/messenger'); - -describe('Controller test - dialog controller test', () => { - const TEST_MSG = 'TEST_MSG'; - const RECORD_FORMAT = 'Please use the format: ".record " or ".record --append-quit"'; - - describe('# test constructor', () => { - it('| constructor with config parameter returns DialogController object', () => { - // call - const dialogController = new DialogController({ - profile: 'default', - debug: true, - skillId: 'a1b2c3', - locale: 'en-US', - stage: 'DEVELOPMENT', - newSession: false - }); - // verify - expect(dialogController).to.be.instanceOf(DialogController); - expect(dialogController.smapiClient.profile).equal('default'); - expect(dialogController.utteranceCache.length).equal(0); - }); - - it('| constructor with empty config object returns DialogController object', () => { - // call - const dialogController = new DialogController({}); - // verify - expect(dialogController).to.be.instanceOf(DialogController); - expect(dialogController.smapiClient.profile).equal(undefined); - expect(dialogController.utteranceCache.length).equal(0); - }); - - it('| constructor with no args throws exception', () => { - try { - // setup & call - new DialogController(); - } catch (err) { - // verify - expect(err).to.match(new RegExp('Cannot have an undefined configuration.')); - } - }); - }); - - describe('# test class method - startSkillSimulation', () => { - let simulateSkillStub; - let dialogController; - - beforeEach(() => { - dialogController = new DialogController({}); - simulateSkillStub = sinon.stub(dialogController.smapiClient.skill.test, 'simulateSkill'); - }); - - afterEach(() => { - sinon.restore(); - }); - - it('| test utterance input and response is stored into appropriate caches', (done) => { - // setup - simulateSkillStub.callsArgWith(6, null, { msg: TEST_MSG }); - // call - dialogController.startSkillSimulation(TEST_MSG, (err, response) => { - // verify - expect(err).equal(null); - expect(dialogController.utteranceCache.length).equal(1); - expect(dialogController.utteranceCache[0]).equal(response.msg); - done(); - }); - }); - - it('| test an error in request does not effect caches', (done) => { - // setup - simulateSkillStub.callsArgWith(6, TEST_MSG, null); - // call - dialogController.startSkillSimulation(TEST_MSG, (err, response) => { - // verify - expect(err).equal(TEST_MSG); - expect(response).equal(undefined); - expect(dialogController.utteranceCache.length).equal(0); - done(); - }); - }); - }); - - describe('# test class method - getSkillSimulationResult', () => { - let getSimulationStub; - let dialogController; - - beforeEach(() => { - dialogController = new DialogController({}); - getSimulationStub = sinon.stub(dialogController.smapiClient.skill.test, 'getSimulation'); - }); - - afterEach(() => { - sinon.restore(); - }); - - it('| test valid simulation response', (done) => { - // setup - const output = { - statusCode: 200, - headers: {}, - body: { - status: 'SUCCESSFUL', - msg: TEST_MSG - } - }; - getSimulationStub.callsArgWith(3, null, output); - // call - dialogController.getSkillSimulationResult(TEST_MSG, (err, response) => { - // verify - expect(err).equal(null); - expect(response).to.deep.equal(output); - done(); - }); - }); - - it('| test an error in request', (done) => { - // setup - getSimulationStub.callsArgWith(3, TEST_MSG, null); - // call - dialogController.getSkillSimulationResult(TEST_MSG, (err, response) => { - // verify - expect(err).equal(TEST_MSG); - expect(response).equal(undefined); - done(); - }); - }); - - it('| test an error in response', (done) => { - // setup - const output = { - statusCode: 200, - headers: {}, - body: { - status: 'SUCCESSFUL', - msg: TEST_MSG, - result: { - error: { - message: TEST_MSG - } - } - } - }; - getSimulationStub.callsArgWith(3, null, output); - // call - dialogController.getSkillSimulationResult(TEST_MSG, (err, response) => { - // verify - expect(err).equal(TEST_MSG); - expect(response).equal(undefined); - done(); - }); - }); - }); - - describe('# test class method - clearSession', () => { - it('| values are reset after method call', () => { - // setup - const dialogController = new DialogController({}); - - // call - dialogController.clearSession(); - - // verify - expect(dialogController.newSession).equal(true); - }); - }); - - describe('# test class method - createReplayFile', () => { - afterEach(() => { - sinon.restore(); - }); - - it('| successful replay file creation', () => { - // setup - const utterances = ['userUtterance']; - const dialogController = new DialogController({}); - const fileSystemStub = sinon.stub(fs, 'outputJSONSync'); - - // call - dialogController.createReplayFile('random_file_name', utterances); - - // verify - expect(fileSystemStub.callCount).equal(1); - expect(fileSystemStub.args[0][1].userInput).deep.equal(utterances); - }); - - it('| file name is empty', () => { - // setup - const dialogController = new DialogController({}); - - // call - dialogController.createReplayFile(''); - - // verify - expect(dialogController.utteranceCache.length).equal(0); - }); - }); - - describe('# test class method - setupSpecialCommands', () => { - const dialogController = new DialogController({}); - const dialogReplView = new DialogReplView({}); - - afterEach(() => { - sinon.restore(); - }); - - it('| Invalid record command format', () => { - // setup - sinon.stub(DialogReplView.prototype, 'registerRecordCommand'); - DialogReplView.prototype.registerRecordCommand.callsArgWith(0, ''); - const warnStub = sinon.stub(); - sinon.stub(Messenger, 'getInstance').returns({ - warn: warnStub - }); - - // call - dialogController.setupSpecialCommands(dialogReplView, () => {}); - - // verify - expect(warnStub.args[0][0]).equal(`Incorrect format. ${RECORD_FORMAT}`); - }); - - it('| Invalid record command format, malformed --append-quit argument', () => { - // setup - const malFormedAppendQuitArgument = '--append'; - sinon.stub(DialogReplView.prototype, 'registerRecordCommand'); - DialogReplView.prototype.registerRecordCommand.callsArgWith(0, `history.json ${malFormedAppendQuitArgument}`); - const warnStub = sinon.stub(); - sinon.stub(Messenger, 'getInstance').returns({ - warn: warnStub - }); - - // call - dialogController.setupSpecialCommands(dialogReplView, () => {}); - - // verify - expect(warnStub.args[0][0]).equal(`Unable to validate arguments: "${malFormedAppendQuitArgument}". ${RECORD_FORMAT}`); - }); - - it('| replay file creation throws error', (done) => { - // setup - const infoStub = sinon.stub().throws(new Error(TEST_MSG)); - sinon.stub(Messenger, 'getInstance').returns({ - info: infoStub - }); - const replayStub = sinon.stub(DialogController.prototype, 'createReplayFile'); - sinon.stub(DialogReplView.prototype, 'registerRecordCommand'); - DialogReplView.prototype.registerRecordCommand.callsArgWith(0, 'file.json'); - - // call - dialogController.setupSpecialCommands(dialogReplView, (error) => { - expect(error.message).equal(TEST_MSG); - expect(replayStub.calledOnce).equal(true); - expect(infoStub.calledOnce).equal(true); - done(); - }); - }); - - it('| Valid record command format, with --append-quit argument', () => { - // setup - const appendQuitArgument = '--append-quit'; - const filePath = 'history.json'; - sinon.stub(DialogReplView.prototype, 'registerRecordCommand'); - DialogReplView.prototype.registerRecordCommand.callsArgWith(0, `${filePath} ${appendQuitArgument}`); - const infoStub = sinon.stub(); - sinon.stub(Messenger, 'getInstance').returns({ - info: infoStub - }); - const replayStub = sinon.stub(DialogController.prototype, 'createReplayFile'); - - // call - dialogController.setupSpecialCommands(dialogReplView, () => {}); - - // verify - expect(infoStub.args[0][0]).equal(`Created replay file at ${filePath} (appended ".quit" to list of utterances).`); - expect(replayStub.calledOnce).equal(true); - expect(replayStub.args[0][0]).equal(filePath); - expect(replayStub.args[0][1][0]).equal('.quit'); - }); - }); - - describe('# test evaluateUtterance -', () => { - const dialogController = new DialogController({}); - const utterance = 'hello'; - const simulationId = 'simulationId'; - const prompt = chalk.yellow.bold('Alexa > '); - let infoStub; - let errorStub; - let terminateSpinnerStub; - let updateSpinnerStub; - let startSpinnerStub; - let replViewStub; - - beforeEach(() => { - infoStub = sinon.stub(); - errorStub = sinon.stub(); - terminateSpinnerStub = sinon.stub(); - updateSpinnerStub = sinon.stub(); - startSpinnerStub = sinon.stub(); - sinon.stub(Messenger, 'getInstance').returns({ - info: infoStub, - error: errorStub - }); - replViewStub = { - startProgressSpinner: startSpinnerStub, - terminateProgressSpinner: terminateSpinnerStub, - updateProgressSpinner: updateSpinnerStub - }; - }); - - afterEach(() => { - sinon.restore(); - }); - - it('| start skill simulation throws error', (done) => { - // setup - sinon.stub(DialogController.prototype, 'startSkillSimulation').callsArgWith(1, TEST_MSG); - // call - dialogController.evaluateUtterance(utterance, replViewStub, () => { - // verify - expect(startSpinnerStub.args[0][0]).equal('Sending simulation request to Alexa...'); - expect(terminateSpinnerStub.calledOnce).equal(true); - expect(errorStub.args[0][0]).equal(TEST_MSG); - done(); - }); - }); - - it('| start skill simulation throws error', (done) => { - // setup - const response = { - statusCode: 400, - body: { - error: { - message: TEST_MSG - } - } - }; - sinon.stub(DialogController.prototype, 'startSkillSimulation').callsArgWith(1, null, response); - // call - dialogController.evaluateUtterance(utterance, replViewStub, () => { - // verify - expect(startSpinnerStub.args[0][0]).equal('Sending simulation request to Alexa...'); - expect(terminateSpinnerStub.calledOnce).equal(true); - expect(errorStub.args[0][0]).equal(TEST_MSG); - done(); - }); - }); - - it('| get skill simulation result throws error', (done) => { - // setup - const response = { - statusCode: 200, - body: { - id: simulationId - } - }; - sinon.stub(DialogController.prototype, 'startSkillSimulation').callsArgWith(1, null, response); - sinon.stub(DialogController.prototype, 'getSkillSimulationResult').callsArgWith(1, TEST_MSG); - // call - dialogController.evaluateUtterance(utterance, replViewStub, () => { - // verify - expect(startSpinnerStub.args[0][0]).equal('Sending simulation request to Alexa...'); - expect(updateSpinnerStub.args[0][0]).equal('Waiting for the simulation response...'); - expect(terminateSpinnerStub.calledOnce).equal(true); - expect(errorStub.args[0][0]).equal(TEST_MSG); - done(); - }); - }); - - it('| valid response is returned with existing session', (done) => { - // setup - const response = { - statusCode: 200, - body: { - id: simulationId, - result: { - alexaExecutionInfo: { - alexaResponses: [{ - content: { - caption: 'hello' - } - }] - }, - skillExecutionInfo: { - invocations: ['hello'] - } - } - } - }; - sinon.stub(DialogController.prototype, 'startSkillSimulation').callsArgWith(1, null, response); - sinon.stub(DialogController.prototype, 'getSkillSimulationResult').callsArgWith(1, null, response); - // call - dialogController.evaluateUtterance(utterance, replViewStub, () => { - // verify - expect(startSpinnerStub.args[0][0]).equal('Sending simulation request to Alexa...'); - expect(updateSpinnerStub.args[0][0]).equal('Waiting for the simulation response...'); - expect(terminateSpinnerStub.calledOnce).equal(true); - expect(infoStub.args[0][0]).equal(`${prompt}hello`); - done(); - }); - }); - - it('| valid response is returned with a new session', (done) => { - // setup - const response = { - statusCode: 200, - body: { - id: simulationId, - result: { - alexaExecutionInfo: { - alexaResponses: [{ - content: { - caption: 'hello' - } - }] - }, - skillExecutionInfo: { - invocations: [{ - invocationResponse: { - body: { - response: { - shouldEndSession: true - } - } - } - }] - } - } - } - }; - sinon.stub(DialogController.prototype, 'startSkillSimulation').callsArgWith(1, null, response); - sinon.stub(DialogController.prototype, 'getSkillSimulationResult').callsArgWith(1, null, response); - const clearSessionStub = sinon.stub(DialogController.prototype, 'clearSession'); - // call - dialogController.evaluateUtterance(utterance, replViewStub, () => { - // verify - expect(startSpinnerStub.args[0][0]).equal('Sending simulation request to Alexa...'); - expect(updateSpinnerStub.args[0][0]).equal('Waiting for the simulation response...'); - expect(terminateSpinnerStub.calledOnce).equal(true); - expect(clearSessionStub.calledOnce).equal(true); - expect(infoStub.args[0][0]).equal('Session ended'); - expect(infoStub.args[1][0]).equal(`${prompt}hello`); - done(); - }); - }); - }); -}); diff --git a/test/unit/controller/dialog-controller/index.spec.ts b/test/unit/controller/dialog-controller/index.spec.ts new file mode 100644 index 00000000..46615fd3 --- /dev/null +++ b/test/unit/controller/dialog-controller/index.spec.ts @@ -0,0 +1,442 @@ +import chalk from "chalk"; +import {expect} from "chai"; +import fs from "fs-extra"; +import sinon from "sinon"; + +import {DialogController, DialogControllerProps} from "../../../../lib/controllers/dialog-controller"; +import {DialogReplView} from "../../../../lib/view/dialog-repl-view"; +import Messenger from "../../../../lib/view/messenger"; +import {RetriableServiceError} from "../../../../lib/exceptions/cli-retriable-error"; + +const baseDialogControllerProps: DialogControllerProps = { + profile: "default", + debug: true, + skillId: "a1b2c3", + locale: "en-US", + stage: "DEVELOPMENT", + newSession: false, + saveSkillIo: "", +}; + +describe("Controller test - dialog controller test", () => { + const TEST_MSG = "TEST_MSG"; + const RECORD_FORMAT = 'Please use the format: ".record " or ".record --append-quit"'; + + describe("# test constructor", () => { + it("| constructor with config parameter returns DialogController object", () => { + // call + const dialogController = new DialogController(baseDialogControllerProps); + // verify + expect(dialogController).to.be.instanceOf(DialogController); + expect(dialogController.smapiClient.profile).equal("default"); + expect(dialogController.utteranceCache.length).equal(0); + }); + + it("| constructor with empty config object returns DialogController object", () => { + // call + const dialogController = new DialogController({} as any); + // verify + expect(dialogController).to.be.instanceOf(DialogController); + expect(dialogController.smapiClient.profile).equal(undefined); + expect(dialogController.utteranceCache.length).equal(0); + }); + + it("| constructor with no args throws exception", () => { + try { + // setup & call + new DialogController({} as any); + } catch (err) { + // verify + expect(err).to.match(new RegExp("Cannot have an undefined configuration.")); + } + }); + }); + + describe("# test class method - startSkillSimulation", () => { + let simulateSkillStub: sinon.SinonStub; + let dialogController: DialogController; + + beforeEach(() => { + dialogController = new DialogController(baseDialogControllerProps); + simulateSkillStub = sinon.stub(dialogController.smapiClient.skill.test, "simulateSkill"); + }); + + afterEach(() => { + sinon.restore(); + }); + + it("| test utterance input and response is stored into appropriate caches", async () => { + // setup + simulateSkillStub.resolves({body: TEST_MSG}); + // call + const response = await dialogController.startSkillSimulation(TEST_MSG); + // verify + expect(dialogController.utteranceCache.length).equal(1); + expect(dialogController.utteranceCache[0]).equal(response.body); + }); + + it("| test an error in request does not effect caches", async () => { + // setup + simulateSkillStub.rejects(TEST_MSG); + // call + await expect(dialogController.startSkillSimulation(TEST_MSG)).rejectedWith(TEST_MSG); + // verify + expect(dialogController.utteranceCache.length).equal(0); + }); + }); + + describe("# test class method - getSkillSimulationResult", () => { + let getSimulationStub: sinon.SinonStub; + let dialogController: DialogController; + + beforeEach(() => { + dialogController = new DialogController(baseDialogControllerProps); + getSimulationStub = sinon.stub(dialogController.smapiClient.skill.test, "getSimulation"); + }); + + afterEach(() => { + sinon.restore(); + }); + + it("| test valid simulation response", async () => { + // setup + const output = { + statusCode: 200, + headers: {}, + body: { + status: "SUCCESSFUL", + msg: TEST_MSG, + }, + }; + getSimulationStub.resolves(output); + // call + const response = await dialogController.getSkillSimulationResult(TEST_MSG); + expect(response).to.deep.equal(output); + }); + + it("| test an error in request", async () => { + // setup + getSimulationStub.rejects(TEST_MSG); + // call + try { + await dialogController.getSkillSimulationResult(TEST_MSG); + } catch (err) { + // verify + expect((err as any).message).equal(TEST_MSG); + } + }); + + it("| test an error in response", async () => { + // setup + const output = { + statusCode: 200, + headers: {}, + body: { + status: "SUCCESSFUL", + msg: TEST_MSG, + result: { + error: { + message: TEST_MSG, + }, + }, + }, + }; + getSimulationStub.resolves(output); + // call + try { + await dialogController.getSkillSimulationResult(TEST_MSG); + } catch (err) { + // verify + expect((err as any).message).equal(TEST_MSG); + } + }); + }); + + describe("# test class method - clearSession", () => { + it("| values are reset after method call", () => { + // setup + const dialogController = new DialogController(baseDialogControllerProps); + + // call + dialogController.clearSession(); + + // verify + expect(dialogController.newSession).equal(true); + }); + }); + + describe("# test class method - createReplayFile", () => { + afterEach(() => { + sinon.restore(); + }); + + it("| successful replay file creation", () => { + // setup + const utterances = ["userUtterance"]; + const dialogController = new DialogController(baseDialogControllerProps); + const fileSystemStub = sinon.stub(fs, "outputJSONSync"); + + // call + dialogController.createReplayFile("random_file_name", utterances); + + // verify + expect(fileSystemStub).calledOnce; + expect(fileSystemStub).calledOnceWith(sinon.match.any, sinon.match({userInput: utterances})); + }); + + it("| file name is empty", () => { + // setup + const dialogController = new DialogController(baseDialogControllerProps); + + // call + dialogController.createReplayFile("", ""); + + // verify + expect(dialogController.utteranceCache.length).equal(0); + }); + }); + + describe("# test class method - setupSpecialCommands", () => { + const dialogController = new DialogController(baseDialogControllerProps); + let dialogReplView: DialogReplView; + + beforeEach(() => { + dialogReplView = new DialogReplView({} as any); + }); + + afterEach(() => { + sinon.restore(); + dialogReplView.close(); + }); + + it("| Invalid record command format", async () => { + // setup + const stubInstance = sinon.stub(DialogReplView.prototype, "registerRecordCommand"); + stubInstance.callsArgWith(0, ""); + const warnStub = sinon.stub(); + sinon.stub(Messenger, "getInstance").returns({ + warn: warnStub, + }); + + // call + await expect(dialogController.setupSpecialCommands(dialogReplView)).rejected; + + // verify + expect(warnStub).calledOnceWith(`Incorrect format. ${RECORD_FORMAT}`); + }); + + it("| Invalid record command format, malformed --append-quit argument", async () => { + // setup + const malFormedAppendQuitArgument = "--append"; + const stubInstance = sinon.stub(DialogReplView.prototype, "registerRecordCommand"); + stubInstance.callsArgWith(0, `history.json ${malFormedAppendQuitArgument}`); + const warnStub = sinon.stub(); + sinon.stub(Messenger, "getInstance").returns({ + warn: warnStub, + }); + + // call + await dialogController.setupSpecialCommands(dialogReplView); + + // verify + expect(warnStub).calledOnceWith(`Unable to validate arguments: "${malFormedAppendQuitArgument}". ${RECORD_FORMAT}`); + }); + + it("| replay file creation throws error", async () => { + // setup + const infoStub = sinon.stub().throws(new Error(TEST_MSG)); + sinon.stub(Messenger, "getInstance").returns({ + info: infoStub, + }); + const replayStub = sinon.stub(DialogController.prototype, "createReplayFile"); + const stubInstance = sinon.stub(DialogReplView.prototype, "registerRecordCommand"); + stubInstance.callsArgWith(0, "file.json"); + + // call + await expect(dialogController.setupSpecialCommands(dialogReplView)).rejectedWith(TEST_MSG); + + expect(replayStub).calledOnce; + expect(infoStub).calledOnce; + }); + + it("| Valid record command format, with --append-quit argument", async () => { + // setup + const appendQuitArgument = "--append-quit"; + const filePath = "history.json"; + const stubInstance = sinon.stub(DialogReplView.prototype, "registerRecordCommand"); + stubInstance.callsArgWith(0, `${filePath} ${appendQuitArgument}`); + const infoStub = sinon.stub(); + sinon.stub(Messenger, "getInstance").returns({ + info: infoStub, + }); + const replayStub = sinon.stub(DialogController.prototype, "createReplayFile"); + + // call + await dialogController.setupSpecialCommands(dialogReplView); + + // verify + expect(infoStub).calledOnceWith(`Created replay file at ${filePath} (appended ".quit" to list of utterances).`); + expect(replayStub.calledOnce).equal(true); + expect(replayStub).calledOnceWith(filePath); + expect(replayStub).calledOnceWith(sinon.match.any, sinon.match.array.contains([".quit"])); + }); + }); + + describe("# test evaluateUtterance -", () => { + const dialogController: DialogController = new DialogController(baseDialogControllerProps); + const utterance = "hello"; + const simulationId = "simulationId"; + const prompt = chalk.yellow.bold("Alexa > "); + let infoStub: sinon.SinonStub; + let errorStub: sinon.SinonStub; + let terminateSpinnerStub: sinon.SinonStub; + let updateSpinnerStub: sinon.SinonStub; + let startSpinnerStub: sinon.SinonStub; + let replViewStub: DialogReplView; + + beforeEach(() => { + infoStub = sinon.stub(); + errorStub = sinon.stub(); + terminateSpinnerStub = sinon.stub(); + updateSpinnerStub = sinon.stub(); + startSpinnerStub = sinon.stub(); + sinon.stub(Messenger, "getInstance").returns({ + info: infoStub, + error: errorStub, + }); + replViewStub = { + startProgressSpinner: startSpinnerStub, + terminateProgressSpinner: terminateSpinnerStub, + updateProgressSpinner: updateSpinnerStub, + } as any; + }); + + afterEach(() => { + sinon.restore(); + }); + + it("| start skill simulation throws error", async () => { + // setup + sinon.stub(DialogController.prototype, "startSkillSimulation").rejects(Error(TEST_MSG)); + + // call + await expect(dialogController.evaluateUtterance(utterance, replViewStub)).eventually.rejected; + + // verify + expect(startSpinnerStub).calledOnceWith("Sending simulation request to Alexa..."); + expect(terminateSpinnerStub).calledOnce; + expect(errorStub).calledOnceWith(TEST_MSG); + }); + + it("| start skill simulation throws error", async () => { + // setup + sinon.stub(dialogController, "startSkillSimulation").rejects(new RetriableServiceError(TEST_MSG)); + + // call + await expect(dialogController.evaluateUtterance(utterance, replViewStub)).rejected; + + // verify + expect(startSpinnerStub).calledOnceWith("Sending simulation request to Alexa..."); + expect(terminateSpinnerStub).calledOnce; + expect(errorStub).calledOnceWith(TEST_MSG); + }); + + it("| get skill simulation result throws error", async () => { + // setup + const response = { + statusCode: 200, + body: { + id: simulationId, + }, + }; + sinon.stub(DialogController.prototype, "startSkillSimulation").resolves(response as any); + sinon.stub(DialogController.prototype, "getSkillSimulationResult").rejects(new RetriableServiceError(TEST_MSG)); + // call + await expect(dialogController.evaluateUtterance(utterance, replViewStub)).eventually.rejected; + // verify + expect(startSpinnerStub).calledOnceWith("Sending simulation request to Alexa..."); + expect(updateSpinnerStub).calledOnceWith("Waiting for the simulation response..."); + expect(terminateSpinnerStub).calledOnce; + expect(errorStub).calledOnceWith(TEST_MSG); + }); + + it("| valid response is returned with existing session", async () => { + // setup + const response = { + statusCode: 200, + body: { + id: simulationId, + result: { + alexaExecutionInfo: { + alexaResponses: [ + { + content: { + caption: "hello", + }, + }, + ], + }, + skillExecutionInfo: { + invocations: ["hello"], + }, + }, + }, + }; + sinon.stub(DialogController.prototype, "startSkillSimulation").resolves(response as any); + sinon.stub(DialogController.prototype, "getSkillSimulationResult").resolves(response); + // call + await dialogController.evaluateUtterance(utterance, replViewStub); + // verify + expect(startSpinnerStub).calledOnceWith("Sending simulation request to Alexa..."); + expect(updateSpinnerStub).calledOnceWith("Waiting for the simulation response..."); + expect(terminateSpinnerStub).calledOnce; + expect(infoStub).calledOnceWith(`${prompt}hello`); + }); + + it("| valid response is returned with a new session", async () => { + // setup + const response = { + statusCode: 200, + body: { + id: simulationId, + result: { + alexaExecutionInfo: { + alexaResponses: [ + { + content: { + caption: "hello", + }, + }, + ], + }, + skillExecutionInfo: { + invocations: [ + { + invocationResponse: { + body: { + response: { + shouldEndSession: true, + }, + }, + }, + }, + ], + }, + }, + }, + }; + sinon.stub(DialogController.prototype, "startSkillSimulation").resolves(response as any); + sinon.stub(DialogController.prototype, "getSkillSimulationResult").resolves(response); + const clearSessionStub = sinon.stub(DialogController.prototype, "clearSession"); + // call + await dialogController.evaluateUtterance(utterance, replViewStub); + // verify + expect(startSpinnerStub).calledOnceWith("Sending simulation request to Alexa..."); + expect(updateSpinnerStub).calledOnceWith("Waiting for the simulation response..."); + expect(terminateSpinnerStub).calledOnce; + expect(clearSessionStub.calledOnce).equal(true); + expect(infoStub).calledWith("Session ended"); + expect(infoStub).calledWith(`${prompt}hello`); + }); + }); +}); diff --git a/test/unit/controller/dialog-controller/index.test.ts b/test/unit/controller/dialog-controller/index.test.ts new file mode 100644 index 00000000..e128dc5d --- /dev/null +++ b/test/unit/controller/dialog-controller/index.test.ts @@ -0,0 +1,442 @@ +import chalk from "chalk"; +import {expect} from "chai"; +import fs from "fs-extra"; +import sinon from "sinon"; + +import {DialogController, DialogControllerProps} from "../../../../lib/controllers/dialog-controller"; +import {DialogReplView} from "../../../../lib/view/dialog-repl-view"; +import Messenger from "../../../../lib/view/messenger"; +import {RetriableServiceError} from "../../../../lib/exceptions/cli-retriable-error"; + +const baseDialogControllerProps: DialogControllerProps = { + profile: "default", + debug: true, + skillId: "a1b2c3", + locale: "en-US", + stage: "DEVELOPMENT", + newSession: false, + saveSkillIo: "", +}; + +describe("Controller test - dialog controller test", () => { + const TEST_MSG = "TEST_MSG"; + const RECORD_FORMAT = 'Please use the format: ".record " or ".record --append-quit"'; + + describe("# test constructor", () => { + it("| constructor with config parameter returns DialogController object", () => { + // call + const dialogController = new DialogController(baseDialogControllerProps); + // verify + expect(dialogController).to.be.instanceOf(DialogController); + expect(dialogController.smapiClient.profile).equal("default"); + expect(dialogController.utteranceCache.length).equal(0); + }); + + it("| constructor with empty config object returns DialogController object", () => { + // call + const dialogController = new DialogController({} as any); + // verify + expect(dialogController).to.be.instanceOf(DialogController); + expect(dialogController.smapiClient.profile).equal(undefined); + expect(dialogController.utteranceCache.length).equal(0); + }); + + it("| constructor with no args throws exception", () => { + try { + // setup & call + new DialogController({} as any); + } catch (err) { + // verify + expect(err).to.match(new RegExp("Cannot have an undefined configuration.")); + } + }); + }); + + describe("# test class method - startSkillSimulation", () => { + let simulateSkillStub: sinon.SinonStub; + let dialogController: DialogController; + + beforeEach(() => { + dialogController = new DialogController(baseDialogControllerProps); + simulateSkillStub = sinon.stub(dialogController.smapiClient.skill.test, "simulateSkill"); + }); + + afterEach(() => { + sinon.restore(); + }); + + it("| test utterance input and response is stored into appropriate caches", async () => { + // setup + simulateSkillStub.resolves({body: TEST_MSG}); + // call + const response = await dialogController.startSkillSimulation(TEST_MSG); + // verify + expect(dialogController.utteranceCache.length).equal(1); + expect(dialogController.utteranceCache[0]).equal(response.body); + }); + + it("| test an error in request does not effect caches", async () => { + // setup + simulateSkillStub.rejects(TEST_MSG); + // call + await expect(dialogController.startSkillSimulation(TEST_MSG)).rejectedWith(TEST_MSG); + // verify + expect(dialogController.utteranceCache.length).equal(0); + }); + }); + + describe("# test class method - getSkillSimulationResult", () => { + let getSimulationStub: sinon.SinonStub; + let dialogController: DialogController; + + beforeEach(() => { + dialogController = new DialogController(baseDialogControllerProps); + getSimulationStub = sinon.stub(dialogController.smapiClient.skill.test, "getSimulation"); + }); + + afterEach(() => { + sinon.restore(); + }); + + it("| test valid simulation response", async () => { + // setup + const output = { + statusCode: 200, + headers: {}, + body: { + status: "SUCCESSFUL", + msg: TEST_MSG, + }, + }; + getSimulationStub.resolves(output); + // call + const response = await dialogController.getSkillSimulationResult(TEST_MSG); + expect(response).to.deep.equal(output); + }); + + it("| test an error in request", async () => { + // setup + getSimulationStub.rejects(TEST_MSG); + // call + try { + await dialogController.getSkillSimulationResult(TEST_MSG); + } catch (err) { + // verify + expect((err as any).message).equal(TEST_MSG); + } + }); + + it("| test an error in response", async () => { + // setup + const output = { + statusCode: 200, + headers: {}, + body: { + status: "SUCCESSFUL", + msg: TEST_MSG, + result: { + error: { + message: TEST_MSG, + }, + }, + }, + }; + getSimulationStub.resolves(output); + // call + try { + await dialogController.getSkillSimulationResult(TEST_MSG); + } catch (err) { + // verify + expect((err as any).message).equal(TEST_MSG); + } + }); + }); + + describe("# test class method - clearSession", () => { + it("| values are reset after method call", () => { + // setup + const dialogController = new DialogController(baseDialogControllerProps); + + // call + dialogController.clearSession(); + + // verify + expect(dialogController.newSession).equal(true); + }); + }); + + describe("# test class method - createReplayFile", () => { + afterEach(() => { + sinon.restore(); + }); + + it("| successful replay file creation", () => { + // setup + const utterances = ["userUtterance"]; + const dialogController = new DialogController(baseDialogControllerProps); + const fileSystemStub = sinon.stub(fs, "outputJSONSync"); + + // call + dialogController.createReplayFile("random_file_name", utterances); + + // verify + expect(fileSystemStub).calledOnce; + expect(fileSystemStub).calledOnceWith(sinon.match.any, sinon.match({userInput: utterances})); + }); + + it("| file name is empty", () => { + // setup + const dialogController = new DialogController(baseDialogControllerProps); + + // call + dialogController.createReplayFile("", ""); + + // verify + expect(dialogController.utteranceCache.length).equal(0); + }); + }); + + describe("# test class method - setupSpecialCommands", () => { + const dialogController = new DialogController(baseDialogControllerProps); + let dialogReplView: DialogReplView; + + beforeEach(() => { + dialogReplView = new DialogReplView({} as any); + }); + + afterEach(() => { + sinon.restore(); + dialogReplView.close(); + }); + + it("| Invalid record command format", async () => { + // setup + const stubInstance = sinon.stub(DialogReplView.prototype, "registerRecordCommand"); + stubInstance.callsArgWith(0, ""); + const warnStub = sinon.stub(); + sinon.stub(Messenger, "getInstance").returns({ + warn: warnStub, + }); + + // call + await expect(dialogController.setupSpecialCommands(dialogReplView)).rejected; + + // verify + expect(warnStub).calledOnceWith(`Incorrect format. ${RECORD_FORMAT}`); + }); + + it("| Invalid record command format, malformed --append-quit argument", async () => { + // setup + const malFormedAppendQuitArgument = "--append"; + const stubInstance = sinon.stub(DialogReplView.prototype, "registerRecordCommand"); + stubInstance.callsArgWith(0, `history.json ${malFormedAppendQuitArgument}`); + const warnStub = sinon.stub(); + sinon.stub(Messenger, "getInstance").returns({ + warn: warnStub, + }); + + // call + await dialogController.setupSpecialCommands(dialogReplView); + + // verify + expect(warnStub).calledOnceWith(`Unable to validate arguments: "${malFormedAppendQuitArgument}". ${RECORD_FORMAT}`); + }); + + it("| replay file creation throws error", async () => { + // setup + const infoStub = sinon.stub().throws(new Error(TEST_MSG)); + sinon.stub(Messenger, "getInstance").returns({ + info: infoStub, + }); + const replayStub = sinon.stub(DialogController.prototype, "createReplayFile"); + const stubInstance = sinon.stub(DialogReplView.prototype, "registerRecordCommand"); + stubInstance.callsArgWith(0, "file.json"); + + // call + await expect(dialogController.setupSpecialCommands(dialogReplView)).rejectedWith(TEST_MSG); + + expect(replayStub).calledOnce; + expect(infoStub).calledOnce; + }); + + it("| Valid record command format, with --append-quit argument", async () => { + // setup + const appendQuitArgument = "--append-quit"; + const filePath = "history.json"; + const stubInstance = sinon.stub(DialogReplView.prototype, "registerRecordCommand"); + stubInstance.callsArgWith(0, `${filePath} ${appendQuitArgument}`); + const infoStub = sinon.stub(); + sinon.stub(Messenger, "getInstance").returns({ + info: infoStub, + }); + const replayStub = sinon.stub(DialogController.prototype, "createReplayFile"); + + // call + await dialogController.setupSpecialCommands(dialogReplView); + + // verify + expect(infoStub).calledOnceWith(`Created replay file at ${filePath} (appended ".quit" to list of utterances).`); + expect(replayStub.calledOnce).equal(true); + expect(replayStub).calledOnceWith(filePath); + expect(replayStub).calledOnceWith(sinon.match.any, sinon.match.array.contains([".quit"])); + }); + }); + + describe("# test evaluateUtterance -", () => { + const dialogController: DialogController = new DialogController(baseDialogControllerProps); + const utterance = "hello"; + const simulationId = "simulationId"; + const prompt = chalk.yellow.bold("Alexa > "); + let infoStub: sinon.SinonStub; + let errorStub: sinon.SinonStub; + let terminateSpinnerStub: sinon.SinonStub; + let updateSpinnerStub: sinon.SinonStub; + let startSpinnerStub: sinon.SinonStub; + let replViewStub: DialogReplView; + + beforeEach(() => { + infoStub = sinon.stub(); + errorStub = sinon.stub(); + terminateSpinnerStub = sinon.stub(); + updateSpinnerStub = sinon.stub(); + startSpinnerStub = sinon.stub(); + sinon.stub(Messenger, "getInstance").returns({ + info: infoStub, + error: errorStub, + }); + replViewStub = { + startProgressSpinner: startSpinnerStub, + terminateProgressSpinner: terminateSpinnerStub, + updateProgressSpinner: updateSpinnerStub, + } as any; + }); + + afterEach(() => { + sinon.restore(); + }); + + it("| start skill simulation throws error", async () => { + // setup + sinon.stub(DialogController.prototype, "startSkillSimulation").rejects(Error(TEST_MSG)); + + // call + await expect(dialogController.evaluateUtterance(utterance, replViewStub)).eventually.rejected; + + // verify + expect(startSpinnerStub).calledOnceWith("Sending simulation request to Alexa..."); + expect(terminateSpinnerStub).calledOnce; + expect(errorStub).calledOnceWith(TEST_MSG); + }); + + it("| start skill simulation throws error", async () => { + // setup + sinon.stub(dialogController, "startSkillSimulation").rejects(new RetriableServiceError(TEST_MSG)); + + // call + await expect(dialogController.evaluateUtterance(utterance, replViewStub)).rejected; + + // verify + expect(startSpinnerStub).calledOnceWith("Sending simulation request to Alexa..."); + expect(terminateSpinnerStub).calledOnce; + expect(errorStub).calledOnceWith(TEST_MSG); + }); + + it("| get skill simulation result throws error", async () => { + // setup + const response = { + statusCode: 200, + body: { + id: simulationId, + }, + }; + sinon.stub(DialogController.prototype, "startSkillSimulation").resolves(response as any); + sinon.stub(DialogController.prototype, "getSkillSimulationResult").rejects(new RetriableServiceError(TEST_MSG)); + // call + await expect(dialogController.evaluateUtterance(utterance, replViewStub)).eventually.rejected; + // verify + expect(startSpinnerStub).calledOnceWith("Sending simulation request to Alexa..."); + expect(updateSpinnerStub).calledOnceWith("Waiting for the simulation response..."); + expect(terminateSpinnerStub).calledOnce; + expect(errorStub).calledOnceWith(TEST_MSG); + }); + + it("| valid response is returned with existing session", async () => { + // setup + const response = { + statusCode: 200, + body: { + id: simulationId, + result: { + alexaExecutionInfo: { + alexaResponses: [ + { + content: { + caption: "hello", + }, + }, + ], + }, + skillExecutionInfo: { + invocations: ["hello"], + }, + }, + }, + }; + sinon.stub(DialogController.prototype, "startSkillSimulation").resolves(response as any); + sinon.stub(DialogController.prototype, "getSkillSimulationResult").resolves(response); + // call + await dialogController.evaluateUtterance(utterance, replViewStub); + // verify + expect(startSpinnerStub).calledOnceWith("Sending simulation request to Alexa..."); + expect(updateSpinnerStub).calledOnceWith("Waiting for the simulation response..."); + expect(terminateSpinnerStub).calledOnce; + expect(infoStub).calledOnceWith(`${prompt}hello`); + }); + + it("| valid response is returned with a new session", async () => { + // setup + const response = { + statusCode: 200, + body: { + id: simulationId, + result: { + alexaExecutionInfo: { + alexaResponses: [ + { + content: { + caption: "hello", + }, + }, + ], + }, + skillExecutionInfo: { + invocations: [ + { + invocationResponse: { + body: { + response: { + shouldEndSession: true, + }, + }, + }, + }, + ], + }, + }, + }, + }; + sinon.stub(DialogController.prototype, "startSkillSimulation").resolves(response as any); + sinon.stub(DialogController.prototype, "getSkillSimulationResult").resolves(response); + const clearSessionStub = sinon.stub(DialogController.prototype, "clearSession"); + // call + await dialogController.evaluateUtterance(utterance, replViewStub); + // verify + expect(startSpinnerStub).calledOnceWith("Sending simulation request to Alexa..."); + expect(updateSpinnerStub).calledOnceWith("Waiting for the simulation response..."); + expect(terminateSpinnerStub).calledOnce; + expect(clearSessionStub.calledOnce).equal(true); + expect(infoStub).calledWith("Session ended"); + expect(infoStub).calledWith(`${prompt}hello`); + }); + }); +}); \ No newline at end of file diff --git a/test/unit/controller/dialog-controller/simulation-response-parser-test.js b/test/unit/controller/dialog-controller/simulation-response-parser-test.js deleted file mode 100644 index 9df079cd..00000000 --- a/test/unit/controller/dialog-controller/simulation-response-parser-test.js +++ /dev/null @@ -1,319 +0,0 @@ -const { expect } = require('chai'); -const responseParser = require('@src/controllers/dialog-controller/simulation-response-parser'); - -describe('Controller test - skill simulation response parser tests', () => { - describe('# helper function - getConsideredIntents', () => { - it('| Test for defined result', () => { - // setup - const TEST_RES = { foo: 'bar' }; - const TEST_OBJ = { - result: { - alexaExecutionInfo: { - consideredIntents: TEST_RES - } - } - }; - // call - const res = responseParser.getConsideredIntents(TEST_OBJ); - // verify - expect(res).deep.equal(TEST_RES); - }); - - it('| Test for undefined result', () => { - // setup - const TEST_OBJ = { - result: { - alexaExecutionInfo: {} - } - }; - // call - const res = responseParser.getConsideredIntents(TEST_OBJ); - // verify - expect(res).to.eql([]); - }); - }); - - describe('# helper function - getJsonInputAndOutputs', () => { - const TEST_MSG = 'TEST_MSG'; - - it('| Test for undefined invocations', () => { - // setup - const TEST_OBJ = { - result: { - skillExecutionInfo: {} - } - }; - // call - const res = responseParser.getJsonInputAndOutputs(TEST_OBJ); - // verify - expect(res).to.eql([]); - }); - - it('| Test for equal invocations requests and responses', () => { - // setup - const TEST_OBJ = { - result: { - skillExecutionInfo: { - invocations: [ - { - invocationRequest: { - body: TEST_MSG - }, - invocationResponse: { - body: TEST_MSG - } - }, - { - invocationRequest: { - body: TEST_MSG - }, - invocationResponse: { - body: TEST_MSG - } - } - ] - } - } - }; - // call - const res = responseParser.getJsonInputAndOutputs(TEST_OBJ); - // verify - expect(res.length).equal(2); - expect(res[0].jsonInput).deep.equal(TEST_MSG); - expect(res[0].jsonOutput).deep.equal({ body: TEST_MSG }); - expect(res[1].jsonInput).deep.equal(TEST_MSG); - expect(res[1].jsonOutput).deep.equal({ body: TEST_MSG }); - }); - - it('| Test for unequal invocations requests and responses', () => { - // setup - const TEST_OBJ = { - result: { - skillExecutionInfo: { - invocations: [ - { - invocationRequest: { - body: TEST_MSG - } - }, - { - invocationRequest: { - body: TEST_MSG - }, - invocationResponse: { - body: TEST_MSG - } - } - ] - } - } - }; - // call - const res = responseParser.getJsonInputAndOutputs(TEST_OBJ); - // verify - expect(res.length).equal(2); - expect(res[0].jsonInput).equal(TEST_MSG); - expect(res[0].jsonOutput).to.eql({}); - expect(res[1].jsonInput).equal(TEST_MSG); - expect(res[1].jsonOutput).to.eql({ body: TEST_MSG }); - }); - }); - - describe('# helper function - shouldEndSession', () => { - it('| Test for undefined invocations', () => { - // setup - const TEST_OBJ = { - result: { - skillExecutionInfo: {} - } - }; - // call - const res = responseParser.shouldEndSession(TEST_OBJ); - // verify - expect(res).equal(false); - }); - - it('| Test for invocations with one response with shouldEndSession', () => { - // setup - const TEST_OBJ = { - result: { - skillExecutionInfo: { - invocations: [ - { - invocationResponse: { - body: { - response: { - shouldEndSession: true - } - } - } - } - ] - } - } - }; - // call - const res = responseParser.shouldEndSession(TEST_OBJ); - // verify - expect(res).equal(true); - }); - - it('| Test for invocations with no response with shouldEndSession', () => { - // setup - const TEST_OBJ = { - result: { - skillExecutionInfo: { - invocations: [ - { - invocationResponse: { - body: { - response: { - shouldEndSession: false - } - } - } - } - ] - } - } - }; - // call - const res = responseParser.shouldEndSession(TEST_OBJ); - // verify - expect(res).equal(false); - }); - }); - - describe('# helper function - getErrorMessage', () => { - const TEST_MSG = 'TEST_MSG'; - - it('| Test with undefined error message', () => { - // setup - const TEST_OBJ = { - result: { - error: {} - } - }; - // call - const res = responseParser.getErrorMessage(TEST_OBJ); - // verify - expect(res).equal(undefined); - }); - - it('| Test with defined error message', () => { - // setup - const TEST_OBJ = { - result: { - error: { - message: TEST_MSG - } - } - }; - // call - const res = responseParser.getErrorMessage(TEST_OBJ); - // verify - expect(res).equal(TEST_MSG); - }); - }); - - describe('# helper function - getCaption', () => { - const TEST_MSG = 'TEST_MSG'; - - it('| Test with undefined alexaResponse', () => { - // setup - const TEST_OBJ = { - result: { - alexaExecutionInfo: {} - } - }; - // call - const res = responseParser.getCaption(TEST_OBJ); - // verify - expect(res).to.eql([]); - }); - - it('| Test with undefined caption array', () => { - // setup - const TEST_OBJ = { - result: { - alexaExecutionInfo: { - alexaResponses: [] - } - } - }; - // call - const res = responseParser.getCaption(TEST_OBJ); - // verify - expect(res).to.eql([]); - }); - - it('| Test with defined captions array', () => { - // setup - const TEST_OBJ = { - result: { - alexaExecutionInfo: { - alexaResponses: [ - { - content: { - caption: TEST_MSG - } - } - ] - } - } - }; - // call - const res = responseParser.getCaption(TEST_OBJ); - // verify - expect(res).to.be.instanceOf(Array); - expect(res.length).equal(1); - expect(res[0]).equal(TEST_MSG); - }); - }); - - describe('# helper function - getStatus', () => { - it('| Test with undefined status', () => { - // setup - const TEST_OBJ = {}; - // call - const res = responseParser.getStatus(TEST_OBJ); - // verify - expect(res).equal(undefined); - }); - - it('| Test with defined status', () => { - // setup - const TEST_MSG = 'TEST_MSG'; - const TEST_OBJ = { - status: TEST_MSG - }; - // call - const res = responseParser.getStatus(TEST_OBJ); - // verify - expect(res).equal(TEST_MSG); - }); - }); - - describe('# helper function - getSimulationId', () => { - it('| Test with undefined id', () => { - // setup - const TEST_OBJ = {}; - // call - const res = responseParser.getSimulationId(TEST_OBJ); - // verify - expect(res).equal(undefined); - }); - - it('| Test with defined id', () => { - // setup - const TEST_MSG = 'TEST_MSG'; - const TEST_OBJ = { - id: TEST_MSG - }; - // call - const res = responseParser.getSimulationId(TEST_OBJ); - // verify - expect(res).equal(TEST_MSG); - }); - }); -}); diff --git a/test/unit/controller/hosted-skill-controller/clone-flow-test.js b/test/unit/controller/hosted-skill-controller/clone-flow-test.js index 81cb4186..c999ca19 100644 --- a/test/unit/controller/hosted-skill-controller/clone-flow-test.js +++ b/test/unit/controller/hosted-skill-controller/clone-flow-test.js @@ -1,211 +1,224 @@ -const { expect } = require('chai'); -const fs = require('fs-extra'); -const jsonfile = require('jsonfile'); -const path = require('path'); -const sinon = require('sinon'); - -const GitClient = require('@src/clients/git-client'); -const Messenger = require('@src/view/messenger'); -const AuthorizationController = require('@src/controllers/authorization-controller'); -const ResourcesConfig = require('@src/model/resources-config'); - -const cloneFlow = require('@src/controllers/hosted-skill-controller/clone-flow'); -const CONSTANTS = require('@src/utils/constants'); - -describe('Controller test - CloneFlow test', () => { - let TEST_DO_DEBUG = false; - const FIXTURE_RESOURCES_CONFIG_FILE_PATH = path.join(process.cwd(), 'test', 'unit', 'fixture', 'model', 'hosted-proj', 'ask-resources.json'); - const TEST_PROFILE = 'default'; - const TEST_PROJECT_PATH = 'TEST_PROJECT_PATH'; - const TEST_SKILL_ID = 'amzn1.ask.skill.5555555-4444-3333-2222-1111111111'; - const TEST_SKILL_NAME = 'TEST_SKILL_NAME'; - const TEST_DEPLOYER_TYPE = '@ask-cli/hosted-skill-deployer'; - const TEST_REPO_URL = 'https://git-codecommit.us-east-1.amazonaws.com/v1/repos/5555555-4444-3333-2222-1111111111'; - const TEST_METADATA = { - repository: { - type: 'GIT', - url: TEST_REPO_URL - }, - }; - - describe('# test CloneFlow method - generateProject', () => { - let infoStub; - beforeEach(() => { - infoStub = sinon.stub(); - sinon.stub(Messenger, 'getInstance').returns({ - info: infoStub, - }); - }); - - afterEach(() => { - sinon.restore(); - }); - - it('| generate Project and ask-resources.json, expect correctly generated', () => { - // setup - sinon.stub(fs, 'mkdirSync'); - sinon.stub(jsonfile, 'writeFileSync'); - sinon.stub(path, 'join').withArgs(TEST_PROJECT_PATH, CONSTANTS.FILE_PATH.ASK_RESOURCES_JSON_CONFIG).returns(FIXTURE_RESOURCES_CONFIG_FILE_PATH); - path.join.callThrough(); - // call - cloneFlow.generateProject(TEST_PROJECT_PATH, TEST_SKILL_ID, TEST_SKILL_NAME, TEST_METADATA, TEST_PROFILE); - // verify - expect(ResourcesConfig.getInstance().getSkillId(TEST_PROFILE)).equal(TEST_SKILL_ID); - expect(ResourcesConfig.getInstance().getSkillInfraType(TEST_PROFILE)).equal(TEST_DEPLOYER_TYPE); - expect(Messenger.getInstance().info.args[0][0]).equal(`\nProject directory for ${TEST_SKILL_NAME} created at\n\t${TEST_PROJECT_PATH}`); - }); +const {expect} = require("chai"); +const fs = require("fs-extra"); +const jsonfile = require("jsonfile"); +const path = require("path"); +const sinon = require("sinon"); + +const GitClient = require("../../../../lib/clients/git-client"); +const Messenger = require("../../../../lib/view/messenger"); +const AuthorizationController = require("../../../../lib/controllers/authorization-controller"); +const ResourcesConfig = require("../../../../lib/model/resources-config"); + +const cloneFlow = require("../../../../lib/controllers/hosted-skill-controller/clone-flow"); +const CONSTANTS = require("../../../../lib/utils/constants"); + +describe("Controller test - CloneFlow test", () => { + let TEST_DO_DEBUG = false; + const FIXTURE_RESOURCES_CONFIG_FILE_PATH = path.join( + process.cwd(), + "test", + "unit", + "fixture", + "model", + "hosted-proj", + "ask-resources.json", + ); + const TEST_PROFILE = "default"; + const TEST_PROJECT_PATH = "TEST_PROJECT_PATH"; + const TEST_SKILL_ID = "amzn1.ask.skill.5555555-4444-3333-2222-1111111111"; + const TEST_SKILL_NAME = "TEST_SKILL_NAME"; + const TEST_DEPLOYER_TYPE = "@ask-cli/hosted-skill-deployer"; + const TEST_REPO_URL = "https://git-codecommit.us-east-1.amazonaws.com/v1/repos/5555555-4444-3333-2222-1111111111"; + const TEST_METADATA = { + repository: { + type: "GIT", + url: TEST_REPO_URL, + }, + }; + + describe("# test CloneFlow method - generateProject", () => { + let infoStub; + beforeEach(() => { + infoStub = sinon.stub(); + sinon.stub(Messenger, "getInstance").returns({ + info: infoStub, + }); }); - describe('# test CloneFlow method - cloneProjectFromGit', () => { - let infoStub; - beforeEach(() => { - infoStub = sinon.stub(); - sinon.stub(Messenger, 'getInstance').returns({ - info: infoStub, - }); - new ResourcesConfig(FIXTURE_RESOURCES_CONFIG_FILE_PATH); - }); - - afterEach(() => { - sinon.restore(); - ResourcesConfig.dispose(); - }); - - it('| clone project from Git without debug mode, expect correct workflow', () => { - // setup - sinon.stub(GitClient.prototype, 'init'); - sinon.stub(GitClient.prototype, 'configureCredentialHelper'); - sinon.stub(GitClient.prototype, 'addOrigin'); - sinon.stub(GitClient.prototype, 'fetchAll'); - sinon.stub(GitClient.prototype, 'checkoutBranch'); - sinon.stub(GitClient.prototype, 'setupGitIgnore'); - sinon.stub(GitClient.prototype, 'add'); - // call - cloneFlow.cloneProjectFromGit(TEST_PROJECT_PATH, TEST_SKILL_ID, TEST_SKILL_NAME, TEST_PROFILE, TEST_DO_DEBUG); - // verify - expect(Messenger.getInstance().info.args[0][0]).equal(`\nLambda code for ${TEST_SKILL_NAME} created at\n\t./lambda`); - }); - - it('| clone project from Git with debug mode, expect correct workflow', () => { - // setup - TEST_DO_DEBUG = true; - sinon.stub(GitClient.prototype, 'init'); - sinon.stub(GitClient.prototype, 'configureCredentialHelper'); - sinon.stub(GitClient.prototype, 'addOrigin'); - sinon.stub(GitClient.prototype, 'fetchAll'); - sinon.stub(GitClient.prototype, 'checkoutBranch'); - sinon.stub(GitClient.prototype, 'setupGitIgnore'); - sinon.stub(GitClient.prototype, 'add'); - // call - cloneFlow.cloneProjectFromGit(TEST_PROJECT_PATH, TEST_SKILL_ID, TEST_SKILL_NAME, TEST_PROFILE, TEST_REPO_URL, TEST_DO_DEBUG); - // verify - expect(Messenger.getInstance().info.args[0][0]).equal('- Setting up git repo...'); - expect(Messenger.getInstance().info.args[1][0]).equal('- Fetching git repo...'); - expect(Messenger.getInstance().info.args[2][0]).equal('- Checking out master branch...'); - expect(Messenger.getInstance().info.args[3][0]).equal('- Setting up .gitignore...'); - expect(Messenger.getInstance().info.args[4][0]).equal('- Git repo successfully setup'); - expect(Messenger.getInstance().info.args[5][0]).equal(`\nLambda code for ${TEST_SKILL_NAME} created at\n\t./lambda`); - }); + afterEach(() => { + sinon.restore(); }); - describe('# test CloneFlow method - doSkillPackageExist', () => { - let infoStub; - - beforeEach(() => { - infoStub = sinon.stub(); - sinon.stub(Messenger, 'getInstance').returns({ - info: infoStub, - }); - new ResourcesConfig(FIXTURE_RESOURCES_CONFIG_FILE_PATH); - sinon.stub(AuthorizationController.prototype, 'tokenRefreshAndRead').callsArgWith(1); - }); - - afterEach(() => { - sinon.restore(); - ResourcesConfig.dispose(); - }); - - it('| Skill-Package exists, expect return directly', (done) => { - // setup - sinon.stub(fs, 'existsSync').returns(true); - // call - cloneFlow.doSkillPackageExist(TEST_SKILL_NAME, TEST_PROJECT_PATH, TEST_SKILL_ID, (err, res) => { - // verify - expect(err).equal(null); - expect(res).equal(true); - done(); - }); - }); - - it('| Skill-Package NOT exists but models and skill-json exist, expect skill-package generated', (done) => { - // setup - sinon.stub(fs, 'existsSync'); - fs.existsSync.withArgs(TEST_PROJECT_PATH).returns(false); - sinon.stub(fs, 'mkdirSync'); - fs.existsSync.withArgs(path.join(TEST_PROJECT_PATH, 'models')).returns(true); - fs.existsSync.withArgs(path.join(TEST_PROJECT_PATH, 'skill.json')).returns(true); - fs.existsSync.withArgs(path.join(TEST_PROJECT_PATH, 'isps')).returns(true); - sinon.stub(fs, 'moveSync'); - // call - cloneFlow.doSkillPackageExist(TEST_SKILL_NAME, TEST_PROJECT_PATH, TEST_SKILL_ID, (err, res) => { - // verify - expect(err).equal(null); - expect(res).equal(true); - done(); - }); - }); - - it('| models NOT exists but Skill-Package and skill-json exist, expect skill-package generated', (done) => { - // setup - sinon.stub(fs, 'existsSync'); - fs.existsSync.withArgs(TEST_PROJECT_PATH).returns(false); - sinon.stub(fs, 'mkdirSync'); - fs.existsSync.withArgs(path.join(TEST_PROJECT_PATH, 'models')).returns(false); - fs.existsSync.withArgs(path.join(TEST_PROJECT_PATH, 'skill.json')).returns(true); - fs.existsSync.withArgs(path.join(TEST_PROJECT_PATH, 'isps')).returns(true); - sinon.stub(fs, 'moveSync'); - // call - cloneFlow.doSkillPackageExist(TEST_SKILL_NAME, TEST_PROJECT_PATH, TEST_SKILL_ID, (err, res) => { - // verify - expect(err).equal(null); - expect(res).equal(true); - done(); - }); - }); - - it('| Skill-Package NOT exists but models and skill-json exist, expect skill-package generated', (done) => { - // setup - sinon.stub(fs, 'existsSync'); - fs.existsSync.withArgs(TEST_PROJECT_PATH).returns(false); - sinon.stub(fs, 'mkdirSync'); - fs.existsSync.withArgs(path.join(TEST_PROJECT_PATH, 'models')).returns(true); - fs.existsSync.withArgs(path.join(TEST_PROJECT_PATH, 'skill.json')).returns(false); - fs.existsSync.withArgs(path.join(TEST_PROJECT_PATH, 'isps')).returns(false); - sinon.stub(fs, 'moveSync'); - // call - cloneFlow.doSkillPackageExist(TEST_SKILL_NAME, TEST_PROJECT_PATH, TEST_SKILL_ID, (err, res) => { - // verify - expect(err).equal(null); - expect(res).equal(true); - done(); - }); - }); - - it('| models and skill-json NOT exist, expect return false', (done) => { - // setup - sinon.stub(fs, 'existsSync'); - fs.existsSync.withArgs(TEST_PROJECT_PATH).returns(false); - sinon.stub(fs, 'mkdirSync'); - fs.existsSync.withArgs(path.join(TEST_PROJECT_PATH, 'models')).returns(false); - fs.existsSync.withArgs(path.join(TEST_PROJECT_PATH, 'skill.json')).returns(false); - fs.existsSync.withArgs(path.join(TEST_PROJECT_PATH, 'isps')).returns(false); - // call - cloneFlow.doSkillPackageExist(TEST_SKILL_NAME, TEST_PROJECT_PATH, TEST_SKILL_ID, (err, res) => { - // verify - expect(err).equal(null); - expect(res).equal(false); - done(); - }); - }); + it("| generate Project and ask-resources.json, expect correctly generated", () => { + // setup + sinon.stub(fs, "mkdirSync"); + sinon.stub(jsonfile, "writeFileSync"); + sinon + .stub(path, "join") + .withArgs(TEST_PROJECT_PATH, CONSTANTS.FILE_PATH.ASK_RESOURCES_JSON_CONFIG) + .returns(FIXTURE_RESOURCES_CONFIG_FILE_PATH); + path.join.callThrough(); + // call + cloneFlow.generateProject(TEST_PROJECT_PATH, TEST_SKILL_ID, TEST_SKILL_NAME, TEST_METADATA, TEST_PROFILE); + // verify + expect(ResourcesConfig.getInstance().getSkillId(TEST_PROFILE)).equal(TEST_SKILL_ID); + expect(ResourcesConfig.getInstance().getSkillInfraType(TEST_PROFILE)).equal(TEST_DEPLOYER_TYPE); + expect(Messenger.getInstance().info.args[0][0]).equal( + `\nProject directory for ${TEST_SKILL_NAME} created at\n\t${TEST_PROJECT_PATH}`, + ); }); + }); + + describe("# test CloneFlow method - cloneProjectFromGit", () => { + let infoStub; + beforeEach(() => { + infoStub = sinon.stub(); + sinon.stub(Messenger, "getInstance").returns({ + info: infoStub, + }); + new ResourcesConfig(FIXTURE_RESOURCES_CONFIG_FILE_PATH); + }); + + afterEach(() => { + sinon.restore(); + ResourcesConfig.dispose(); + }); + + it("| clone project from Git without debug mode, expect correct workflow", () => { + // setup + sinon.stub(GitClient.prototype, "init"); + sinon.stub(GitClient.prototype, "configureCredentialHelper"); + sinon.stub(GitClient.prototype, "addOrigin"); + sinon.stub(GitClient.prototype, "fetchAll"); + sinon.stub(GitClient.prototype, "checkoutBranch"); + sinon.stub(GitClient.prototype, "setupGitIgnore"); + sinon.stub(GitClient.prototype, "add"); + // call + cloneFlow.cloneProjectFromGit(TEST_PROJECT_PATH, TEST_SKILL_ID, TEST_SKILL_NAME, TEST_PROFILE, TEST_DO_DEBUG); + // verify + expect(Messenger.getInstance().info.args[0][0]).equal(`\nLambda code for ${TEST_SKILL_NAME} created at\n\t./lambda`); + }); + + it("| clone project from Git with debug mode, expect correct workflow", () => { + // setup + TEST_DO_DEBUG = true; + sinon.stub(GitClient.prototype, "init"); + sinon.stub(GitClient.prototype, "configureCredentialHelper"); + sinon.stub(GitClient.prototype, "addOrigin"); + sinon.stub(GitClient.prototype, "fetchAll"); + sinon.stub(GitClient.prototype, "checkoutBranch"); + sinon.stub(GitClient.prototype, "setupGitIgnore"); + sinon.stub(GitClient.prototype, "add"); + // call + cloneFlow.cloneProjectFromGit(TEST_PROJECT_PATH, TEST_SKILL_ID, TEST_SKILL_NAME, TEST_PROFILE, TEST_REPO_URL, TEST_DO_DEBUG); + // verify + expect(Messenger.getInstance().info.args[0][0]).equal("- Setting up git repo..."); + expect(Messenger.getInstance().info.args[1][0]).equal("- Fetching git repo..."); + expect(Messenger.getInstance().info.args[2][0]).equal("- Checking out master branch..."); + expect(Messenger.getInstance().info.args[3][0]).equal("- Setting up .gitignore..."); + expect(Messenger.getInstance().info.args[4][0]).equal("- Git repo successfully setup"); + expect(Messenger.getInstance().info.args[5][0]).equal(`\nLambda code for ${TEST_SKILL_NAME} created at\n\t./lambda`); + }); + }); + + describe("# test CloneFlow method - doSkillPackageExist", () => { + let infoStub; + + beforeEach(() => { + infoStub = sinon.stub(); + sinon.stub(Messenger, "getInstance").returns({ + info: infoStub, + }); + new ResourcesConfig(FIXTURE_RESOURCES_CONFIG_FILE_PATH); + sinon.stub(AuthorizationController.prototype, "tokenRefreshAndRead").callsArgWith(1); + }); + + afterEach(() => { + sinon.restore(); + ResourcesConfig.dispose(); + }); + + it("| Skill-Package exists, expect return directly", (done) => { + // setup + sinon.stub(fs, "existsSync").returns(true); + // call + cloneFlow.doSkillPackageExist(TEST_SKILL_NAME, TEST_PROJECT_PATH, TEST_SKILL_ID, (err, res) => { + // verify + expect(err).equal(null); + expect(res).equal(true); + done(); + }); + }); + + it("| Skill-Package NOT exists but models and skill-json exist, expect skill-package generated", (done) => { + // setup + sinon.stub(fs, "existsSync"); + fs.existsSync.withArgs(TEST_PROJECT_PATH).returns(false); + sinon.stub(fs, "mkdirSync"); + fs.existsSync.withArgs(path.join(TEST_PROJECT_PATH, "models")).returns(true); + fs.existsSync.withArgs(path.join(TEST_PROJECT_PATH, "skill.json")).returns(true); + fs.existsSync.withArgs(path.join(TEST_PROJECT_PATH, "isps")).returns(true); + sinon.stub(fs, "moveSync"); + // call + cloneFlow.doSkillPackageExist(TEST_SKILL_NAME, TEST_PROJECT_PATH, TEST_SKILL_ID, (err, res) => { + // verify + expect(err).equal(null); + expect(res).equal(true); + done(); + }); + }); + + it("| models NOT exists but Skill-Package and skill-json exist, expect skill-package generated", (done) => { + // setup + sinon.stub(fs, "existsSync"); + fs.existsSync.withArgs(TEST_PROJECT_PATH).returns(false); + sinon.stub(fs, "mkdirSync"); + fs.existsSync.withArgs(path.join(TEST_PROJECT_PATH, "models")).returns(false); + fs.existsSync.withArgs(path.join(TEST_PROJECT_PATH, "skill.json")).returns(true); + fs.existsSync.withArgs(path.join(TEST_PROJECT_PATH, "isps")).returns(true); + sinon.stub(fs, "moveSync"); + // call + cloneFlow.doSkillPackageExist(TEST_SKILL_NAME, TEST_PROJECT_PATH, TEST_SKILL_ID, (err, res) => { + // verify + expect(err).equal(null); + expect(res).equal(true); + done(); + }); + }); + + it("| Skill-Package NOT exists but models and skill-json exist, expect skill-package generated", (done) => { + // setup + sinon.stub(fs, "existsSync"); + fs.existsSync.withArgs(TEST_PROJECT_PATH).returns(false); + sinon.stub(fs, "mkdirSync"); + fs.existsSync.withArgs(path.join(TEST_PROJECT_PATH, "models")).returns(true); + fs.existsSync.withArgs(path.join(TEST_PROJECT_PATH, "skill.json")).returns(false); + fs.existsSync.withArgs(path.join(TEST_PROJECT_PATH, "isps")).returns(false); + sinon.stub(fs, "moveSync"); + // call + cloneFlow.doSkillPackageExist(TEST_SKILL_NAME, TEST_PROJECT_PATH, TEST_SKILL_ID, (err, res) => { + // verify + expect(err).equal(null); + expect(res).equal(true); + done(); + }); + }); + + it("| models and skill-json NOT exist, expect return false", (done) => { + // setup + sinon.stub(fs, "existsSync"); + fs.existsSync.withArgs(TEST_PROJECT_PATH).returns(false); + sinon.stub(fs, "mkdirSync"); + fs.existsSync.withArgs(path.join(TEST_PROJECT_PATH, "models")).returns(false); + fs.existsSync.withArgs(path.join(TEST_PROJECT_PATH, "skill.json")).returns(false); + fs.existsSync.withArgs(path.join(TEST_PROJECT_PATH, "isps")).returns(false); + // call + cloneFlow.doSkillPackageExist(TEST_SKILL_NAME, TEST_PROJECT_PATH, TEST_SKILL_ID, (err, res) => { + // verify + expect(err).equal(null); + expect(res).equal(false); + done(); + }); + }); + }); }); diff --git a/test/unit/controller/hosted-skill-controller/helper-test.js b/test/unit/controller/hosted-skill-controller/helper-test.js index c82e11a9..99cda776 100644 --- a/test/unit/controller/hosted-skill-controller/helper-test.js +++ b/test/unit/controller/hosted-skill-controller/helper-test.js @@ -1,139 +1,136 @@ -const { expect } = require('chai'); -const fs = require('fs-extra'); -const https = require('https'); -const path = require('path'); -const sinon = require('sinon'); -const { PassThrough } = require('stream'); +const {expect} = require("chai"); +const fs = require("fs-extra"); +const https = require("https"); +const path = require("path"); +const sinon = require("sinon"); +const {PassThrough} = require("stream"); -const helper = require('@src/controllers/hosted-skill-controller/helper'); +const helper = require("../../../../lib/controllers/hosted-skill-controller/helper"); -describe('Controller test - hosted skill controller - helper test', () => { - const TEST_ERROR = 'error'; +describe("Controller test - hosted skill controller - helper test", () => { + const TEST_ERROR = "error"; - - describe('# test helper method: downloadAuthInfoScript', () => { - - afterEach(() => { - sinon.restore(); - }); - - it('| helper download Script fails, expect error thrown ', (done) => { - // setup - sinon.stub(helper, 'downloadScriptFromS3').callsArgWith(2, TEST_ERROR); - // call - helper.downloadAuthInfoScript((err) => { - expect(err).equal(TEST_ERROR); - done(); - }); - }); - - it('| helper download Script succeeds, expect none error response', (done) => { - // setup - sinon.stub(helper, 'downloadScriptFromS3').callsArgWith(2, null); - // call - helper.downloadAuthInfoScript((err) => { - expect(err).equal(null); - done(); - }); - }); + describe("# test helper method: downloadAuthInfoScript", () => { + afterEach(() => { + sinon.restore(); }); - describe('# test helper method: downloadAskPrePushScript', () => { - - afterEach(() => { - sinon.restore(); - }); - - it('| helper download Script fails, expect error thrown ', (done) => { - // setup - sinon.stub(fs, 'ensureDirSync'); - sinon.stub(helper, 'downloadScriptFromS3').callsArgWith(2, TEST_ERROR); - // call - helper.downloadAskPrePushScript((err) => { - expect(err).equal(TEST_ERROR); - done(); - }); - }); + it("| helper download Script fails, expect error thrown ", (done) => { + // setup + sinon.stub(helper, "downloadScriptFromS3").callsArgWith(2, TEST_ERROR); + // call + helper.downloadAuthInfoScript((err) => { + expect(err).equal(TEST_ERROR); + done(); + }); + }); - it('| helper download Script succeeds, expect none error response', (done) => { - // setup - sinon.stub(fs, 'ensureDirSync'); - sinon.stub(helper, 'downloadScriptFromS3').callsArgWith(2, null); - // call - helper.downloadAskPrePushScript((err) => { - expect(err).equal(null); - done(); - }); - }); + it("| helper download Script succeeds, expect none error response", (done) => { + // setup + sinon.stub(helper, "downloadScriptFromS3").callsArgWith(2, null); + // call + helper.downloadAuthInfoScript((err) => { + expect(err).equal(null); + done(); + }); }); + }); - describe('# test helper method: downloadGitCredentialHelperScript', () => { + describe("# test helper method: downloadAskPrePushScript", () => { + afterEach(() => { + sinon.restore(); + }); - afterEach(() => { - sinon.restore(); - }); + it("| helper download Script fails, expect error thrown ", (done) => { + // setup + sinon.stub(fs, "ensureDirSync"); + sinon.stub(helper, "downloadScriptFromS3").callsArgWith(2, TEST_ERROR); + // call + helper.downloadAskPrePushScript((err) => { + expect(err).equal(TEST_ERROR); + done(); + }); + }); - it('| helper download Script fails, expect error thrown ', (done) => { - // setup - sinon.stub(fs, 'ensureDirSync'); - sinon.stub(helper, 'downloadScriptFromS3').callsArgWith(2, TEST_ERROR); - // call - helper.downloadGitCredentialHelperScript((err) => { - expect(err).equal(TEST_ERROR); - done(); - }); - }); + it("| helper download Script succeeds, expect none error response", (done) => { + // setup + sinon.stub(fs, "ensureDirSync"); + sinon.stub(helper, "downloadScriptFromS3").callsArgWith(2, null); + // call + helper.downloadAskPrePushScript((err) => { + expect(err).equal(null); + done(); + }); + }); + }); - it('| helper download Script succeeds, expect none error response', (done) => { - // setup - sinon.stub(fs, 'ensureDirSync'); - sinon.stub(helper, 'downloadScriptFromS3').callsArgWith(2, null); - // call - helper.downloadGitCredentialHelperScript((err) => { - expect(err).equal(null); - done(); - }); - }); + describe("# test helper method: downloadGitCredentialHelperScript", () => { + afterEach(() => { + sinon.restore(); }); - describe('# test helper method: downloadScriptFromS3', () => { - const TEST_SCRIPT_URL = 'script_url'; - const TEST_FILE_PATH = 'filepath' - let httpsSub; - let writeStreamOnStub; - let responseStub; + it("| helper download Script fails, expect error thrown ", (done) => { + // setup + sinon.stub(fs, "ensureDirSync"); + sinon.stub(helper, "downloadScriptFromS3").callsArgWith(2, TEST_ERROR); + // call + helper.downloadGitCredentialHelperScript((err) => { + expect(err).equal(TEST_ERROR); + done(); + }); + }); - beforeEach(() => { - responseStub = { - pipe: () => {} - } - writeStreamOnStub = sinon.stub(); - sinon.stub(fs, 'createWriteStream').returns({ - on: writeStreamOnStub - }); - httpsSub = sinon.stub(https, 'get'); - }); + it("| helper download Script succeeds, expect none error response", (done) => { + // setup + sinon.stub(fs, "ensureDirSync"); + sinon.stub(helper, "downloadScriptFromS3").callsArgWith(2, null); + // call + helper.downloadGitCredentialHelperScript((err) => { + expect(err).equal(null); + done(); + }); + }); + }); + + describe("# test helper method: downloadScriptFromS3", () => { + const TEST_SCRIPT_URL = "script_url"; + const TEST_FILE_PATH = "filepath"; + let httpsSub; + let writeStreamOnStub; + let responseStub; + + beforeEach(() => { + responseStub = { + pipe: () => {}, + }; + writeStreamOnStub = sinon.stub(); + sinon.stub(fs, "createWriteStream").returns({ + on: writeStreamOnStub, + }); + httpsSub = sinon.stub(https, "get"); + }); - afterEach(() => { - sinon.restore(); - }); + afterEach(() => { + sinon.restore(); + }); - it('| download Script succeeds, expect none error response', (done) => { - // setup - httpsSub.callsFake((TEST_SCRIPT_URL, callback) => { - return callback(responseStub); - }) - // sinon.spy(TEST_STREAM, 'pipe'); - writeStreamOnStub.callsArgWith(1); - sinon.stub(fs, 'chmodSync'); - // call - helper.downloadScriptFromS3(TEST_SCRIPT_URL, TEST_FILE_PATH, (err) => { - // verify - expect(fs.createWriteStream.args[0][0]).equal(TEST_FILE_PATH); - expect(httpsSub.args[0][0]).equal(TEST_SCRIPT_URL) - expect(err).equal(null); - done(); - }); - }); + it("| download Script succeeds, expect none error response", (done) => { + // setup + httpsSub.callsFake((TEST_SCRIPT_URL, callback) => { + callback(responseStub); + return {on: sinon.stub()}; + }); + // sinon.spy(TEST_STREAM, 'pipe'); + writeStreamOnStub.callsArgWith(1); + sinon.stub(fs, "chmodSync"); + // call + helper.downloadScriptFromS3(TEST_SCRIPT_URL, TEST_FILE_PATH, (err) => { + // verify + expect(fs.createWriteStream.args[0][0]).equal(TEST_FILE_PATH); + expect(httpsSub.args[0][0]).equal(TEST_SCRIPT_URL); + expect(err).equal(null); + done(); + }); }); + }); }); diff --git a/test/unit/controller/hosted-skill-controller/index-test.js b/test/unit/controller/hosted-skill-controller/index-test.js index d524004e..9e431f3c 100644 --- a/test/unit/controller/hosted-skill-controller/index-test.js +++ b/test/unit/controller/hosted-skill-controller/index-test.js @@ -1,620 +1,619 @@ -const { expect } = require('chai'); -const fs = require('fs-extra'); -const sinon = require('sinon'); - -const httpClient = require('@src/clients/http-client'); -const AuthorizationController = require('@src/controllers/authorization-controller'); -const CloneFlow = require('@src/controllers/hosted-skill-controller/clone-flow'); -const helper = require('@src/controllers/hosted-skill-controller/helper'); -const HostedSkillController = require('@src/controllers/hosted-skill-controller'); -const SkillMetadataController = require('@src/controllers/skill-metadata-controller'); -const CONSTANTS = require('@src/utils/constants'); -const Messenger = require('@src/view/messenger'); -const jsonView = require('@src/view/json-view'); - -describe('Controller test - hosted skill controller test', () => { - const TEST_PROFILE = 'default'; // test file uses 'default' profile - const TEST_DO_DEBUG = false; - const TEST_SKILL_ID = 'SKILL_ID'; - const TEST_SKILL_NAME = 'SKILL_NAME'; - const TEST_MANIFEST = {}; - const TEST_VENDOR_ID = 'TEST_VENDOR_ID'; - const TEST_PERMISSION_TYPE = 'TEST_PERMISSION_TYPE'; - const TEST_PROJECT_PATH = 'PROJECT_PATH'; - const TEST_LOCALE = 'en-US'; - const TEST_CONFIGURATION = { - profile: TEST_PROFILE, - doDebug: TEST_DO_DEBUG - }; - describe('# inspect correctness for constructor', () => { - it('| initiate as a HostedSkillController class', () => { - const hostedSkillController = new HostedSkillController(TEST_CONFIGURATION); - expect(hostedSkillController).to.be.instanceOf(HostedSkillController); - expect(hostedSkillController.profile).equal(TEST_PROFILE); - expect(hostedSkillController.doDebug).equal(TEST_DO_DEBUG); - }); - }); - - describe('# test class method: createSkill', () => { - let hostedSkillController; - beforeEach(() => { - hostedSkillController = new HostedSkillController(TEST_CONFIGURATION); - sinon.stub(AuthorizationController.prototype, 'tokenRefreshAndRead').callsArgWith(1); - }); - - afterEach(() => { - sinon.restore(); - }); - - it('| create hosted skill fails, expect error thrown', (done) => { - // setup - const TEST_ERROR = 'TEST_ERROR'; - sinon.stub(httpClient, 'request').callsArgWith(3, TEST_ERROR); // stub createHostedSkill request - // call - hostedSkillController.createSkill(TEST_MANIFEST, (err, res) => { - expect(err).equal(TEST_ERROR); - expect(res).equal(undefined); - done(); - }); - }); - - it('| create hosted skill response status >= 300, expect error thrown', (done) => { - // setup - const TEST_ERROR = 'TEST_ERROR'; - const TEST_STATUS_ERROR = { - statusCode: 403, - body: { - error: TEST_ERROR - } - }; - sinon.stub(httpClient, 'request').callsArgWith(3, null, TEST_STATUS_ERROR); // stub createHostedSkill request - // call - hostedSkillController.createSkill(TEST_MANIFEST, (err, res) => { - expect(err).equal(jsonView.toString({ error: TEST_ERROR })); - expect(res).equal(undefined); - done(); - }); - }); - - it('| polling skill status fails, expect error thrown', (done) => { - // setup - const TEST_CREATE_SKILL_RESPONSE = { - statusCode: 200, - headers: {}, - body: {} - }; - const TEST_POLLING_ERROR = 'TEST_POLLING_ERROR'; - sinon.stub(httpClient, 'request').callsArgWith(3, null, TEST_CREATE_SKILL_RESPONSE); // stub createHostedSkill request - sinon.stub(helper, 'pollingSkillStatus').callsArgWith(2, TEST_POLLING_ERROR); - // call - hostedSkillController.createSkill(TEST_MANIFEST, (err, res) => { - expect(err).equal(TEST_POLLING_ERROR); - expect(res).equal(undefined); - done(); - }); - }); - - it('| polling skill status succeed, expect skillId return', (done) => { - // setup - const TEST_CREATE_SKILL_RESPONSE = { - statusCode: 200, - headers: {}, - body: { - skillId: TEST_SKILL_ID - } - }; - sinon.stub(httpClient, 'request').callsArgWith(3, null, TEST_CREATE_SKILL_RESPONSE); // stub createHostedSkill request - sinon.stub(helper, 'pollingSkillStatus').callsArgWith(2, null); - sinon.stub(helper, 'handleSkillStatus').callsArgWith(2, null); - // call - hostedSkillController.createSkill(TEST_MANIFEST, (err, res) => { - expect(err).equal(null); - expect(res).equal(TEST_SKILL_ID); - done(); - }); - }); - }); - - describe('# test class method: clone', () => { - let hostedSkillController; - let infoStub; - beforeEach(() => { - hostedSkillController = new HostedSkillController(TEST_CONFIGURATION); - sinon.stub(AuthorizationController.prototype, 'tokenRefreshAndRead').callsArgWith(1); - infoStub = sinon.stub(); - sinon.stub(Messenger, 'getInstance').returns({ - info: infoStub, - }); - }); - - afterEach(() => { - sinon.restore(); - }); - - it('| project directory already exists, expect error thrown ', (done) => { - // setup - sinon.stub(fs, 'existsSync').withArgs(TEST_PROJECT_PATH).returns(true); - // call - hostedSkillController.clone(TEST_SKILL_ID, TEST_SKILL_NAME, TEST_PROJECT_PATH, (err, res) => { - expect(err).equal(`${TEST_PROJECT_PATH} directory already exists.`); - expect(res).equal(undefined); - done(); - }); - }); - - it('| get Hosted skill Metadata fails, expect error thrown ', (done) => { - // setup - const TEST_METADATA_ERROR = 'TEST_METADATA_ERROR'; - const TEST_ERROR = new Error(TEST_METADATA_ERROR); - sinon.stub(fs, 'existsSync').withArgs(TEST_PROJECT_PATH).returns(false); - sinon.stub(httpClient, 'request').callsArgWith(3, TEST_ERROR); // stub getAlexaHostedSkillMetadata smapi request - // call - hostedSkillController.clone(TEST_SKILL_ID, TEST_SKILL_NAME, TEST_PROJECT_PATH, (err, res) => { - expect(err.message).equal(TEST_METADATA_ERROR); - expect(res).equal(undefined); - done(); - }); - }); - - it('| get Hosted skill Metadata response status >= 300, expect error thrown ', (done) => { - // setup - const TEST_METADATA_ERROR = 'TEST_METADATA_ERROR'; - const TEST_STATUS_ERROR = { - statusCode: 403, - body: { - error: TEST_METADATA_ERROR - } - }; - sinon.stub(fs, 'existsSync').withArgs(TEST_PROJECT_PATH).returns(false); - sinon.stub(httpClient, 'request').callsArgWith(3, null, TEST_STATUS_ERROR); // stub getAlexaHostedSkillMetadata smapi request - // call - hostedSkillController.clone(TEST_SKILL_ID, TEST_SKILL_NAME, TEST_PROJECT_PATH, (err, res) => { - expect(err).equal(jsonView.toString({ error: TEST_METADATA_ERROR })); - expect(res).equal(undefined); - done(); - }); - }); - - it('| do skill package exist fails, expect error thrown ', (done) => { - // setup - const TEST_SKILL_PACKAGE_ERROR = 'TEST_SKILL_PACKAGE_ERROR'; - const TEST_STATUS_RESPONSE = { - statusCode: 200, - body: { - alexaHosted: { repository: { url: 'test' } } - } - }; - sinon.stub(fs, 'existsSync').withArgs(TEST_PROJECT_PATH).returns(false); - sinon.stub(httpClient, 'request').callsArgWith(3, null, TEST_STATUS_RESPONSE); // stub getAlexaHostedSkillMetadata smapi request - sinon.stub(CloneFlow, 'generateProject'); - sinon.stub(CloneFlow, 'cloneProjectFromGit'); - sinon.stub(CloneFlow, 'doSkillPackageExist').callsArgWith(3, TEST_SKILL_PACKAGE_ERROR); - // call - hostedSkillController.clone(TEST_SKILL_ID, TEST_SKILL_NAME, TEST_PROJECT_PATH, (err, res) => { - expect(err).equal(TEST_SKILL_PACKAGE_ERROR); - expect(res).equal(undefined); - done(); - }); - }); - - it('| skill package exists, expect skill-package generated ', (done) => { - // setup - sinon.stub(fs, 'existsSync').withArgs(TEST_PROJECT_PATH).returns(false); - sinon.stub(HostedSkillController.prototype, 'getHostedSkillMetadata').yields(null, { repository: { url: 'test' } }); - sinon.stub(CloneFlow, 'generateProject'); - sinon.stub(CloneFlow, 'cloneProjectFromGit'); - sinon.stub(CloneFlow, 'doSkillPackageExist').callsArgWith(3, null, true); - // call - hostedSkillController.clone(TEST_SKILL_ID, TEST_SKILL_NAME, TEST_PROJECT_PATH, (err) => { - expect(err).equal(undefined); - expect(Messenger.getInstance().info.args[0][0]).equal( - `\nSkill schema and interactionModels for ${TEST_SKILL_NAME} created at\n\t./skill-package\n` - ); - done(); - }); - }); - - it('| skill package do NOT exist, export skill-package fails, expect no error ', (done) => { - // setup - const TEST_EXPORT_ERROR = 'TEST_EXPORT_ERROR'; - sinon.stub(fs, 'existsSync').withArgs(TEST_PROJECT_PATH).returns(false); - sinon.stub(HostedSkillController.prototype, 'getHostedSkillMetadata').yields(null, { repository: { url: 'test' } }); - sinon.stub(CloneFlow, 'generateProject'); - sinon.stub(CloneFlow, 'cloneProjectFromGit'); - sinon.stub(CloneFlow, 'doSkillPackageExist').callsArgWith(3, null, false); - sinon.stub(SkillMetadataController.prototype, 'getSkillPackage').callsArgWith(3, TEST_EXPORT_ERROR); - // call - hostedSkillController.clone(TEST_SKILL_ID, TEST_SKILL_NAME, TEST_PROJECT_PATH, (err) => { - expect(err).equal(TEST_EXPORT_ERROR); - done(); - }); - }); - - it('| skill package do NOT exist, export skill-package succeed, expect skill-package generated ', (done) => { - // setup - sinon.stub(fs, 'existsSync').withArgs(TEST_PROJECT_PATH).returns(false); - sinon.stub(HostedSkillController.prototype, 'getHostedSkillMetadata').yields(null, { repository: { url: 'test' } }); - sinon.stub(CloneFlow, 'generateProject'); - sinon.stub(CloneFlow, 'cloneProjectFromGit'); - sinon.stub(CloneFlow, 'doSkillPackageExist').callsArgWith(3, null); - sinon.stub(SkillMetadataController.prototype, 'getSkillPackage').callsArgWith(3, null); - // call - hostedSkillController.clone(TEST_SKILL_ID, TEST_SKILL_NAME, TEST_PROJECT_PATH, (err) => { - expect(err).equal(undefined); - expect(Messenger.getInstance().info.args[0][0]).equal( - `\nSkill schema and interactionModels for ${TEST_SKILL_NAME} created at\n\t./skill-package\n` - ); - done(); - }); - }); - }); - - describe('# test class method: getHostedSkillPermission', () => { - let hostedSkillController; - beforeEach(() => { - hostedSkillController = new HostedSkillController(TEST_CONFIGURATION); - sinon.stub(AuthorizationController.prototype, 'tokenRefreshAndRead').callsArgWith(1); - }); - - afterEach(() => { - sinon.restore(); - }); - - it('| get hosted skill permission fails, expect error thrown', (done) => { - // setup - const TEST_ERROR = 'TEST_ERROR'; - sinon.stub(httpClient, 'request').callsArgWith(3, TEST_ERROR); // stub getHostedSkillPermission request - // call - hostedSkillController.getHostedSkillPermission(TEST_VENDOR_ID, TEST_PERMISSION_TYPE, (err, res) => { - expect(err).equal(TEST_ERROR); - expect(res).equal(undefined); - done(); - }); - }); - - it('| get hosted skill permission response status >= 300, expect error thrown', (done) => { - // setup - const TEST_ERROR = 'TEST_ERROR'; - const TEST_STATUS_ERROR = { - statusCode: 403, - body: { - error: TEST_ERROR - } - }; - sinon.stub(httpClient, 'request').callsArgWith(3, null, TEST_STATUS_ERROR); // stub getHostedSkillPermission request - // call - hostedSkillController.getHostedSkillPermission(TEST_VENDOR_ID, TEST_PERMISSION_TYPE, (err, res) => { - expect(err).equal(jsonView.toString({ error: TEST_ERROR })); - expect(res).equal(undefined); - done(); - }); - }); - - it('| get hosted skill permission succeed, expect error thrown', (done) => { - // setup - const TEST_PERMISSION_RESPONSE = { - statusCode: 200, - headers: {}, - body: {} - }; - sinon.stub(httpClient, 'request').callsArgWith(3, null, TEST_PERMISSION_RESPONSE); // stub getHostedSkillPermission request - // call - hostedSkillController.getHostedSkillPermission(TEST_VENDOR_ID, TEST_PERMISSION_TYPE, (err) => { - expect(err).equal(null); - done(); - }); - }); - }); - - describe('# test class method: checkSkillStatus', () => { - let hostedSkillController; - let infoStub; - beforeEach(() => { - infoStub = sinon.stub(); - sinon.stub(Messenger, 'getInstance').returns({ - info: infoStub, - }); - hostedSkillController = new HostedSkillController(TEST_CONFIGURATION); - sinon.stub(AuthorizationController.prototype, 'tokenRefreshAndRead').callsArgWith(1); - }); - - afterEach(() => { - sinon.restore(); - }); - - it('| polling to get skill status fails, expect error thrown ', (done) => { - // setup - const TEST_STATUS_ERROR = 'TEST_STATUS_ERROR'; - const TEST_ERROR = new Error(TEST_STATUS_ERROR); - sinon.stub(httpClient, 'request').callsArgWith(3, TEST_ERROR); // stub getSkillStatus smapi request - // call - hostedSkillController.checkSkillStatus(TEST_SKILL_ID, (err, res) => { - expect(err.message).equal(TEST_STATUS_ERROR); - expect(res).equal(undefined); - done(); - }); - }); - - it('| polling to get skill status response >= 300, expect error thrown ', (done) => { - // setup - const TEST_STATUS_ERROR = 'TEST_STATUS_ERROR'; - const TEST_ERROR = { - statusCode: 403, - body: { - error: TEST_STATUS_ERROR - } - }; - sinon.stub(httpClient, 'request').callsArgWith(3, null, TEST_ERROR); // stub getSkillStatus smapi request - // call - hostedSkillController.checkSkillStatus(TEST_SKILL_ID, (err, res) => { - expect(err).equal(jsonView.toString({ error: TEST_STATUS_ERROR })); - expect(res).equal(undefined); - done(); - }); - }); - - it('| polling to get skill status until all resources are SUCCEEDED, expect correct response', (done) => { - // setup - const TEST_STATUS_RESPONSE_0 = { - statusCode: 200, - headers: {}, - body: { - [CONSTANTS.HOSTED_SKILL.RESOURCES.MANIFEST]: { - lastUpdateRequest: { - status: 'SUCCEEDED' - } - } - } - }; - const TEST_STATUS_RESPONSE_1 = { - statusCode: 200, - headers: {}, - body: { - [CONSTANTS.HOSTED_SKILL.RESOURCES.MANIFEST]: { - lastUpdateRequest: { - status: 'SUCCEEDED' - } - }, - [CONSTANTS.HOSTED_SKILL.RESOURCES.INTERACTION_MODEL]: { - [TEST_LOCALE]: { - lastUpdateRequest: { - status: 'SUCCEEDED' - } - } - }, - [CONSTANTS.HOSTED_SKILL.RESOURCES.PROVISIONING]: { - lastUpdateRequest: { - status: 'SUCCEEDED' - } - } - } - }; - const stubTestFunc = sinon.stub(httpClient, 'request'); // stub getSkillStatus smapi request - stubTestFunc.onCall(0).callsArgWith(3, null, TEST_STATUS_RESPONSE_0); - stubTestFunc.onCall(1).callsArgWith(3, null, TEST_STATUS_RESPONSE_1); - // call - hostedSkillController.checkSkillStatus(TEST_SKILL_ID, (err, res) => { - expect(err).equal(null); - expect(res).equal(TEST_SKILL_ID); - done(); - }); - }); - - it('| polling to get skill status response is null, expect error thrown ', (done) => { - // setup - const TEST_RESPONSE = null; - sinon.stub(helper, 'pollingSkillStatus').callsArgWith(2, null, TEST_RESPONSE); - // call - hostedSkillController.checkSkillStatus(TEST_SKILL_ID, (err, res) => { - expect(err).equal('Response from the creation of hosted skill is not valid.'); - expect(res).equal(undefined); - done(); - }); - }); - - it('| polling to get skill status some resources are IN_PROGRESS, expect error thrown ', (done) => { - // setup - const TEST_RESPONSE = { - manifest: CONSTANTS.HOSTED_SKILL.INTERACTION_MODEL_STATUS.SUCCESS, - interactionModel: CONSTANTS.HOSTED_SKILL.INTERACTION_MODEL_STATUS.IN_PROGRESS, - hostedSkillProvisioning: CONSTANTS.HOSTED_SKILL.PROVISIONING_STATUS.IN_PROGRESS - }; - sinon.stub(helper, 'pollingSkillStatus').callsArgWith(2, null, TEST_RESPONSE); - // call - hostedSkillController.checkSkillStatus(TEST_SKILL_ID, (err, res) => { - expect(err).equal('Timeout when checking the status of hosted-skill creation. Please try again.'); - expect(res).equal(undefined); - done(); - }); - }); - - it('| polling to get provisioning is FAILURE, expect error thrown ', (done) => { - // setup - const TEST_RESPONSE = { - manifest: CONSTANTS.HOSTED_SKILL.INTERACTION_MODEL_STATUS.SUCCESS, - interactionModel: CONSTANTS.HOSTED_SKILL.INTERACTION_MODEL_STATUS.SUCCESS, - hostedSkillProvisioning: CONSTANTS.HOSTED_SKILL.PROVISIONING_STATUS.FAILURE - }; - sinon.stub(helper, 'pollingSkillStatus').callsArgWith(2, null, TEST_RESPONSE); - // call - hostedSkillController.checkSkillStatus(TEST_SKILL_ID, (err, res) => { - expect(err).equal( - 'Check skill status failed for the following reason:\nSkill provisioning step failed.\n' - + 'Infrastructure provision for the hosted skill failed. Please try again.' - ); - expect(res).equal(undefined); - done(); - }); - }); - - it('| polling to get skill status interactionModel is FAILURE, expect error thrown ', (done) => { - // setup - const TEST_RESPONSE = { - manifest: CONSTANTS.HOSTED_SKILL.INTERACTION_MODEL_STATUS.FAILURE, - interactionModel: CONSTANTS.HOSTED_SKILL.INTERACTION_MODEL_STATUS.FAILURE, - hostedSkillProvisioning: CONSTANTS.HOSTED_SKILL.PROVISIONING_STATUS.SUCCESS - }; - sinon.stub(helper, 'pollingSkillStatus').callsArgWith(2, null, TEST_RESPONSE); - // call - hostedSkillController.checkSkillStatus(TEST_SKILL_ID, (err, res) => { - expect(err).equal( - 'Check skill status failed for the following reason:\n' - + 'Skill interaction model building step failed\nSkill manifest building step failed\n' - + 'Infrastructure provision for the hosted skill failed. Please try again.' - ); - expect(res).equal(undefined); - done(); - }); - }); - }); - - describe('# test class method: deleteSkill', () => { - let hostedSkillController; - beforeEach(() => { - hostedSkillController = new HostedSkillController(TEST_CONFIGURATION); - sinon.stub(AuthorizationController.prototype, 'tokenRefreshAndRead').callsArgWith(1); - }); - - afterEach(() => { - sinon.restore(); - }); - - it('| delete skill fails, expect error thrown', (done) => { - // setup - const TEST_ERROR = 'TEST_ERROR'; - sinon.stub(httpClient, 'request').callsArgWith(3, TEST_ERROR); // stub deleteSkill request - // call - hostedSkillController.deleteSkill(TEST_SKILL_ID, (err, res) => { - expect(err).equal(TEST_ERROR); - expect(res).equal(undefined); - done(); - }); - }); - - it('| delete skill succeed, expect no response', (done) => { - // setup - const TEST_DELETE_RESPONSE = { - statusCode: 200, - headers: {}, - body: {} - }; - sinon.stub(httpClient, 'request').callsArgWith(3, null, TEST_DELETE_RESPONSE); // stub deleteSkill request - // call - hostedSkillController.deleteSkill(TEST_SKILL_ID, (err) => { - expect(err).equal(undefined); - done(); - }); - }); - }); - - describe('# test class method: downloadAskScripts', () => { - let hostedSkillController; - const TEST_ERROR = 'error'; - const TEST_FOLDER_NAME = 'folderName'; - beforeEach(() => { - hostedSkillController = new HostedSkillController(TEST_CONFIGURATION); - }); - - afterEach(() => { - sinon.restore(); - }); - - it('| check S3 Scripts fails, expect error thrown ', (done) => { - // setup - sinon.stub(fs, 'ensureDirSync'); - sinon.stub(HostedSkillController.prototype, 'updateAskSystemScripts').callsArgWith(0, TEST_ERROR); - // call - hostedSkillController.downloadAskScripts(TEST_FOLDER_NAME, (err) => { - expect(err).equal(TEST_ERROR); - done(); - }); - }); - - it('| download Script from S3 fails, expect error thrown ', (done) => { - // setup - sinon.stub(fs, 'ensureDirSync'); - sinon.stub(HostedSkillController.prototype, 'updateAskSystemScripts').callsArgWith(0, null); - sinon.stub(helper, 'downloadScriptFromS3').callsArgWith(2, TEST_ERROR); - // call - hostedSkillController.downloadAskScripts(TEST_FOLDER_NAME, (err) => { - expect(err).equal(TEST_ERROR); - done(); - }); - }); - - it('| download Script from S3 succeeds, expect none error response', (done) => { - // setup - sinon.stub(fs, 'ensureDirSync'); - sinon.stub(HostedSkillController.prototype, 'updateAskSystemScripts').callsArgWith(0, null); - sinon.stub(helper, 'downloadScriptFromS3').callsArgWith(2, null); - // call - hostedSkillController.downloadAskScripts(TEST_FOLDER_NAME, (err) => { - expect(err).equal(null); - done(); - }); - }); - - }); - - describe('# test class method: updateAskSystemScripts', () => { - let hostedSkillController; - const TEST_ERROR = 'error'; - const TEST_FOLDER_NAME = 'folderName'; - beforeEach(() => { - hostedSkillController = new HostedSkillController(TEST_CONFIGURATION); - }); - - afterEach(() => { - sinon.restore(); - }); - - it('| update Auth Info Script fails, expect error thrown ', (done) => { - // setup - sinon.stub(fs, 'ensureDirSync'); - sinon.stub(helper, 'downloadAuthInfoScript').callsArgWith(0, TEST_ERROR); - // call - hostedSkillController.updateAskSystemScripts((err) => { - expect(err).equal(TEST_ERROR); - done(); - }); - }); - - it('| update Ask Pre Push Script fails, expect error thrown ', (done) => { - // setup - sinon.stub(fs, 'ensureDirSync'); - sinon.stub(helper, 'downloadAuthInfoScript').callsArgWith(0, null); - sinon.stub(helper, 'downloadAskPrePushScript').callsArgWith(0, TEST_ERROR); - // call - hostedSkillController.updateAskSystemScripts((err) => { - expect(err).equal(TEST_ERROR); - done(); - }); - }); - - it('| update git credential helper Script fails, expect none error response', (done) => { - // setup - sinon.stub(fs, 'ensureDirSync'); - sinon.stub(helper, 'downloadAuthInfoScript').callsArgWith(0, null); - sinon.stub(helper, 'downloadAskPrePushScript').callsArgWith(0, null); - sinon.stub(helper, 'downloadGitCredentialHelperScript').callsArgWith(0, TEST_ERROR); - // call - hostedSkillController.updateAskSystemScripts((err) => { - expect(err).equal(TEST_ERROR); - done(); - }); - }); - - it('| All Scripts checking succeeds, expect none error response', (done) => { - // setup - sinon.stub(fs, 'ensureDirSync'); - sinon.stub(helper, 'downloadAuthInfoScript').callsArgWith(0, null); - sinon.stub(helper, 'downloadAskPrePushScript').callsArgWith(0, null); - sinon.stub(helper, 'downloadGitCredentialHelperScript').callsArgWith(0, null); - // call - hostedSkillController.updateAskSystemScripts((err) => { - expect(err).equal(null); - done(); - }); - }); +const {expect} = require("chai"); +const fs = require("fs-extra"); +const sinon = require("sinon"); + +const httpClient = require("../../../../lib/clients/http-client"); +const AuthorizationController = require("../../../../lib/controllers/authorization-controller"); +const CloneFlow = require("../../../../lib/controllers/hosted-skill-controller/clone-flow"); +const helper = require("../../../../lib/controllers/hosted-skill-controller/helper"); +const HostedSkillController = require("../../../../lib/controllers/hosted-skill-controller"); +const SkillMetadataController = require("../../../../lib/controllers/skill-metadata-controller"); +const CONSTANTS = require("../../../../lib/utils/constants"); +const Messenger = require("../../../../lib/view/messenger"); +const jsonView = require("../../../../lib/view/json-view"); + +describe("Controller test - hosted skill controller test", () => { + const TEST_PROFILE = "default"; // test file uses 'default' profile + const TEST_DO_DEBUG = false; + const TEST_SKILL_ID = "SKILL_ID"; + const TEST_SKILL_NAME = "SKILL_NAME"; + const TEST_MANIFEST = {}; + const TEST_VENDOR_ID = "TEST_VENDOR_ID"; + const TEST_PERMISSION_TYPE = "TEST_PERMISSION_TYPE"; + const TEST_PROJECT_PATH = "PROJECT_PATH"; + const TEST_LOCALE = "en-US"; + const TEST_CONFIGURATION = { + profile: TEST_PROFILE, + doDebug: TEST_DO_DEBUG, + }; + describe("# inspect correctness for constructor", () => { + it("| initiate as a HostedSkillController class", () => { + const hostedSkillController = new HostedSkillController(TEST_CONFIGURATION); + expect(hostedSkillController).to.be.instanceOf(HostedSkillController); + expect(hostedSkillController.profile).equal(TEST_PROFILE); + expect(hostedSkillController.doDebug).equal(TEST_DO_DEBUG); }); + }); + + describe("# test class method: createSkill", () => { + let hostedSkillController; + beforeEach(() => { + hostedSkillController = new HostedSkillController(TEST_CONFIGURATION); + sinon.stub(AuthorizationController.prototype, "tokenRefreshAndRead").callsArgWith(1); + }); + + afterEach(() => { + sinon.restore(); + }); + + it("| create hosted skill fails, expect error thrown", (done) => { + // setup + const TEST_ERROR = "TEST_ERROR"; + sinon.stub(httpClient, "request").callsArgWith(3, TEST_ERROR); // stub createHostedSkill request + // call + hostedSkillController.createSkill(TEST_MANIFEST, (err, res) => { + expect(err).equal(TEST_ERROR); + expect(res).equal(undefined); + done(); + }); + }); + + it("| create hosted skill response status >= 300, expect error thrown", (done) => { + // setup + const TEST_ERROR = "TEST_ERROR"; + const TEST_STATUS_ERROR = { + statusCode: 403, + body: { + error: TEST_ERROR, + }, + }; + sinon.stub(httpClient, "request").callsArgWith(3, null, TEST_STATUS_ERROR); // stub createHostedSkill request + // call + hostedSkillController.createSkill(TEST_MANIFEST, (err, res) => { + expect(err).equal(jsonView.toString({error: TEST_ERROR})); + expect(res).equal(undefined); + done(); + }); + }); + + it("| polling skill status fails, expect error thrown", (done) => { + // setup + const TEST_CREATE_SKILL_RESPONSE = { + statusCode: 200, + headers: {}, + body: {}, + }; + const TEST_POLLING_ERROR = "TEST_POLLING_ERROR"; + sinon.stub(httpClient, "request").callsArgWith(3, null, TEST_CREATE_SKILL_RESPONSE); // stub createHostedSkill request + sinon.stub(helper, "pollingSkillStatus").callsArgWith(2, TEST_POLLING_ERROR); + // call + hostedSkillController.createSkill(TEST_MANIFEST, (err, res) => { + expect(err).equal(TEST_POLLING_ERROR); + expect(res).equal(undefined); + done(); + }); + }); + + it("| polling skill status succeed, expect skillId return", (done) => { + // setup + const TEST_CREATE_SKILL_RESPONSE = { + statusCode: 200, + headers: {}, + body: { + skillId: TEST_SKILL_ID, + }, + }; + sinon.stub(httpClient, "request").callsArgWith(3, null, TEST_CREATE_SKILL_RESPONSE); // stub createHostedSkill request + sinon.stub(helper, "pollingSkillStatus").callsArgWith(2, null); + sinon.stub(helper, "handleSkillStatus").callsArgWith(2, null); + // call + hostedSkillController.createSkill(TEST_MANIFEST, (err, res) => { + expect(err).equal(null); + expect(res).equal(TEST_SKILL_ID); + done(); + }); + }); + }); + + describe("# test class method: clone", () => { + let hostedSkillController; + let infoStub; + beforeEach(() => { + hostedSkillController = new HostedSkillController(TEST_CONFIGURATION); + sinon.stub(AuthorizationController.prototype, "tokenRefreshAndRead").callsArgWith(1); + infoStub = sinon.stub(); + sinon.stub(Messenger, "getInstance").returns({ + info: infoStub, + }); + }); + + afterEach(() => { + sinon.restore(); + }); + + it("| project directory already exists, expect error thrown ", (done) => { + // setup + sinon.stub(fs, "existsSync").withArgs(TEST_PROJECT_PATH).returns(true); + // call + hostedSkillController.clone(TEST_SKILL_ID, TEST_SKILL_NAME, TEST_PROJECT_PATH, (err, res) => { + expect(err).equal(`${TEST_PROJECT_PATH} directory already exists.`); + expect(res).equal(undefined); + done(); + }); + }); + + it("| get Hosted skill Metadata fails, expect error thrown ", (done) => { + // setup + const TEST_METADATA_ERROR = "TEST_METADATA_ERROR"; + const TEST_ERROR = new Error(TEST_METADATA_ERROR); + sinon.stub(fs, "existsSync").withArgs(TEST_PROJECT_PATH).returns(false); + sinon.stub(httpClient, "request").callsArgWith(3, TEST_ERROR); // stub getAlexaHostedSkillMetadata smapi request + // call + hostedSkillController.clone(TEST_SKILL_ID, TEST_SKILL_NAME, TEST_PROJECT_PATH, (err, res) => { + expect(err.message).equal(TEST_METADATA_ERROR); + expect(res).equal(undefined); + done(); + }); + }); + + it("| get Hosted skill Metadata response status >= 300, expect error thrown ", (done) => { + // setup + const TEST_METADATA_ERROR = "TEST_METADATA_ERROR"; + const TEST_STATUS_ERROR = { + statusCode: 403, + body: { + error: TEST_METADATA_ERROR, + }, + }; + sinon.stub(fs, "existsSync").withArgs(TEST_PROJECT_PATH).returns(false); + sinon.stub(httpClient, "request").callsArgWith(3, null, TEST_STATUS_ERROR); // stub getAlexaHostedSkillMetadata smapi request + // call + hostedSkillController.clone(TEST_SKILL_ID, TEST_SKILL_NAME, TEST_PROJECT_PATH, (err, res) => { + expect(err).equal(jsonView.toString({error: TEST_METADATA_ERROR})); + expect(res).equal(undefined); + done(); + }); + }); + + it("| do skill package exist fails, expect error thrown ", (done) => { + // setup + const TEST_SKILL_PACKAGE_ERROR = "TEST_SKILL_PACKAGE_ERROR"; + const TEST_STATUS_RESPONSE = { + statusCode: 200, + body: { + alexaHosted: {repository: {url: "test"}}, + }, + }; + sinon.stub(fs, "existsSync").withArgs(TEST_PROJECT_PATH).returns(false); + sinon.stub(httpClient, "request").callsArgWith(3, null, TEST_STATUS_RESPONSE); // stub getAlexaHostedSkillMetadata smapi request + sinon.stub(CloneFlow, "generateProject"); + sinon.stub(CloneFlow, "cloneProjectFromGit"); + sinon.stub(CloneFlow, "doSkillPackageExist").callsArgWith(3, TEST_SKILL_PACKAGE_ERROR); + // call + hostedSkillController.clone(TEST_SKILL_ID, TEST_SKILL_NAME, TEST_PROJECT_PATH, (err, res) => { + expect(err).equal(TEST_SKILL_PACKAGE_ERROR); + expect(res).equal(undefined); + done(); + }); + }); + + it("| skill package exists, expect skill-package generated ", (done) => { + // setup + sinon.stub(fs, "existsSync").withArgs(TEST_PROJECT_PATH).returns(false); + sinon.stub(HostedSkillController.prototype, "getHostedSkillMetadata").yields(null, {repository: {url: "test"}}); + sinon.stub(CloneFlow, "generateProject"); + sinon.stub(CloneFlow, "cloneProjectFromGit"); + sinon.stub(CloneFlow, "doSkillPackageExist").callsArgWith(3, null, true); + // call + hostedSkillController.clone(TEST_SKILL_ID, TEST_SKILL_NAME, TEST_PROJECT_PATH, (err) => { + expect(err).equal(undefined); + expect(Messenger.getInstance().info.args[0][0]).equal( + `\nSkill schema and interactionModels for ${TEST_SKILL_NAME} created at\n\t./skill-package\n`, + ); + done(); + }); + }); + + it("| skill package do NOT exist, export skill-package fails, expect no error ", (done) => { + // setup + const TEST_EXPORT_ERROR = "TEST_EXPORT_ERROR"; + sinon.stub(fs, "existsSync").withArgs(TEST_PROJECT_PATH).returns(false); + sinon.stub(HostedSkillController.prototype, "getHostedSkillMetadata").yields(null, {repository: {url: "test"}}); + sinon.stub(CloneFlow, "generateProject"); + sinon.stub(CloneFlow, "cloneProjectFromGit"); + sinon.stub(CloneFlow, "doSkillPackageExist").callsArgWith(3, null, false); + sinon.stub(SkillMetadataController.prototype, "getSkillPackage").callsArgWith(3, TEST_EXPORT_ERROR); + // call + hostedSkillController.clone(TEST_SKILL_ID, TEST_SKILL_NAME, TEST_PROJECT_PATH, (err) => { + expect(err).equal(TEST_EXPORT_ERROR); + done(); + }); + }); + + it("| skill package do NOT exist, export skill-package succeed, expect skill-package generated ", (done) => { + // setup + sinon.stub(fs, "existsSync").withArgs(TEST_PROJECT_PATH).returns(false); + sinon.stub(HostedSkillController.prototype, "getHostedSkillMetadata").yields(null, {repository: {url: "test"}}); + sinon.stub(CloneFlow, "generateProject"); + sinon.stub(CloneFlow, "cloneProjectFromGit"); + sinon.stub(CloneFlow, "doSkillPackageExist").callsArgWith(3, null); + sinon.stub(SkillMetadataController.prototype, "getSkillPackage").callsArgWith(3, null); + // call + hostedSkillController.clone(TEST_SKILL_ID, TEST_SKILL_NAME, TEST_PROJECT_PATH, (err) => { + expect(err).equal(undefined); + expect(Messenger.getInstance().info.args[0][0]).equal( + `\nSkill schema and interactionModels for ${TEST_SKILL_NAME} created at\n\t./skill-package\n`, + ); + done(); + }); + }); + }); + + describe("# test class method: getHostedSkillPermission", () => { + let hostedSkillController; + beforeEach(() => { + hostedSkillController = new HostedSkillController(TEST_CONFIGURATION); + sinon.stub(AuthorizationController.prototype, "tokenRefreshAndRead").callsArgWith(1); + }); + + afterEach(() => { + sinon.restore(); + }); + + it("| get hosted skill permission fails, expect error thrown", (done) => { + // setup + const TEST_ERROR = "TEST_ERROR"; + sinon.stub(httpClient, "request").callsArgWith(3, TEST_ERROR); // stub getHostedSkillPermission request + // call + hostedSkillController.getHostedSkillPermission(TEST_VENDOR_ID, TEST_PERMISSION_TYPE, (err, res) => { + expect(err).equal(TEST_ERROR); + expect(res).equal(undefined); + done(); + }); + }); + + it("| get hosted skill permission response status >= 300, expect error thrown", (done) => { + // setup + const TEST_ERROR = "TEST_ERROR"; + const TEST_STATUS_ERROR = { + statusCode: 403, + body: { + error: TEST_ERROR, + }, + }; + sinon.stub(httpClient, "request").callsArgWith(3, null, TEST_STATUS_ERROR); // stub getHostedSkillPermission request + // call + hostedSkillController.getHostedSkillPermission(TEST_VENDOR_ID, TEST_PERMISSION_TYPE, (err, res) => { + expect(err).equal(jsonView.toString({error: TEST_ERROR})); + expect(res).equal(undefined); + done(); + }); + }); + + it("| get hosted skill permission succeed, expect error thrown", (done) => { + // setup + const TEST_PERMISSION_RESPONSE = { + statusCode: 200, + headers: {}, + body: {}, + }; + sinon.stub(httpClient, "request").callsArgWith(3, null, TEST_PERMISSION_RESPONSE); // stub getHostedSkillPermission request + // call + hostedSkillController.getHostedSkillPermission(TEST_VENDOR_ID, TEST_PERMISSION_TYPE, (err) => { + expect(err).equal(null); + done(); + }); + }); + }); + + describe("# test class method: checkSkillStatus", () => { + let hostedSkillController; + let infoStub; + beforeEach(() => { + infoStub = sinon.stub(); + sinon.stub(Messenger, "getInstance").returns({ + info: infoStub, + }); + hostedSkillController = new HostedSkillController(TEST_CONFIGURATION); + sinon.stub(AuthorizationController.prototype, "tokenRefreshAndRead").callsArgWith(1); + }); + + afterEach(() => { + sinon.restore(); + }); + + it("| polling to get skill status fails, expect error thrown ", (done) => { + // setup + const TEST_STATUS_ERROR = "TEST_STATUS_ERROR"; + const TEST_ERROR = new Error(TEST_STATUS_ERROR); + sinon.stub(httpClient, "request").callsArgWith(3, TEST_ERROR); // stub getSkillStatus smapi request + // call + hostedSkillController.checkSkillStatus(TEST_SKILL_ID, (err, res) => { + expect(err.message).equal(TEST_STATUS_ERROR); + expect(res).equal(undefined); + done(); + }); + }); + + it("| polling to get skill status response >= 300, expect error thrown ", (done) => { + // setup + const TEST_STATUS_ERROR = "TEST_STATUS_ERROR"; + const TEST_ERROR = { + statusCode: 403, + body: { + error: TEST_STATUS_ERROR, + }, + }; + sinon.stub(httpClient, "request").callsArgWith(3, null, TEST_ERROR); // stub getSkillStatus smapi request + // call + hostedSkillController.checkSkillStatus(TEST_SKILL_ID, (err, res) => { + expect(err).equal(jsonView.toString({error: TEST_STATUS_ERROR})); + expect(res).equal(undefined); + done(); + }); + }); + + it("| polling to get skill status until all resources are SUCCEEDED, expect correct response", (done) => { + // setup + const TEST_STATUS_RESPONSE_0 = { + statusCode: 200, + headers: {}, + body: { + [CONSTANTS.HOSTED_SKILL.RESOURCES.MANIFEST]: { + lastUpdateRequest: { + status: "SUCCEEDED", + }, + }, + }, + }; + const TEST_STATUS_RESPONSE_1 = { + statusCode: 200, + headers: {}, + body: { + [CONSTANTS.HOSTED_SKILL.RESOURCES.MANIFEST]: { + lastUpdateRequest: { + status: "SUCCEEDED", + }, + }, + [CONSTANTS.HOSTED_SKILL.RESOURCES.INTERACTION_MODEL]: { + [TEST_LOCALE]: { + lastUpdateRequest: { + status: "SUCCEEDED", + }, + }, + }, + [CONSTANTS.HOSTED_SKILL.RESOURCES.PROVISIONING]: { + lastUpdateRequest: { + status: "SUCCEEDED", + }, + }, + }, + }; + const stubTestFunc = sinon.stub(httpClient, "request"); // stub getSkillStatus smapi request + stubTestFunc.onCall(0).callsArgWith(3, null, TEST_STATUS_RESPONSE_0); + stubTestFunc.onCall(1).callsArgWith(3, null, TEST_STATUS_RESPONSE_1); + // call + hostedSkillController.checkSkillStatus(TEST_SKILL_ID, (err, res) => { + expect(err).equal(null); + expect(res).equal(TEST_SKILL_ID); + done(); + }); + }); + + it("| polling to get skill status response is null, expect error thrown ", (done) => { + // setup + const TEST_RESPONSE = null; + sinon.stub(helper, "pollingSkillStatus").callsArgWith(2, null, TEST_RESPONSE); + // call + hostedSkillController.checkSkillStatus(TEST_SKILL_ID, (err, res) => { + expect(err).equal("Response from the creation of hosted skill is not valid."); + expect(res).equal(undefined); + done(); + }); + }); + + it("| polling to get skill status some resources are IN_PROGRESS, expect error thrown ", (done) => { + // setup + const TEST_RESPONSE = { + manifest: CONSTANTS.HOSTED_SKILL.INTERACTION_MODEL_STATUS.SUCCESS, + interactionModel: CONSTANTS.HOSTED_SKILL.INTERACTION_MODEL_STATUS.IN_PROGRESS, + hostedSkillProvisioning: CONSTANTS.HOSTED_SKILL.PROVISIONING_STATUS.IN_PROGRESS, + }; + sinon.stub(helper, "pollingSkillStatus").callsArgWith(2, null, TEST_RESPONSE); + // call + hostedSkillController.checkSkillStatus(TEST_SKILL_ID, (err, res) => { + expect(err).equal("Timeout when checking the status of hosted-skill creation. Please try again."); + expect(res).equal(undefined); + done(); + }); + }); + + it("| polling to get provisioning is FAILURE, expect error thrown ", (done) => { + // setup + const TEST_RESPONSE = { + manifest: CONSTANTS.HOSTED_SKILL.INTERACTION_MODEL_STATUS.SUCCESS, + interactionModel: CONSTANTS.HOSTED_SKILL.INTERACTION_MODEL_STATUS.SUCCESS, + hostedSkillProvisioning: CONSTANTS.HOSTED_SKILL.PROVISIONING_STATUS.FAILURE, + }; + sinon.stub(helper, "pollingSkillStatus").callsArgWith(2, null, TEST_RESPONSE); + // call + hostedSkillController.checkSkillStatus(TEST_SKILL_ID, (err, res) => { + expect(err).equal( + "Check skill status failed for the following reason:\nSkill provisioning step failed.\n" + + "Infrastructure provision for the hosted skill failed. Please try again.", + ); + expect(res).equal(undefined); + done(); + }); + }); + + it("| polling to get skill status interactionModel is FAILURE, expect error thrown ", (done) => { + // setup + const TEST_RESPONSE = { + manifest: CONSTANTS.HOSTED_SKILL.INTERACTION_MODEL_STATUS.FAILURE, + interactionModel: CONSTANTS.HOSTED_SKILL.INTERACTION_MODEL_STATUS.FAILURE, + hostedSkillProvisioning: CONSTANTS.HOSTED_SKILL.PROVISIONING_STATUS.SUCCESS, + }; + sinon.stub(helper, "pollingSkillStatus").callsArgWith(2, null, TEST_RESPONSE); + // call + hostedSkillController.checkSkillStatus(TEST_SKILL_ID, (err, res) => { + expect(err).equal( + "Check skill status failed for the following reason:\n" + + "Skill interaction model building step failed\nSkill manifest building step failed\n" + + "Infrastructure provision for the hosted skill failed. Please try again.", + ); + expect(res).equal(undefined); + done(); + }); + }); + }); + + describe("# test class method: deleteSkill", () => { + let hostedSkillController; + beforeEach(() => { + hostedSkillController = new HostedSkillController(TEST_CONFIGURATION); + sinon.stub(AuthorizationController.prototype, "tokenRefreshAndRead").callsArgWith(1); + }); + + afterEach(() => { + sinon.restore(); + }); + + it("| delete skill fails, expect error thrown", (done) => { + // setup + const TEST_ERROR = "TEST_ERROR"; + sinon.stub(httpClient, "request").callsArgWith(3, TEST_ERROR); // stub deleteSkill request + // call + hostedSkillController.deleteSkill(TEST_SKILL_ID, (err, res) => { + expect(err).equal(TEST_ERROR); + expect(res).equal(undefined); + done(); + }); + }); + + it("| delete skill succeed, expect no response", (done) => { + // setup + const TEST_DELETE_RESPONSE = { + statusCode: 200, + headers: {}, + body: {}, + }; + sinon.stub(httpClient, "request").callsArgWith(3, null, TEST_DELETE_RESPONSE); // stub deleteSkill request + // call + hostedSkillController.deleteSkill(TEST_SKILL_ID, (err) => { + expect(err).equal(undefined); + done(); + }); + }); + }); + + describe("# test class method: downloadAskScripts", () => { + let hostedSkillController; + const TEST_ERROR = "error"; + const TEST_FOLDER_NAME = "folderName"; + beforeEach(() => { + hostedSkillController = new HostedSkillController(TEST_CONFIGURATION); + }); + + afterEach(() => { + sinon.restore(); + }); + + it("| check S3 Scripts fails, expect error thrown ", (done) => { + // setup + sinon.stub(fs, "ensureDirSync"); + sinon.stub(HostedSkillController.prototype, "updateAskSystemScripts").callsArgWith(0, TEST_ERROR); + // call + hostedSkillController.downloadAskScripts(TEST_FOLDER_NAME, (err) => { + expect(err).equal(TEST_ERROR); + done(); + }); + }); + + it("| download Script from S3 fails, expect error thrown ", (done) => { + // setup + sinon.stub(fs, "ensureDirSync"); + sinon.stub(HostedSkillController.prototype, "updateAskSystemScripts").callsArgWith(0, null); + sinon.stub(helper, "downloadScriptFromS3").callsArgWith(2, TEST_ERROR); + // call + hostedSkillController.downloadAskScripts(TEST_FOLDER_NAME, (err) => { + expect(err).equal(TEST_ERROR); + done(); + }); + }); + + it("| download Script from S3 succeeds, expect none error response", (done) => { + // setup + sinon.stub(fs, "ensureDirSync"); + sinon.stub(HostedSkillController.prototype, "updateAskSystemScripts").callsArgWith(0, null); + sinon.stub(helper, "downloadScriptFromS3").callsArgWith(2, null); + // call + hostedSkillController.downloadAskScripts(TEST_FOLDER_NAME, (err) => { + expect(err).equal(null); + done(); + }); + }); + }); + + describe("# test class method: updateAskSystemScripts", () => { + let hostedSkillController; + const TEST_ERROR = "error"; + const TEST_FOLDER_NAME = "folderName"; + beforeEach(() => { + hostedSkillController = new HostedSkillController(TEST_CONFIGURATION); + }); + + afterEach(() => { + sinon.restore(); + }); + + it("| update Auth Info Script fails, expect error thrown ", (done) => { + // setup + sinon.stub(fs, "ensureDirSync"); + sinon.stub(helper, "downloadAuthInfoScript").callsArgWith(0, TEST_ERROR); + // call + hostedSkillController.updateAskSystemScripts((err) => { + expect(err).equal(TEST_ERROR); + done(); + }); + }); + + it("| update Ask Pre Push Script fails, expect error thrown ", (done) => { + // setup + sinon.stub(fs, "ensureDirSync"); + sinon.stub(helper, "downloadAuthInfoScript").callsArgWith(0, null); + sinon.stub(helper, "downloadAskPrePushScript").callsArgWith(0, TEST_ERROR); + // call + hostedSkillController.updateAskSystemScripts((err) => { + expect(err).equal(TEST_ERROR); + done(); + }); + }); + + it("| update git credential helper Script fails, expect none error response", (done) => { + // setup + sinon.stub(fs, "ensureDirSync"); + sinon.stub(helper, "downloadAuthInfoScript").callsArgWith(0, null); + sinon.stub(helper, "downloadAskPrePushScript").callsArgWith(0, null); + sinon.stub(helper, "downloadGitCredentialHelperScript").callsArgWith(0, TEST_ERROR); + // call + hostedSkillController.updateAskSystemScripts((err) => { + expect(err).equal(TEST_ERROR); + done(); + }); + }); + + it("| All Scripts checking succeeds, expect none error response", (done) => { + // setup + sinon.stub(fs, "ensureDirSync"); + sinon.stub(helper, "downloadAuthInfoScript").callsArgWith(0, null); + sinon.stub(helper, "downloadAskPrePushScript").callsArgWith(0, null); + sinon.stub(helper, "downloadGitCredentialHelperScript").callsArgWith(0, null); + // call + hostedSkillController.updateAskSystemScripts((err) => { + expect(err).equal(null); + done(); + }); + }); + }); }); diff --git a/test/unit/controller/skill-code-controller-test.js b/test/unit/controller/skill-code-controller-test.js index 5b1e1677..5d0400ce 100644 --- a/test/unit/controller/skill-code-controller-test.js +++ b/test/unit/controller/skill-code-controller-test.js @@ -1,173 +1,181 @@ -const { expect } = require('chai'); -const sinon = require('sinon'); -const path = require('path'); -const fs = require('fs-extra'); -const ResourcesConfig = require('@src/model/resources-config'); -const SkillCodeController = require('@src/controllers/skill-code-controller'); -const CodeBuilder = require('@src/controllers/skill-code-controller/code-builder'); +const {expect} = require("chai"); +const sinon = require("sinon"); +const path = require("path"); +const fs = require("fs-extra"); +const ResourcesConfig = require("../../../lib/model/resources-config"); +const SkillCodeController = require("../../../lib/controllers/skill-code-controller"); +const CodeBuilder = require("../../../lib/controllers/skill-code-controller/code-builder"); -describe('Controller test - skill code controller test', () => { - const FIXTURE_RESOURCES_CONFIG_FILE_PATH = path.join(process.cwd(), 'test', 'unit', 'fixture', 'model', 'regular-proj', 'ask-resources.json'); - const TEST_PROFILE = 'default'; // test file uses 'default' profile - const TEST_DO_DEBUG = false; - const TEST_CODE_SRC = './awsStack/lambda-NA/src'; - const TEST_EU_CODE_SRC = './awsStack/lambda-EU/src'; - const TEST_CODE_BUILD = 'build'; - const TEST_CONFIGURATION = { - profile: TEST_PROFILE, - doDebug: TEST_DO_DEBUG - }; +describe("Controller test - skill code controller test", () => { + const FIXTURE_RESOURCES_CONFIG_FILE_PATH = path.join( + process.cwd(), + "test", + "unit", + "fixture", + "model", + "regular-proj", + "ask-resources.json", + ); + const TEST_PROFILE = "default"; // test file uses 'default' profile + const TEST_DO_DEBUG = false; + const TEST_CODE_SRC = "./awsStack/lambda-NA/src"; + const TEST_EU_CODE_SRC = "./awsStack/lambda-EU/src"; + const TEST_CODE_BUILD = "build"; + const TEST_CONFIGURATION = { + profile: TEST_PROFILE, + doDebug: TEST_DO_DEBUG, + }; - describe('# inspect correctness for constructor', () => { - it('| initiate as a SkillCodeController class', () => { - const skillCodeController = new SkillCodeController(TEST_CONFIGURATION); - expect(skillCodeController).to.be.instanceOf(SkillCodeController); - expect(skillCodeController.profile).equal(TEST_PROFILE); - expect(skillCodeController.doDebug).equal(false); - }); + describe("# inspect correctness for constructor", () => { + it("| initiate as a SkillCodeController class", () => { + const skillCodeController = new SkillCodeController(TEST_CONFIGURATION); + expect(skillCodeController).to.be.instanceOf(SkillCodeController); + expect(skillCodeController.profile).equal(TEST_PROFILE); + expect(skillCodeController.doDebug).equal(false); }); + }); - describe('# test class method: buildCode', () => { - const TEST_CODE_LIST = [ - { - src: TEST_CODE_SRC, - build: TEST_CODE_BUILD, - doDebug: TEST_DO_DEBUG - } - ]; - let skillCodeController; + describe("# test class method: buildCode", () => { + const TEST_CODE_LIST = [ + { + src: TEST_CODE_SRC, + build: TEST_CODE_BUILD, + doDebug: TEST_DO_DEBUG, + }, + ]; + let skillCodeController; - beforeEach(() => { - skillCodeController = new SkillCodeController(TEST_CONFIGURATION); - new ResourcesConfig(FIXTURE_RESOURCES_CONFIG_FILE_PATH); - }); + beforeEach(() => { + skillCodeController = new SkillCodeController(TEST_CONFIGURATION); + new ResourcesConfig(FIXTURE_RESOURCES_CONFIG_FILE_PATH); + }); - afterEach(() => { - ResourcesConfig.dispose(); - sinon.restore(); - }); + afterEach(() => { + ResourcesConfig.dispose(); + sinon.restore(); + }); - it('| skillCodeController resolve unique code settings fails, expect error throws', (done) => { - // setup - sinon.stub(SkillCodeController.prototype, '_resolveUniqueCodeList').throws(new Error('error')); - // call - skillCodeController.buildCode((err) => { - // verify - expect(err.message).equal('error'); - done(); - }); - }); + it("| skillCodeController resolve unique code settings fails, expect error throws", (done) => { + // setup + sinon.stub(SkillCodeController.prototype, "_resolveUniqueCodeList").throws(new Error("error")); + // call + skillCodeController.buildCode((err) => { + // verify + expect(err.message).equal("error"); + done(); + }); + }); - it('| skillCodeController resolve unique code settings passes but code builder execute fails, expect error throws', (done) => { - // setup - sinon.stub(SkillCodeController.prototype, '_resolveUniqueCodeList').returns(TEST_CODE_LIST); - sinon.stub(CodeBuilder.prototype, '_selectBuildFlowClass'); - sinon.stub(CodeBuilder.prototype, 'execute').callsArgWith(0, 'error'); - // call - skillCodeController.buildCode((err) => { - // verify - expect(err).equal('error'); - done(); - }); - }); + it("| skillCodeController resolve unique code settings passes but code builder execute fails, expect error throws", (done) => { + // setup + sinon.stub(SkillCodeController.prototype, "_resolveUniqueCodeList").returns(TEST_CODE_LIST); + sinon.stub(CodeBuilder.prototype, "_selectBuildFlowClass"); + sinon.stub(CodeBuilder.prototype, "execute").callsArgWith(0, "error"); + // call + skillCodeController.buildCode((err) => { + // verify + expect(err).equal("error"); + done(); + }); + }); - it('| skillCodeController resolve unique code settings and code builder execute pass, expect no error called back', (done) => { - // setup - sinon.stub(SkillCodeController.prototype, '_resolveUniqueCodeList').returns(TEST_CODE_LIST); - sinon.stub(CodeBuilder.prototype, '_selectBuildFlowClass'); - sinon.stub(CodeBuilder.prototype, 'execute').callsArgWith(0); - // call - skillCodeController.buildCode((err) => { - // verify - expect(err).equal(null); - done(); - }); - }); + it("| skillCodeController resolve unique code settings and code builder execute pass, expect no error called back", (done) => { + // setup + sinon.stub(SkillCodeController.prototype, "_resolveUniqueCodeList").returns(TEST_CODE_LIST); + sinon.stub(CodeBuilder.prototype, "_selectBuildFlowClass"); + sinon.stub(CodeBuilder.prototype, "execute").callsArgWith(0); + // call + skillCodeController.buildCode((err) => { + // verify + expect(err).equal(null); + done(); + }); }); + }); - describe('# test class method: _resolveUniqueCodeList', () => { - let skillCodeController; + describe("# test class method: _resolveUniqueCodeList", () => { + let skillCodeController; - beforeEach(() => { - skillCodeController = new SkillCodeController(TEST_CONFIGURATION); - new ResourcesConfig(FIXTURE_RESOURCES_CONFIG_FILE_PATH); - sinon.stub(fs, 'existsSync').returns(true); - }); + beforeEach(() => { + skillCodeController = new SkillCodeController(TEST_CONFIGURATION); + new ResourcesConfig(FIXTURE_RESOURCES_CONFIG_FILE_PATH); + sinon.stub(fs, "existsSync").returns(true); + }); - afterEach(() => { - ResourcesConfig.dispose(); - sinon.restore(); - }); + afterEach(() => { + ResourcesConfig.dispose(); + sinon.restore(); + }); - it('| codeResources does not exist, expect error throws', () => { - // setup - sinon.stub(ResourcesConfig.prototype, 'getCodeRegions').returns([]); - // call - try { - skillCodeController._resolveUniqueCodeList(); - } catch (e) { - // verify - expect(e).equal('Invalid skill code settings. Please make sure to provide the "code" field correctly in ask-resources file.'); - } - }); + it("| codeResources does not exist, expect error throws", () => { + // setup + sinon.stub(ResourcesConfig.prototype, "getCodeRegions").returns([]); + // call + try { + skillCodeController._resolveUniqueCodeList(); + } catch (e) { + // verify + expect(e).equal('Invalid skill code settings. Please make sure to provide the "code" field correctly in ask-resources file.'); + } + }); - it('| codeResources src is blank string, expect error throws', () => { - // setup - ResourcesConfig.getInstance().setCodeSrcByRegion(TEST_PROFILE, 'region1', ' '); - // call - try { - skillCodeController._resolveUniqueCodeList(); - } catch (e) { - // verify - expect(e).equal('Invalid code setting in region region1. "src" must be set if you want to deploy skill code with skill package.'); - } - }); + it("| codeResources src is blank string, expect error throws", () => { + // setup + ResourcesConfig.getInstance().setCodeSrcByRegion(TEST_PROFILE, "region1", " "); + // call + try { + skillCodeController._resolveUniqueCodeList(); + } catch (e) { + // verify + expect(e).equal('Invalid code setting in region region1. "src" must be set if you want to deploy skill code with skill package.'); + } + }); - it('| codeResources src does not exist, expect error throws', () => { - // setup - ResourcesConfig.getInstance().setCodeSrcByRegion(TEST_PROFILE, 'default', TEST_CODE_SRC); - fs.existsSync.withArgs(TEST_CODE_SRC).returns(false); - // call - try { - skillCodeController._resolveUniqueCodeList(); - } catch (e) { - // verify - expect(e).equal(`Invalid code setting in region default. File doesn't exist for code src: ${TEST_CODE_SRC}.`); - } - }); + it("| codeResources src does not exist, expect error throws", () => { + // setup + ResourcesConfig.getInstance().setCodeSrcByRegion(TEST_PROFILE, "default", TEST_CODE_SRC); + fs.existsSync.withArgs(TEST_CODE_SRC).returns(false); + // call + try { + skillCodeController._resolveUniqueCodeList(); + } catch (e) { + // verify + expect(e).equal(`Invalid code setting in region default. File doesn't exist for code src: ${TEST_CODE_SRC}.`); + } + }); - it('| codeResources has same src code in different regions, expect the list is unique result', () => { - // setup - sinon.stub(ResourcesConfig.prototype, 'getCodeBuildByRegion').returns({ - folder: 'folder', - file: 'file' - }); - // call - let codeLists; - try { - codeLists = skillCodeController._resolveUniqueCodeList(); - } catch (e) { - // verify - expect(e).equal(undefined); - } - expect(codeLists).deep.equal([ - { - src: TEST_CODE_SRC, - build: { - folder: 'folder', - file: 'file' - }, - regionsList: ['default', 'NA'] - }, - { - src: TEST_EU_CODE_SRC, - build: { - folder: 'folder', - file: 'file' - }, - regionsList: ['EU'] - } - ]); - }); + it("| codeResources has same src code in different regions, expect the list is unique result", () => { + // setup + sinon.stub(ResourcesConfig.prototype, "getCodeBuildByRegion").returns({ + folder: "folder", + file: "file", + }); + // call + let codeLists; + try { + codeLists = skillCodeController._resolveUniqueCodeList(); + } catch (e) { + // verify + expect(e).equal(undefined); + } + expect(codeLists).deep.equal([ + { + src: TEST_CODE_SRC, + build: { + folder: "folder", + file: "file", + }, + regionsList: ["default", "NA"], + }, + { + src: TEST_EU_CODE_SRC, + build: { + folder: "folder", + file: "file", + }, + regionsList: ["EU"], + }, + ]); }); + }); }); diff --git a/test/unit/controller/skill-infrastructure-controller-test.js b/test/unit/controller/skill-infrastructure-controller-test.js index 2abcf17f..bf9abc46 100644 --- a/test/unit/controller/skill-infrastructure-controller-test.js +++ b/test/unit/controller/skill-infrastructure-controller-test.js @@ -1,872 +1,872 @@ -const { expect } = require('chai'); -const sinon = require('sinon'); -const fs = require('fs'); -const fse = require('fs-extra'); -const path = require('path'); - -const SkillMetadataController = require('@src/controllers/skill-metadata-controller'); -const ResourcesConfig = require('@src/model/resources-config'); -const Manifest = require('@src/model/manifest'); -const SkillInfrastructureController = require('@src/controllers/skill-infrastructure-controller'); -const DeployDelegate = require('@src/controllers/skill-infrastructure-controller/deploy-delegate'); -const MultiTasksView = require('@src/view/multi-tasks-view'); -const AuthorizationController = require('@src/controllers/authorization-controller'); -const profileHelper = require('@src/utils/profile-helper'); -const hashUtils = require('@src/utils/hash-utils'); - -describe('Controller test - skill infrastructure controller test', () => { - const FIXTURE_RESOURCES_CONFIG_FILE_PATH = path.join(process.cwd(), 'test', 'unit', 'fixture', 'model', 'regular-proj', 'ask-resources.json'); - const FIXTURE_MANIFEST_FILE_PATH = path.join(process.cwd(), 'test', 'unit', 'fixture', 'model', 'manifest.json'); - const TEST_PROFILE = 'default'; // test file uses 'default' profile - const TEST_WORKSPACE = 'workspace'; - const TEST_CONFIGURATION = { - profile: TEST_PROFILE, - doDebug: false - }; - const TEST_USER_CONFIG = { - user: 'config' - }; - - describe('# inspect correctness for constructor', () => { - it('| initiate as a SkillInfrastructureController class', () => { - const skillInfraController = new SkillInfrastructureController(TEST_CONFIGURATION); - expect(skillInfraController).to.be.instanceOf(SkillInfrastructureController); - expect(skillInfraController.profile).equal(TEST_PROFILE); - expect(skillInfraController.doDebug).equal(false); - }); +const {expect} = require("chai"); +const sinon = require("sinon"); +const fs = require("fs"); +const fse = require("fs-extra"); +const path = require("path"); + +const SkillMetadataController = require("../../../lib/controllers/skill-metadata-controller"); +const ResourcesConfig = require("../../../lib/model/resources-config"); +const Manifest = require("../../../lib/model/manifest"); +const SkillInfrastructureController = require("../../../lib/controllers/skill-infrastructure-controller"); +const DeployDelegate = require("../../../lib/controllers/skill-infrastructure-controller/deploy-delegate"); +const MultiTasksView = require("../../../lib/view/multi-tasks-view"); +const AuthorizationController = require("../../../lib/controllers/authorization-controller"); +const profileHelper = require("../../../lib/utils/profile-helper"); +const hashUtils = require("../../../lib/utils/hash-utils"); +const acUtils = require("../../../lib/utils/ac-util"); + +describe("Controller test - skill infrastructure controller test", () => { + const FIXTURE_RESOURCES_CONFIG_FILE_PATH = path.join( + process.cwd(), + "test", + "unit", + "fixture", + "model", + "regular-proj", + "ask-resources.json", + ); + const FIXTURE_MANIFEST_FILE_PATH = path.join(process.cwd(), "test", "unit", "fixture", "model", "manifest.json"); + const TEST_PROFILE = "default"; // test file uses 'default' profile + const TEST_WORKSPACE = "workspace"; + const TEST_CONFIGURATION = { + profile: TEST_PROFILE, + doDebug: false, + }; + const TEST_USER_CONFIG = { + user: "config", + }; + + describe("# inspect correctness for constructor", () => { + it("| initiate as a SkillInfrastructureController class", () => { + const skillInfraController = new SkillInfrastructureController(TEST_CONFIGURATION); + expect(skillInfraController).to.be.instanceOf(SkillInfrastructureController); + expect(skillInfraController.profile).equal(TEST_PROFILE); + expect(skillInfraController.doDebug).equal(false); }); + }); - describe('# test class method: bootstrapInfrastructures', () => { - const skillInfraController = new SkillInfrastructureController(TEST_CONFIGURATION); - - beforeEach(() => { - new ResourcesConfig(FIXTURE_RESOURCES_CONFIG_FILE_PATH); - }); - - afterEach(() => { - ResourcesConfig.dispose(); - sinon.restore(); - }); - - it('| skill infrastructures infra type not set, expect error is called back', (done) => { - // setup - ResourcesConfig.getInstance().setSkillInfraType(TEST_PROFILE, ' '); - // call - skillInfraController.bootstrapInfrastructures(TEST_WORKSPACE, (err, res) => { - // verify - expect(res).equal(undefined); - expect(err).equal('[Error]: Please set the "type" field for your skill infrastructures.'); - done(); - }); - }); - - it('| loading deploy delegate error, expect error is called back', (done) => { - // setup - sinon.stub(DeployDelegate, 'load').callsArgWith(1, 'error'); - // call - skillInfraController.bootstrapInfrastructures(TEST_WORKSPACE, (err, res) => { - // verify - expect(res).equal(undefined); - expect(err).equal('error'); - done(); - }); - }); - - it('| loading deploy delegate pass but bootstrap fails, expect error is called back', (done) => { - // setup - const bootstrapStub = sinon.stub(); - const mockDeployDelegate = { - bootstrap: bootstrapStub, - invoke: () => 'invoke' - }; - sinon.stub(DeployDelegate, 'load').callsArgWith(1, null, mockDeployDelegate); - bootstrapStub.callsArgWith(1, 'error'); - // call - skillInfraController.bootstrapInfrastructures(TEST_WORKSPACE, (err, res) => { - // verify - expect(res).equal(undefined); - expect(err).equal('error'); - done(); - }); - }); + describe("# test class method: bootstrapInfrastructures", () => { + const skillInfraController = new SkillInfrastructureController(TEST_CONFIGURATION); - it('| loading deploy delegate and its bootstrap pass, expect config is called correctly in each step', (done) => { - // setup - const oldUserConfig = ResourcesConfig.getInstance().getSkillInfraUserConfig(TEST_PROFILE); - const bootstrapStub = sinon.stub(); - const mockDeployDelegate = { - bootstrap: bootstrapStub, - invoke: () => 'invoke' - }; - sinon.stub(DeployDelegate, 'load').callsArgWith(1, null, mockDeployDelegate); - bootstrapStub.callsArgWith(1, null, { userConfig: TEST_USER_CONFIG }); - // call - skillInfraController.bootstrapInfrastructures(TEST_WORKSPACE, (err, res) => { - // verify - expect(bootstrapStub.args[0][0].workspacePath).equal(TEST_WORKSPACE); - expect(bootstrapStub.args[0][0].userConfig).equal(oldUserConfig); - expect(res).equal(undefined); - expect(err).equal(undefined); - expect(ResourcesConfig.getInstance().getSkillInfraUserConfig(TEST_PROFILE)).deep.equal(TEST_USER_CONFIG); - done(); - }); - }); + beforeEach(() => { + new ResourcesConfig(FIXTURE_RESOURCES_CONFIG_FILE_PATH); }); - describe('# test class method: deployInfrastructure', () => { - const TEST_DEPLOY_DELEGATE = {}; - const TEST_DEPLOY_RESULT = { - default: { - endpoint: { - url: 'TEST_URL' - }, - lastDeployHash: 'TEST_HASH', - deployState: {} - } - }; - const skillInfraController = new SkillInfrastructureController(TEST_CONFIGURATION); - - beforeEach(() => { - new ResourcesConfig(FIXTURE_RESOURCES_CONFIG_FILE_PATH); - }); - - afterEach(() => { - ResourcesConfig.dispose(); - sinon.restore(); - }); - - it('| prepare deploy delegate fails, expect error called back', (done) => { - // setup - sinon.stub(DeployDelegate, 'load').callsArgWith(1, 'error'); - // call - skillInfraController.deployInfrastructure((err, res) => { - // verify - expect(res).equal(undefined); - expect(err).equal('error'); - done(); - }); - }); + afterEach(() => { + ResourcesConfig.dispose(); + sinon.restore(); + }); - it('| deploy infra to all regions fails, expect error called back', (done) => { - // setup - sinon.stub(DeployDelegate, 'load').callsArgWith(1, null, TEST_DEPLOY_DELEGATE); - sinon.stub(SkillInfrastructureController.prototype, 'deployInfraToAllRegions').callsArgWith(1, 'error'); - // call - skillInfraController.deployInfrastructure((err, res) => { - // verify - expect(res).equal(undefined); - expect(err).equal('error'); - done(); - }); - }); + it("| skill infrastructures infra type not set, expect error is called back", (done) => { + // setup + ResourcesConfig.getInstance().setSkillInfraType(TEST_PROFILE, " "); + // call + skillInfraController.bootstrapInfrastructures(TEST_WORKSPACE, (err, res) => { + // verify + expect(res).equal(undefined); + expect(err).equal('[Error]: Please set the "type" field for your skill infrastructures.'); + done(); + }); + }); - it('| deploy to all regions passes but update skill manifest after deploy fails, expect error called back', (done) => { - // setup - sinon.stub(DeployDelegate, 'load').callsArgWith(1, null, TEST_DEPLOY_DELEGATE); - sinon.stub(SkillInfrastructureController.prototype, 'deployInfraToAllRegions').callsArgWith(1, null, TEST_DEPLOY_RESULT); - sinon.stub(SkillInfrastructureController.prototype, 'updateSkillManifestWithDeployResult').callsArgWith(1, 'error'); - sinon.stub(fs, 'writeFileSync'); - // call - skillInfraController.deployInfrastructure((err, res) => { - // verify - expect(res).equal(undefined); - expect(err).equal('error'); - done(); - }); - }); + it("| loading deploy delegate error, expect error is called back", (done) => { + // setup + sinon.stub(DeployDelegate, "load").callsArgWith(1, "error"); + // call + skillInfraController.bootstrapInfrastructures(TEST_WORKSPACE, (err, res) => { + // verify + expect(res).equal(undefined); + expect(err).equal("error"); + done(); + }); + }); - it('| update resources config and update skill manifest after deploy pass, expect no error called back', (done) => { - // setup - sinon.stub(DeployDelegate, 'load').callsArgWith(1, null, TEST_DEPLOY_DELEGATE); - sinon.stub(SkillInfrastructureController.prototype, 'deployInfraToAllRegions').callsArgWith(1, null, TEST_DEPLOY_RESULT); - sinon.stub(SkillInfrastructureController.prototype, 'updateSkillManifestWithDeployResult').callsArgWith(1, null); - sinon.stub(fs, 'writeFileSync'); - // call - skillInfraController.deployInfrastructure((err, res) => { - // verify - expect(res).equal(undefined); - expect(err).equal(undefined); - done(); - }); - }); + it("| loading deploy delegate pass but bootstrap fails, expect error is called back", (done) => { + // setup + const bootstrapStub = sinon.stub(); + const mockDeployDelegate = { + bootstrap: bootstrapStub, + invoke: () => "invoke", + }; + sinon.stub(DeployDelegate, "load").callsArgWith(1, null, mockDeployDelegate); + bootstrapStub.callsArgWith(1, "error"); + // call + skillInfraController.bootstrapInfrastructures(TEST_WORKSPACE, (err, res) => { + // verify + expect(res).equal(undefined); + expect(err).equal("error"); + done(); + }); }); - describe('# test class method: deployInfraToAllRegions', () => { - const TEST_DD = {}; - const skillInfraController = new SkillInfrastructureController(TEST_CONFIGURATION); + it("| loading deploy delegate and its bootstrap pass, expect config is called correctly in each step", (done) => { + // setup + const oldUserConfig = ResourcesConfig.getInstance().getSkillInfraUserConfig(TEST_PROFILE); + const bootstrapStub = sinon.stub(); + const mockDeployDelegate = { + bootstrap: bootstrapStub, + invoke: () => "invoke", + }; + sinon.stub(DeployDelegate, "load").callsArgWith(1, null, mockDeployDelegate); + bootstrapStub.callsArgWith(1, null, {userConfig: TEST_USER_CONFIG}); + // call + skillInfraController.bootstrapInfrastructures(TEST_WORKSPACE, (err, res) => { + // verify + expect(bootstrapStub.args[0][0].workspacePath).equal(TEST_WORKSPACE); + expect(bootstrapStub.args[0][0].userConfig).equal(oldUserConfig); + expect(res).equal(undefined); + expect(err).equal(undefined); + expect(ResourcesConfig.getInstance().getSkillInfraUserConfig(TEST_PROFILE)).deep.equal(TEST_USER_CONFIG); + done(); + }); + }); + }); + + describe("# test class method: deployInfrastructure", () => { + const TEST_DEPLOY_DELEGATE = {}; + const TEST_DEPLOY_RESULT = { + default: { + endpoint: { + url: "TEST_URL", + }, + lastDeployHash: "TEST_HASH", + deployState: {}, + }, + }; + const skillInfraController = new SkillInfrastructureController(TEST_CONFIGURATION); - beforeEach(() => { - new ResourcesConfig(FIXTURE_RESOURCES_CONFIG_FILE_PATH); - new Manifest(FIXTURE_MANIFEST_FILE_PATH); - TEST_DD.validateDeployDelegateResponse = sinon.stub(); - }); + beforeEach(() => { + new ResourcesConfig(FIXTURE_RESOURCES_CONFIG_FILE_PATH); + }); - afterEach(() => { - ResourcesConfig.dispose(); - Manifest.dispose(); - sinon.restore(); - }); + afterEach(() => { + ResourcesConfig.dispose(); + sinon.restore(); + }); - it('| skill name failed to parse, expect error called back', (done) => { - // setup - Manifest.getInstance().setSkillName('中文 '); - sinon.stub(path, 'basename').returns('中文 '); - // call - skillInfraController.deployInfraToAllRegions(TEST_DD, (err, res) => { - // verify - expect(res).equal(undefined); - expect(err).equal('[Error]: Failed to parse the skill name used to decide the CloudFormation stack name. ' - + 'Please make sure your skill name or skill project folder basename contains alphanumeric characters.'); - done(); - }); - }); + it("| prepare deploy delegate fails, expect error called back", (done) => { + // setup + sinon.stub(DeployDelegate, "load").callsArgWith(1, "error"); + // call + skillInfraController.deployInfrastructure((err, res) => { + // verify + expect(res).equal(undefined); + expect(err).equal("error"); + done(); + }); + }); - it('| code does not have any region, expect error called back', (done) => { - // setup - sinon.stub(ResourcesConfig.prototype, 'getCodeRegions').returns([]); - // call - skillInfraController.deployInfraToAllRegions(TEST_DD, (err, res) => { - // verify - expect(res).equal(undefined); - expect(err).equal('[Warn]: Skip the infrastructure deployment, as the "code" field has not been set in the resources config file.'); - done(); - }); - }); + it("| deploy infra to all regions fails, expect error called back", (done) => { + // setup + sinon.stub(DeployDelegate, "load").callsArgWith(1, null, TEST_DEPLOY_DELEGATE); + sinon.stub(SkillInfrastructureController.prototype, "deployInfraToAllRegions").callsArgWith(1, "error"); + // call + skillInfraController.deployInfrastructure((err, res) => { + // verify + expect(res).equal(undefined); + expect(err).equal("error"); + done(); + }); + }); - it('| start multi-tasks fails, expect error called back', (done) => { - // setup - sinon.stub(MultiTasksView.prototype, 'loadTask'); - sinon.stub(MultiTasksView.prototype, 'start').callsArgWith(0, { error: 'error' }); - // call - skillInfraController.deployInfraToAllRegions(TEST_DD, (err, res) => { - // verify - expect(res).equal(undefined); - expect(err).equal('error'); - expect(MultiTasksView.prototype.loadTask.callCount).equal(3); - expect(MultiTasksView.prototype.loadTask.args[0][1]).equal('Deploy Alexa skill infrastructure for region "default"'); - expect(MultiTasksView.prototype.loadTask.args[0][2]).equal('default'); - expect(MultiTasksView.prototype.loadTask.args[1][1]).equal('Deploy Alexa skill infrastructure for region "NA"'); - expect(MultiTasksView.prototype.loadTask.args[1][2]).equal('NA'); - expect(MultiTasksView.prototype.loadTask.args[2][1]).equal('Deploy Alexa skill infrastructure for region "EU"'); - expect(MultiTasksView.prototype.loadTask.args[2][2]).equal('EU'); - done(); - }); - }); + it("| deploy to all regions passes but update skill manifest after deploy fails, expect error called back", (done) => { + // setup + sinon.stub(DeployDelegate, "load").callsArgWith(1, null, TEST_DEPLOY_DELEGATE); + sinon.stub(SkillInfrastructureController.prototype, "deployInfraToAllRegions").callsArgWith(1, null, TEST_DEPLOY_RESULT); + sinon.stub(SkillInfrastructureController.prototype, "updateSkillManifestWithDeployResult").callsArgWith(1, "error"); + sinon.stub(fs, "writeFileSync"); + // call + skillInfraController.deployInfrastructure((err, res) => { + // verify + expect(res).equal(undefined); + expect(err).equal("error"); + done(); + }); + }); - it('| start multi-tasks fails partially, expect error called back and state updated', (done) => { - // setup - sinon.stub(MultiTasksView.prototype, 'loadTask'); - sinon.stub(MultiTasksView.prototype, 'start').callsArgWith(0, { error: 'error', partialResult: { NA: 'partial' } }); - sinon.stub(SkillInfrastructureController.prototype, '_updateResourcesConfig'); - // call - skillInfraController.deployInfraToAllRegions(TEST_DD, (err, res) => { - // verify - expect(res).equal(undefined); - expect(err).equal('error'); - expect(SkillInfrastructureController.prototype._updateResourcesConfig.args[0][1]).deep.equal({ NA: 'partial' }); - done(); - }); - }); + it("| update resources config and update skill manifest after deploy pass, expect no error called back", (done) => { + // setup + sinon.stub(DeployDelegate, "load").callsArgWith(1, null, TEST_DEPLOY_DELEGATE); + sinon.stub(SkillInfrastructureController.prototype, "deployInfraToAllRegions").callsArgWith(1, null, TEST_DEPLOY_RESULT); + sinon.stub(SkillInfrastructureController.prototype, "updateSkillManifestWithDeployResult").callsArgWith(1, null); + sinon.stub(fs, "writeFileSync"); + // call + skillInfraController.deployInfrastructure((err, res) => { + // verify + expect(res).equal(undefined); + expect(err).equal(undefined); + done(); + }); + }); + }); - it('| deploy delegate validate response fails, expect error called back', (done) => { - // setup - sinon.stub(MultiTasksView.prototype, 'loadTask'); - sinon.stub(MultiTasksView.prototype, 'start').callsArgWith(0); - TEST_DD.validateDeployDelegateResponse.throws(new Error('error')); - // call - skillInfraController.deployInfraToAllRegions(TEST_DD, (err, res) => { - // verify - expect(res).equal(undefined); - expect(err.message).equal('error'); - done(); - }); - }); + describe("# test class method: deployInfraToAllRegions", () => { + const TEST_DD = {}; + const skillInfraController = new SkillInfrastructureController(TEST_CONFIGURATION); - it('| deploy infra to all regions pass, expect no error called back', (done) => { - // setup - sinon.stub(SkillInfrastructureController.prototype, '_deployInfraByRegion'); - sinon.stub(SkillInfrastructureController.prototype, '_updateResourcesConfig'); - sinon.stub(MultiTasksView.prototype, 'loadTask').callsArgWith(0); - sinon.stub(MultiTasksView.prototype, 'start').callsArgWith(0, null, {}); - // call - skillInfraController.deployInfraToAllRegions(TEST_DD, (err, res) => { - // verify - expect(res).deep.equal({}); - expect(err).equal(null); - expect(MultiTasksView.prototype.loadTask.callCount).equal(3); - expect(MultiTasksView.prototype.loadTask.args[0][1]).equal('Deploy Alexa skill infrastructure for region "default"'); - expect(MultiTasksView.prototype.loadTask.args[0][2]).equal('default'); - expect(MultiTasksView.prototype.loadTask.args[1][1]).equal('Deploy Alexa skill infrastructure for region "NA"'); - expect(MultiTasksView.prototype.loadTask.args[1][2]).equal('NA'); - expect(MultiTasksView.prototype.loadTask.args[2][1]).equal('Deploy Alexa skill infrastructure for region "EU"'); - expect(MultiTasksView.prototype.loadTask.args[2][2]).equal('EU'); - done(); - }); - }); + beforeEach(() => { + new ResourcesConfig(FIXTURE_RESOURCES_CONFIG_FILE_PATH); + new Manifest(FIXTURE_MANIFEST_FILE_PATH); + TEST_DD.validateDeployDelegateResponse = sinon.stub(); + }); - it('| deploy infra to all regions pass with skip, expect no error called back and skipped result updated', (done) => { - // setup - sinon.stub(SkillInfrastructureController.prototype, '_deployInfraByRegion'); - sinon.stub(SkillInfrastructureController.prototype, '_updateResourcesConfig'); - sinon.stub(MultiTasksView.prototype, 'loadTask'); - sinon.stub(MultiTasksView.prototype, 'start').callsArgWith(0, null, { - default: 'success', - NA: { isDeploySkipped: true, deployRegion: 'default' }, - EU: 'success' - }); - // call - skillInfraController.deployInfraToAllRegions(TEST_DD, (err, res) => { - // verify - expect(res).deep.equal({ default: 'success', NA: 'success', EU: 'success' }); - expect(err).equal(null); - done(); - }); - }); + afterEach(() => { + ResourcesConfig.dispose(); + Manifest.dispose(); + sinon.restore(); + }); - it('| deploy infra to all regions fails partially with skip, expect error called back and skipped result updated', (done) => { - // setup - sinon.stub(SkillInfrastructureController.prototype, '_deployInfraByRegion'); - sinon.stub(SkillInfrastructureController.prototype, '_updateResourcesConfig'); - sinon.stub(MultiTasksView.prototype, 'loadTask'); - sinon.stub(MultiTasksView.prototype, 'start').callsArgWith(0, { - error: 'error', - partialResult: { - default: 'partial', - NA: { isDeploySkipped: true, deployRegion: 'default' }, - EU: 'partial' - } - }); - // call - skillInfraController.deployInfraToAllRegions(TEST_DD, (err, res) => { - // verify - expect(res).equal(undefined); - expect(err).equal('error'); - expect(SkillInfrastructureController.prototype._updateResourcesConfig.args[0][1]).deep.equal({ - default: 'partial', - NA: 'partial', - EU: 'partial' - }); - done(); - }); - }); + it("| skill name failed to parse, expect error called back", (done) => { + // setup + Manifest.getInstance().setSkillName("中文 "); + sinon.stub(path, "basename").returns("中文 "); + // call + skillInfraController.deployInfraToAllRegions(TEST_DD, (err, res) => { + // verify + expect(res).equal(undefined); + expect(err).equal( + "[Error]: Failed to parse the skill name used to decide the CloudFormation stack name. " + + "Please make sure your skill name or skill project folder basename contains alphanumeric characters.", + ); + done(); + }); }); - describe('# test class method: updateSkillManifestWithDeployResult', () => { - const TEST_DEPLOY_RESULT = { - default: { - endpoint: { - url: 'TEST_URL1' - } - }, - EU: { - endpoint: { - url: 'TEST_URL2' - } - } - }; - const skillInfraController = new SkillInfrastructureController(TEST_CONFIGURATION); - - beforeEach(() => { - new ResourcesConfig(FIXTURE_RESOURCES_CONFIG_FILE_PATH); - new Manifest(FIXTURE_MANIFEST_FILE_PATH); - sinon.stub(fse, 'writeFileSync'); - }); + it("| code does not have any region, expect error called back", (done) => { + // setup + sinon.stub(ResourcesConfig.prototype, "getCodeRegions").returns([]); + // call + skillInfraController.deployInfraToAllRegions(TEST_DD, (err, res) => { + // verify + expect(res).equal(undefined); + expect(err).equal('[Warn]: Skip the infrastructure deployment, as the "code" field has not been set in the resources config file.'); + done(); + }); + }); - afterEach(() => { - ResourcesConfig.dispose(); - Manifest.dispose(); - sinon.restore(); - }); + it("| start multi-tasks fails, expect error called back", (done) => { + // setup + sinon.stub(MultiTasksView.prototype, "loadTask"); + sinon.stub(MultiTasksView.prototype, "start").callsArgWith(0, {error: "error"}); + // call + skillInfraController.deployInfraToAllRegions(TEST_DD, (err, res) => { + // verify + expect(res).equal(undefined); + expect(err).equal("error"); + expect(MultiTasksView.prototype.loadTask.callCount).equal(3); + expect(MultiTasksView.prototype.loadTask.args[0][1]).equal('Deploy Alexa skill infrastructure for region "default"'); + expect(MultiTasksView.prototype.loadTask.args[0][2]).equal("default"); + expect(MultiTasksView.prototype.loadTask.args[1][1]).equal('Deploy Alexa skill infrastructure for region "NA"'); + expect(MultiTasksView.prototype.loadTask.args[1][2]).equal("NA"); + expect(MultiTasksView.prototype.loadTask.args[2][1]).equal('Deploy Alexa skill infrastructure for region "EU"'); + expect(MultiTasksView.prototype.loadTask.args[2][2]).equal("EU"); + done(); + }); + }); - it('| manifest update correctly but hash fails, expect error called back', (done) => { - // setup - sinon.stub(AuthorizationController.prototype, 'tokenRefreshAndRead').callsArgWith(1); - sinon.stub(hashUtils, 'getHash').callsArgWith(1, 'hash error'); - // call - skillInfraController.updateSkillManifestWithDeployResult(TEST_DEPLOY_RESULT, (err, res) => { - // verify - expect(res).equal(undefined); - expect(err).equal('hash error'); - expect(hashUtils.getHash.args[0][0]).equal(ResourcesConfig.getInstance().getSkillMetaSrc(TEST_PROFILE)); - expect(Manifest.getInstance().getApisEndpointByDomainRegion('custom', 'default').url).equal('TEST_URL1'); - expect(Manifest.getInstance().getApisEndpointByDomainRegion('custom', 'EU').url).equal('TEST_URL2'); - done(); - }); - }); + it("| start multi-tasks fails partially, expect error called back and state updated", (done) => { + // setup + sinon.stub(MultiTasksView.prototype, "loadTask"); + sinon.stub(MultiTasksView.prototype, "start").callsArgWith(0, {error: "error", partialResult: {NA: "partial"}}); + sinon.stub(SkillInfrastructureController.prototype, "_updateResourcesConfig"); + // call + skillInfraController.deployInfraToAllRegions(TEST_DD, (err, res) => { + // verify + expect(res).equal(undefined); + expect(err).equal("error"); + expect(SkillInfrastructureController.prototype._updateResourcesConfig.args[0][1]).deep.equal({NA: "partial"}); + done(); + }); + }); - it('| manifest update correctly but hash is same, expect called back with nothing', (done) => { - // setup - ResourcesConfig.getInstance().setSkillMetaLastDeployHash(TEST_PROFILE, 'TEST_HASH'); - sinon.stub(AuthorizationController.prototype, 'tokenRefreshAndRead').callsArgWith(1); - sinon.stub(hashUtils, 'getHash').callsArgWith(1, null, 'TEST_HASH'); - // call - skillInfraController.updateSkillManifestWithDeployResult(TEST_DEPLOY_RESULT, (err, res) => { - // verify - expect(res).equal(undefined); - expect(err).equal(undefined); - expect(Manifest.getInstance().getApisEndpointByDomainRegion('custom', 'default').url).equal('TEST_URL1'); - expect(Manifest.getInstance().getApisEndpointByDomainRegion('custom', 'EU').url).equal('TEST_URL2'); - done(); - }); - }); + it("| deploy delegate validate response fails, expect error called back", (done) => { + // setup + sinon.stub(MultiTasksView.prototype, "loadTask"); + sinon.stub(MultiTasksView.prototype, "start").callsArgWith(0); + TEST_DD.validateDeployDelegateResponse.throws(new Error("error")); + // call + skillInfraController.deployInfraToAllRegions(TEST_DD, (err, res) => { + // verify + expect(res).equal(undefined); + expect(err.message).equal("error"); + done(); + }); + }); - it('| manifest update correctly but skill manifest update fails, expect update error called back', (done) => { - // setup - sinon.stub(AuthorizationController.prototype, 'tokenRefreshAndRead').callsArgWith(1); - sinon.stub(hashUtils, 'getHash').callsArgWith(1, null, 'TEST_HASH'); - sinon.stub(SkillInfrastructureController.prototype, '_ensureSkillManifestGotUpdated').callsArgWith(0, 'update error'); - // call - skillInfraController.updateSkillManifestWithDeployResult(TEST_DEPLOY_RESULT, (err, res) => { - // verify - expect(res).equal(undefined); - expect(err).equal('update error'); - expect(Manifest.getInstance().getApisEndpointByDomainRegion('custom', 'default').url).equal('TEST_URL1'); - expect(Manifest.getInstance().getApisEndpointByDomainRegion('custom', 'EU').url).equal('TEST_URL2'); - done(); - }); - }); + it("| deploy infra to all regions pass, expect no error called back", (done) => { + // setup + sinon.stub(SkillInfrastructureController.prototype, "_deployInfraByRegion"); + sinon.stub(SkillInfrastructureController.prototype, "_updateResourcesConfig"); + sinon.stub(MultiTasksView.prototype, "loadTask").callsArgWith(0); + sinon.stub(MultiTasksView.prototype, "start").callsArgWith(0, null, {}); + // call + skillInfraController.deployInfraToAllRegions(TEST_DD, (err, res) => { + // verify + expect(res).deep.equal({}); + expect(err).equal(null); + expect(MultiTasksView.prototype.loadTask.callCount).equal(3); + expect(MultiTasksView.prototype.loadTask.args[0][1]).equal('Deploy Alexa skill infrastructure for region "default"'); + expect(MultiTasksView.prototype.loadTask.args[0][2]).equal("default"); + expect(MultiTasksView.prototype.loadTask.args[1][1]).equal('Deploy Alexa skill infrastructure for region "NA"'); + expect(MultiTasksView.prototype.loadTask.args[1][2]).equal("NA"); + expect(MultiTasksView.prototype.loadTask.args[2][1]).equal('Deploy Alexa skill infrastructure for region "EU"'); + expect(MultiTasksView.prototype.loadTask.args[2][2]).equal("EU"); + done(); + }); + }); - it('| manifest update correctly, expect success message and new hash set', (done) => { - // setup - sinon.stub(AuthorizationController.prototype, 'tokenRefreshAndRead').callsArgWith(1); - sinon.stub(hashUtils, 'getHash').callsArgWith(1, null, 'TEST_HASH'); - sinon.stub(SkillInfrastructureController.prototype, '_ensureSkillManifestGotUpdated').callsArgWith(0); - const setApisEndpointByDomainRegionSpy = sinon.spy(Manifest.prototype, 'setApisEndpointByDomainRegion'); - const setEventsEndpointByRegionSpy = sinon.spy(Manifest.prototype, 'setEventsEndpointByRegion'); - const setEventsPublicationsSpy = sinon.spy(Manifest.prototype, 'setEventsPublications'); - const setEventsSubscriptionsSpy = sinon.spy(Manifest.prototype, 'setEventsSubscriptions'); - // call - skillInfraController.updateSkillManifestWithDeployResult(TEST_DEPLOY_RESULT, (err, res) => { - // verify - expect(res).equal(undefined); - expect(err).equal(undefined); - expect(setApisEndpointByDomainRegionSpy.callCount).eq(4); - expect(setEventsEndpointByRegionSpy.callCount).eq(0); - expect(setEventsPublicationsSpy.callCount).eq(0); - expect(setEventsSubscriptionsSpy.callCount).eq(0); - expect(Manifest.getInstance().getApisEndpointByDomainRegion('custom', 'default').url).equal('TEST_URL1'); - expect(Manifest.getInstance().getApisEndpointByDomainRegion('custom', 'EU').url).equal('TEST_URL2'); - expect(ResourcesConfig.getInstance().getSkillMetaLastDeployHash(TEST_PROFILE)).equal('TEST_HASH'); - done(); - }); - }); + it("| deploy infra to all regions pass with skip, expect no error called back and skipped result updated", (done) => { + // setup + sinon.stub(SkillInfrastructureController.prototype, "_deployInfraByRegion"); + sinon.stub(SkillInfrastructureController.prototype, "_updateResourcesConfig"); + sinon.stub(MultiTasksView.prototype, "loadTask"); + sinon.stub(MultiTasksView.prototype, "start").callsArgWith(0, null, { + default: "success", + NA: {isDeploySkipped: true, deployRegion: "default"}, + EU: "success", + }); + // call + skillInfraController.deployInfraToAllRegions(TEST_DD, (err, res) => { + // verify + expect(res).deep.equal({default: "success", NA: "success", EU: "success"}); + expect(err).equal(null); + done(); + }); + }); - it('| manifest update correctly with events endpoint only, expect success message and new hash set', (done) => { - // setup - sinon.stub(AuthorizationController.prototype, 'tokenRefreshAndRead').callsArgWith(1); - sinon.stub(hashUtils, 'getHash').callsArgWith(1, null, 'TEST_HASH'); - sinon.stub(SkillInfrastructureController.prototype, '_ensureSkillManifestGotUpdated').callsArgWith(0); - sinon.stub(ResourcesConfig.prototype, 'getSkillEvents').returns({}); - const setApisEndpointByDomainRegionSpy = sinon.spy(Manifest.prototype, 'setApisEndpointByDomainRegion'); - const setEventsEndpointByRegionSpy = sinon.spy(Manifest.prototype, 'setEventsEndpointByRegion'); - const setEventsPublicationsSpy = sinon.spy(Manifest.prototype, 'setEventsPublications'); - const setEventsSubscriptionsSpy = sinon.spy(Manifest.prototype, 'setEventsSubscriptions'); - // call - skillInfraController.updateSkillManifestWithDeployResult(TEST_DEPLOY_RESULT, (err, res) => { - // verify - expect(res).equal(undefined); - expect(err).equal(undefined); - expect(setApisEndpointByDomainRegionSpy.callCount).eq(4); - expect(setEventsEndpointByRegionSpy.callCount).eq(2); - expect(setEventsPublicationsSpy.callCount).eq(0); - expect(setEventsSubscriptionsSpy.callCount).eq(0); - expect(Manifest.getInstance().getApisEndpointByDomainRegion('custom', 'default').url).equal('TEST_URL1'); - expect(Manifest.getInstance().getApisEndpointByDomainRegion('custom', 'EU').url).equal('TEST_URL2'); - expect(Manifest.getInstance().getEventsEndpointByRegion('default').url).equal('TEST_URL1'); - expect(Manifest.getInstance().getEventsEndpointByRegion('EU').url).equal('TEST_URL2'); - expect(ResourcesConfig.getInstance().getSkillMetaLastDeployHash(TEST_PROFILE)).equal('TEST_HASH'); - done(); - }); - }); + it("| deploy infra to all regions fails partially with skip, expect error called back and skipped result updated", (done) => { + // setup + sinon.stub(SkillInfrastructureController.prototype, "_deployInfraByRegion"); + sinon.stub(SkillInfrastructureController.prototype, "_updateResourcesConfig"); + sinon.stub(MultiTasksView.prototype, "loadTask"); + sinon.stub(MultiTasksView.prototype, "start").callsArgWith(0, { + error: "error", + partialResult: { + default: "partial", + NA: {isDeploySkipped: true, deployRegion: "default"}, + EU: "partial", + }, + }); + // call + skillInfraController.deployInfraToAllRegions(TEST_DD, (err, res) => { + // verify + expect(res).equal(undefined); + expect(err).equal("error"); + expect(SkillInfrastructureController.prototype._updateResourcesConfig.args[0][1]).deep.equal({ + default: "partial", + NA: "partial", + EU: "partial", + }); + done(); + }); + }); + }); + + describe("# test class method: updateSkillManifestWithDeployResult", () => { + const TEST_DEPLOY_RESULT = { + default: { + endpoint: { + url: "TEST_URL1", + }, + }, + EU: { + endpoint: { + url: "TEST_URL2", + }, + }, + }; + const skillInfraController = new SkillInfrastructureController(TEST_CONFIGURATION); - it('| manifest update correctly with events properties, expect success message and new hash set', (done) => { - // setup - sinon.stub(AuthorizationController.prototype, 'tokenRefreshAndRead').callsArgWith(1); - sinon.stub(hashUtils, 'getHash').callsArgWith(1, null, 'TEST_HASH'); - sinon.stub(SkillInfrastructureController.prototype, '_ensureSkillManifestGotUpdated').callsArgWith(0); - sinon.stub(ResourcesConfig.prototype, 'getSkillEvents').returns({ - publications: ["TEST_PUBLICATION"], - subscriptions: ["TEST_SUBSCRIPTION"] - }); - const setApisEndpointByDomainRegionSpy = sinon.spy(Manifest.prototype, 'setApisEndpointByDomainRegion'); - const setEventsEndpointByRegionSpy = sinon.spy(Manifest.prototype, 'setEventsEndpointByRegion'); - const setEventsPublicationsSpy = sinon.spy(Manifest.prototype, 'setEventsPublications'); - const setEventsSubscriptionsSpy = sinon.spy(Manifest.prototype, 'setEventsSubscriptions'); - // call - skillInfraController.updateSkillManifestWithDeployResult(TEST_DEPLOY_RESULT, (err, res) => { - // verify - expect(res).equal(undefined); - expect(err).equal(undefined); - expect(setApisEndpointByDomainRegionSpy.callCount).eq(4); - expect(setEventsEndpointByRegionSpy.callCount).eq(2); - expect(setEventsPublicationsSpy.callCount).eq(1); - expect(setEventsSubscriptionsSpy.callCount).eq(1); - expect(Manifest.getInstance().getApisEndpointByDomainRegion('custom', 'default').url).equal('TEST_URL1'); - expect(Manifest.getInstance().getApisEndpointByDomainRegion('custom', 'EU').url).equal('TEST_URL2'); - expect(Manifest.getInstance().getEventsEndpointByRegion('default').url).equal('TEST_URL1'); - expect(Manifest.getInstance().getEventsEndpointByRegion('EU').url).equal('TEST_URL2'); - expect(Manifest.getInstance().getEventsPublications()[0].eventName).equal('TEST_PUBLICATION'); - expect(Manifest.getInstance().getEventsSubscriptions()[0].eventName).equal('TEST_SUBSCRIPTION'); - expect(ResourcesConfig.getInstance().getSkillMetaLastDeployHash(TEST_PROFILE)).equal('TEST_HASH'); - done(); - }); - }); + beforeEach(() => { + new ResourcesConfig(FIXTURE_RESOURCES_CONFIG_FILE_PATH); + new Manifest(FIXTURE_MANIFEST_FILE_PATH); + sinon.stub(fse, "writeFileSync"); + }); - it('| manifest update when target endpoints is not set, expect success message and new hash set', (done) => { - // setup - sinon.stub(AuthorizationController.prototype, 'tokenRefreshAndRead').callsArgWith(1); - sinon.stub(hashUtils, 'getHash').callsArgWith(1, null, 'TEST_HASH'); - sinon.stub(SkillInfrastructureController.prototype, '_ensureSkillManifestGotUpdated').callsArgWith(0); - sinon.stub(ResourcesConfig.prototype, 'getTargetEndpoints').returns([]); - const setApisEndpointByDomainRegionSpy = sinon.spy(Manifest.prototype, 'setApisEndpointByDomainRegion'); - const setEventsEndpointByRegionSpy = sinon.spy(Manifest.prototype, 'setEventsEndpointByRegion'); - const setEventsPublicationsSpy = sinon.spy(Manifest.prototype, 'setEventsPublications'); - const setEventsSubscriptionsSpy = sinon.spy(Manifest.prototype, 'setEventsSubscriptions'); - // call - skillInfraController.updateSkillManifestWithDeployResult(TEST_DEPLOY_RESULT, (err, res) => { - // verify - expect(res).equal(undefined); - expect(err).equal(undefined); - expect(setApisEndpointByDomainRegionSpy.callCount).eq(2); - expect(setEventsEndpointByRegionSpy.callCount).eq(0); - expect(setEventsPublicationsSpy.callCount).eq(0); - expect(setEventsSubscriptionsSpy.callCount).eq(0); - expect(Manifest.getInstance().getApisEndpointByDomainRegion('custom', 'default').url).equal('TEST_URL1'); - expect(Manifest.getInstance().getApisEndpointByDomainRegion('custom', 'EU').url).equal('TEST_URL2'); - expect(ResourcesConfig.getInstance().getSkillMetaLastDeployHash(TEST_PROFILE)).equal('TEST_HASH'); - done(); - }); - }); + afterEach(() => { + ResourcesConfig.dispose(); + Manifest.dispose(); + sinon.restore(); }); - describe('# test class method: _deployInfraByRegion', () => { - let TEST_REPORTER, TEST_DD; - const TEST_REGION = 'default'; - const TEST_SKILL_NAME = 'skillName'; - const TEST_DEPLOY_REGIONS = { TEST_REGION: 'deployRegion' }; - const TEST_HASH = 'hash'; - - const skillInfraController = new SkillInfrastructureController(TEST_CONFIGURATION); - - beforeEach(() => { - new ResourcesConfig(FIXTURE_RESOURCES_CONFIG_FILE_PATH); - sinon.stub(path, 'resolve').returns('base'); - sinon.stub(fse, 'statSync').returns({ - isDirectory: () => true - }); - TEST_REPORTER = {}; - TEST_DD = { - invoke: sinon.stub() - }; - }); + it("| manifest update correctly but hash fails, expect error called back", (done) => { + // setup + sinon.stub(AuthorizationController.prototype, "tokenRefreshAndRead").callsArgWith(1); + sinon.stub(hashUtils, "getHash").callsArgWith(1, "hash error"); + // call + skillInfraController.updateSkillManifestWithDeployResult(TEST_DEPLOY_RESULT, (err, res) => { + // verify + expect(res).equal(undefined); + expect(err).equal("hash error"); + expect(hashUtils.getHash.args[0][0]).equal(ResourcesConfig.getInstance().getSkillMetaSrc(TEST_PROFILE)); + expect(Manifest.getInstance().getApisEndpointByDomainRegion("custom", "default").url).equal("TEST_URL1"); + expect(Manifest.getInstance().getApisEndpointByDomainRegion("custom", "EU").url).equal("TEST_URL2"); + done(); + }); + }); - afterEach(() => { - ResourcesConfig.dispose(); - sinon.restore(); - }); + it("| manifest update correctly but hash is same, expect called back with nothing", (done) => { + // setup + ResourcesConfig.getInstance().setSkillMetaLastDeployHash(TEST_PROFILE, "TEST_HASH"); + sinon.stub(AuthorizationController.prototype, "tokenRefreshAndRead").callsArgWith(1); + sinon.stub(hashUtils, "getHash").callsArgWith(1, null, "TEST_HASH"); + // call + skillInfraController.updateSkillManifestWithDeployResult(TEST_DEPLOY_RESULT, (err, res) => { + // verify + expect(res).equal(undefined); + expect(err).equal(undefined); + expect(Manifest.getInstance().getApisEndpointByDomainRegion("custom", "default").url).equal("TEST_URL1"); + expect(Manifest.getInstance().getApisEndpointByDomainRegion("custom", "EU").url).equal("TEST_URL2"); + done(); + }); + }); - it('| get hash fails, expect error called back', (done) => { - // setup - sinon.stub(hashUtils, 'getHash').callsArgWith(1, 'hash error'); - // call - skillInfraController._deployInfraByRegion(TEST_REPORTER, TEST_DD, TEST_REGION, TEST_SKILL_NAME, TEST_DEPLOY_REGIONS, (err, res) => { - // verify - expect(res).equal(undefined); - expect(err).equal('hash error'); - done(); - }); - }); + it("| manifest update correctly but skill manifest update fails, expect update error called back", (done) => { + // setup + sinon.stub(AuthorizationController.prototype, "tokenRefreshAndRead").callsArgWith(1); + sinon.stub(hashUtils, "getHash").callsArgWith(1, null, "TEST_HASH"); + sinon.stub(SkillInfrastructureController.prototype, "_ensureSkillManifestGotUpdated").callsArgWith(0, "update error"); + // call + skillInfraController.updateSkillManifestWithDeployResult(TEST_DEPLOY_RESULT, (err, res) => { + // verify + expect(res).equal(undefined); + expect(err).equal("update error"); + expect(Manifest.getInstance().getApisEndpointByDomainRegion("custom", "default").url).equal("TEST_URL1"); + expect(Manifest.getInstance().getApisEndpointByDomainRegion("custom", "EU").url).equal("TEST_URL2"); + done(); + }); + }); - it('| deploy delegate invoke fails, expect error called back', (done) => { - // setup - sinon.stub(hashUtils, 'getHash').callsArgWith(1, null, TEST_HASH); - ResourcesConfig.getInstance().setCodeLastDeployHashByRegion(TEST_PROFILE, TEST_REGION, TEST_HASH); - TEST_DD.invoke.callsArgWith(2, 'invoke error'); - // call - skillInfraController._deployInfraByRegion(TEST_REPORTER, TEST_DD, TEST_REGION, TEST_SKILL_NAME, TEST_DEPLOY_REGIONS, (err, res) => { - // verify - expect(res).equal(undefined); - expect(err).equal('invoke error'); - expect(TEST_DD.invoke.args[0][1].code.isCodeModified).equal(false); - done(); - }); - }); + it("| manifest update correctly, expect success message and new hash set", (done) => { + // setup + sinon.stub(AuthorizationController.prototype, "tokenRefreshAndRead").callsArgWith(1); + sinon.stub(hashUtils, "getHash").callsArgWith(1, null, "TEST_HASH"); + sinon.stub(SkillInfrastructureController.prototype, "_ensureSkillManifestGotUpdated").callsArgWith(0); + const setApisEndpointByDomainRegionSpy = sinon.spy(Manifest.prototype, "setApisEndpointByDomainRegion"); + const setEventsEndpointByRegionSpy = sinon.spy(Manifest.prototype, "setEventsEndpointByRegion"); + const setEventsPublicationsSpy = sinon.spy(Manifest.prototype, "setEventsPublications"); + const setEventsSubscriptionsSpy = sinon.spy(Manifest.prototype, "setEventsSubscriptions"); + // call + skillInfraController.updateSkillManifestWithDeployResult(TEST_DEPLOY_RESULT, (err, res) => { + // verify + expect(res).equal(undefined); + expect(err).equal(undefined); + expect(setApisEndpointByDomainRegionSpy.callCount).eq(4); + expect(setEventsEndpointByRegionSpy.callCount).eq(0); + expect(setEventsPublicationsSpy.callCount).eq(0); + expect(setEventsSubscriptionsSpy.callCount).eq(0); + expect(Manifest.getInstance().getApisEndpointByDomainRegion("custom", "default").url).equal("TEST_URL1"); + expect(Manifest.getInstance().getApisEndpointByDomainRegion("custom", "EU").url).equal("TEST_URL2"); + expect(ResourcesConfig.getInstance().getSkillMetaLastDeployHash(TEST_PROFILE)).equal("TEST_HASH"); + done(); + }); + }); - it('| deploy delegate invoke passes with isCodeDeployed true, expect invoke result called back with currentHash', (done) => { - // setup - sinon.stub(hashUtils, 'getHash').callsArgWith(1, null, TEST_HASH); - TEST_DD.invoke.callsArgWith(2, null, { - isCodeDeployed: true, - isAllStepSuccess: true - }); - // call - skillInfraController._deployInfraByRegion(TEST_REPORTER, TEST_DD, TEST_REGION, TEST_SKILL_NAME, TEST_DEPLOY_REGIONS, (err, res) => { - // verify - expect(res).deep.equal({ - isCodeDeployed: true, - isAllStepSuccess: true, - lastDeployHash: TEST_HASH - }); - expect(err).equal(null); - done(); - }); - }); + it("| manifest update correctly with events endpoint only, expect success message and new hash set", (done) => { + // setup + sinon.stub(AuthorizationController.prototype, "tokenRefreshAndRead").callsArgWith(1); + sinon.stub(hashUtils, "getHash").callsArgWith(1, null, "TEST_HASH"); + sinon.stub(SkillInfrastructureController.prototype, "_ensureSkillManifestGotUpdated").callsArgWith(0); + sinon.stub(ResourcesConfig.prototype, "getSkillEvents").returns({}); + const setApisEndpointByDomainRegionSpy = sinon.spy(Manifest.prototype, "setApisEndpointByDomainRegion"); + const setEventsEndpointByRegionSpy = sinon.spy(Manifest.prototype, "setEventsEndpointByRegion"); + const setEventsPublicationsSpy = sinon.spy(Manifest.prototype, "setEventsPublications"); + const setEventsSubscriptionsSpy = sinon.spy(Manifest.prototype, "setEventsSubscriptions"); + // call + skillInfraController.updateSkillManifestWithDeployResult(TEST_DEPLOY_RESULT, (err, res) => { + // verify + expect(res).equal(undefined); + expect(err).equal(undefined); + expect(setApisEndpointByDomainRegionSpy.callCount).eq(4); + expect(setEventsEndpointByRegionSpy.callCount).eq(2); + expect(setEventsPublicationsSpy.callCount).eq(0); + expect(setEventsSubscriptionsSpy.callCount).eq(0); + expect(Manifest.getInstance().getApisEndpointByDomainRegion("custom", "default").url).equal("TEST_URL1"); + expect(Manifest.getInstance().getApisEndpointByDomainRegion("custom", "EU").url).equal("TEST_URL2"); + expect(Manifest.getInstance().getEventsEndpointByRegion("default").url).equal("TEST_URL1"); + expect(Manifest.getInstance().getEventsEndpointByRegion("EU").url).equal("TEST_URL2"); + expect(ResourcesConfig.getInstance().getSkillMetaLastDeployHash(TEST_PROFILE)).equal("TEST_HASH"); + done(); + }); + }); - it('| deploy delegate invoke passes, expect invoke result called back', (done) => { - // setup - sinon.stub(hashUtils, 'getHash').callsArgWith(1, null, TEST_HASH); - TEST_DD.invoke.callsArgWith(2, null, { - isCodeDeployed: false, - isAllStepSuccess: true, - resultMessage: 'success', - deployState: {} - }); - // call - skillInfraController._deployInfraByRegion(TEST_REPORTER, TEST_DD, TEST_REGION, TEST_SKILL_NAME, TEST_DEPLOY_REGIONS, (err, res) => { - // verify - expect(res).deep.equal({ - isCodeDeployed: false, - isAllStepSuccess: true, - resultMessage: 'success', - deployState: {} - }); - expect(err).equal(null); - done(); - }); - }); + it("| manifest update correctly with events properties, expect success message and new hash set", (done) => { + // setup + sinon.stub(AuthorizationController.prototype, "tokenRefreshAndRead").callsArgWith(1); + sinon.stub(hashUtils, "getHash").callsArgWith(1, null, "TEST_HASH"); + sinon.stub(SkillInfrastructureController.prototype, "_ensureSkillManifestGotUpdated").callsArgWith(0); + sinon.stub(ResourcesConfig.prototype, "getSkillEvents").returns({ + publications: ["TEST_PUBLICATION"], + subscriptions: ["TEST_SUBSCRIPTION"], + }); + const setApisEndpointByDomainRegionSpy = sinon.spy(Manifest.prototype, "setApisEndpointByDomainRegion"); + const setEventsEndpointByRegionSpy = sinon.spy(Manifest.prototype, "setEventsEndpointByRegion"); + const setEventsPublicationsSpy = sinon.spy(Manifest.prototype, "setEventsPublications"); + const setEventsSubscriptionsSpy = sinon.spy(Manifest.prototype, "setEventsSubscriptions"); + // call + skillInfraController.updateSkillManifestWithDeployResult(TEST_DEPLOY_RESULT, (err, res) => { + // verify + expect(res).equal(undefined); + expect(err).equal(undefined); + expect(setApisEndpointByDomainRegionSpy.callCount).eq(4); + expect(setEventsEndpointByRegionSpy.callCount).eq(2); + expect(setEventsPublicationsSpy.callCount).eq(1); + expect(setEventsSubscriptionsSpy.callCount).eq(1); + expect(Manifest.getInstance().getApisEndpointByDomainRegion("custom", "default").url).equal("TEST_URL1"); + expect(Manifest.getInstance().getApisEndpointByDomainRegion("custom", "EU").url).equal("TEST_URL2"); + expect(Manifest.getInstance().getEventsEndpointByRegion("default").url).equal("TEST_URL1"); + expect(Manifest.getInstance().getEventsEndpointByRegion("EU").url).equal("TEST_URL2"); + expect(Manifest.getInstance().getEventsPublications()[0].eventName).equal("TEST_PUBLICATION"); + expect(Manifest.getInstance().getEventsSubscriptions()[0].eventName).equal("TEST_SUBSCRIPTION"); + expect(ResourcesConfig.getInstance().getSkillMetaLastDeployHash(TEST_PROFILE)).equal("TEST_HASH"); + done(); + }); + }); - it('| deploy delegate invoke skipped, expect invoke result called back', (done) => { - // setup - sinon.stub(hashUtils, 'getHash').callsArgWith(1, null, TEST_HASH); - TEST_REPORTER.skipTask = sinon.stub(); - TEST_DD.invoke.callsArgWith(2, null, { - isDeploySkipped: true, - resultMessage: 'skipped', - deployRegion: 'deployRegion', - deployState: {} - }); - // call - skillInfraController._deployInfraByRegion(TEST_REPORTER, TEST_DD, TEST_REGION, TEST_SKILL_NAME, TEST_DEPLOY_REGIONS, (err, res) => { - // verify - expect(res).deep.equal({ - isDeploySkipped: true, - resultMessage: 'skipped', - deployRegion: 'deployRegion', - deployState: {} - }); - expect(err).equal(null); - expect(TEST_REPORTER.skipTask.calledOnce).equal(true); - expect(TEST_REPORTER.skipTask.args[0][0]).equal('skipped'); - done(); - }); - }); + it("| manifest update when target endpoints is not set, expect success message and new hash set", (done) => { + // setup + sinon.stub(AuthorizationController.prototype, "tokenRefreshAndRead").callsArgWith(1); + sinon.stub(hashUtils, "getHash").callsArgWith(1, null, "TEST_HASH"); + sinon.stub(SkillInfrastructureController.prototype, "_ensureSkillManifestGotUpdated").callsArgWith(0); + sinon.stub(ResourcesConfig.prototype, "getTargetEndpoints").returns([]); + const setApisEndpointByDomainRegionSpy = sinon.spy(Manifest.prototype, "setApisEndpointByDomainRegion"); + const setEventsEndpointByRegionSpy = sinon.spy(Manifest.prototype, "setEventsEndpointByRegion"); + const setEventsPublicationsSpy = sinon.spy(Manifest.prototype, "setEventsPublications"); + const setEventsSubscriptionsSpy = sinon.spy(Manifest.prototype, "setEventsSubscriptions"); + // call + skillInfraController.updateSkillManifestWithDeployResult(TEST_DEPLOY_RESULT, (err, res) => { + // verify + expect(res).equal(undefined); + expect(err).equal(undefined); + expect(setApisEndpointByDomainRegionSpy.callCount).eq(2); + expect(setEventsEndpointByRegionSpy.callCount).eq(0); + expect(setEventsPublicationsSpy.callCount).eq(0); + expect(setEventsSubscriptionsSpy.callCount).eq(0); + expect(Manifest.getInstance().getApisEndpointByDomainRegion("custom", "default").url).equal("TEST_URL1"); + expect(Manifest.getInstance().getApisEndpointByDomainRegion("custom", "EU").url).equal("TEST_URL2"); + expect(ResourcesConfig.getInstance().getSkillMetaLastDeployHash(TEST_PROFILE)).equal("TEST_HASH"); + done(); + }); + }); + }); + + describe("# test class method: _deployInfraByRegion", () => { + let TEST_REPORTER, TEST_DD; + const TEST_REGION = "default"; + const TEST_SKILL_NAME = "skillName"; + const TEST_DEPLOY_REGIONS = {TEST_REGION: "deployRegion"}; + const TEST_HASH = "hash"; + + const skillInfraController = new SkillInfrastructureController(TEST_CONFIGURATION); + + beforeEach(() => { + new ResourcesConfig(FIXTURE_RESOURCES_CONFIG_FILE_PATH); + sinon.stub(path, "resolve").returns("base"); + sinon.stub(fse, "statSync").returns({ + isDirectory: () => true, + }); + TEST_REPORTER = {}; + TEST_DD = { + invoke: sinon.stub(), + }; + }); - it('| deploy delegate invoke partial succeed with reasons called back, expect invoke result called back along with the message', (done) => { - // setup - sinon.stub(hashUtils, 'getHash').callsArgWith(1, null, TEST_HASH); - TEST_DD.invoke.callsArgWith(2, null, { - isCodeDeployed: true, - isAllStepSuccess: false, - resultMessage: 'partial fail', - deployState: {} - }); - // call - skillInfraController._deployInfraByRegion(TEST_REPORTER, TEST_DD, TEST_REGION, TEST_SKILL_NAME, TEST_DEPLOY_REGIONS, (err, res) => { - // verify - expect(res).equal(undefined); - expect(err).deep.equal({ - message: 'partial fail', - context: { - isCodeDeployed: true, - isAllStepSuccess: false, - lastDeployHash: TEST_HASH, - resultMessage: 'partial fail', - deployState: {} - } - }); - done(); - }); - }); + afterEach(() => { + ResourcesConfig.dispose(); + sinon.restore(); }); - describe('# test class method: _updateResourcesConfig', () => { - let TEST_REGION_LIST, TEST_DEPLOY_RESULT; - - const skillInfraController = new SkillInfrastructureController(TEST_CONFIGURATION); - - beforeEach(() => { - TEST_REGION_LIST = ['default']; - TEST_DEPLOY_RESULT = { - default: { - endpoint: { - url: 'TEST_URL' - }, - lastDeployHash: 'TEST_HASH', - deployState: {} - } - }; - new ResourcesConfig(FIXTURE_RESOURCES_CONFIG_FILE_PATH); - sinon.stub(fse, 'writeFileSync'); - }); + it("| get hash fails, expect error called back", (done) => { + // setup + sinon.stub(hashUtils, "getHash").callsArgWith(1, "hash error"); + // call + skillInfraController._deployInfraByRegion(TEST_REPORTER, TEST_DD, TEST_REGION, TEST_SKILL_NAME, TEST_DEPLOY_REGIONS, (err, res) => { + // verify + expect(res).equal(undefined); + expect(err).equal("hash error"); + done(); + }); + }); - afterEach(() => { - ResourcesConfig.dispose(); - sinon.restore(); - }); + it("| deploy delegate invoke fails, expect error called back", (done) => { + // setup + sinon.stub(hashUtils, "getHash").callsArgWith(1, null, TEST_HASH); + ResourcesConfig.getInstance().setCodeLastDeployHashByRegion(TEST_PROFILE, TEST_REGION, TEST_HASH); + TEST_DD.invoke.callsArgWith(2, "invoke error"); + // call + skillInfraController._deployInfraByRegion(TEST_REPORTER, TEST_DD, TEST_REGION, TEST_SKILL_NAME, TEST_DEPLOY_REGIONS, (err, res) => { + // verify + expect(res).equal(undefined); + expect(err).equal("invoke error"); + expect(TEST_DD.invoke.args[0][1].code.isCodeModified).equal(false); + done(); + }); + }); - it('| update resources config correctly', () => { - // call - skillInfraController._updateResourcesConfig(TEST_REGION_LIST, TEST_DEPLOY_RESULT); - // verify - expect(ResourcesConfig.getInstance().getCodeLastDeployHashByRegion(TEST_PROFILE, 'default')).equal('TEST_HASH'); - expect(ResourcesConfig.getInstance().getSkillInfraDeployState(TEST_PROFILE)).deep.equal({ default: {} }); - expect(fse.writeFileSync.callCount).equal(2); - }); + it("| deploy delegate invoke passes with isCodeDeployed true, expect invoke result called back with currentHash", (done) => { + // setup + sinon.stub(hashUtils, "getHash").callsArgWith(1, null, TEST_HASH); + TEST_DD.invoke.callsArgWith(2, null, { + isCodeDeployed: true, + isAllStepSuccess: true, + }); + // call + skillInfraController._deployInfraByRegion(TEST_REPORTER, TEST_DD, TEST_REGION, TEST_SKILL_NAME, TEST_DEPLOY_REGIONS, (err, res) => { + // verify + expect(res).deep.equal({ + isCodeDeployed: true, + isAllStepSuccess: true, + lastDeployHash: TEST_HASH, + }); + expect(err).equal(null); + done(); + }); + }); - it('| update resources config using previous state for unreported regions', () => { - // setup - TEST_REGION_LIST = ['default', 'NA']; - ResourcesConfig.getInstance().setCodeLastDeployHashByRegion(TEST_PROFILE, 'NA', 'TEST_HASH'); - ResourcesConfig.getInstance().setSkillInfraDeployState(TEST_PROFILE, { default: {}, NA: {} }); - // call - skillInfraController._updateResourcesConfig(TEST_REGION_LIST, TEST_DEPLOY_RESULT); - // verify - expect(ResourcesConfig.getInstance().getCodeLastDeployHashByRegion(TEST_PROFILE, 'NA')).equal('TEST_HASH'); - expect(ResourcesConfig.getInstance().getSkillInfraDeployState(TEST_PROFILE)).deep.equal({ default: {}, NA: {} }); - expect(fse.writeFileSync.callCount).equal(2); - }); + it("| deploy delegate invoke passes, expect invoke result called back", (done) => { + // setup + sinon.stub(hashUtils, "getHash").callsArgWith(1, null, TEST_HASH); + TEST_DD.invoke.callsArgWith(2, null, { + isCodeDeployed: false, + isAllStepSuccess: true, + resultMessage: "success", + deployState: {}, + }); + // call + skillInfraController._deployInfraByRegion(TEST_REPORTER, TEST_DD, TEST_REGION, TEST_SKILL_NAME, TEST_DEPLOY_REGIONS, (err, res) => { + // verify + expect(res).deep.equal({ + isCodeDeployed: false, + isAllStepSuccess: true, + resultMessage: "success", + deployState: {}, + }); + expect(err).equal(null); + done(); + }); + }); - it('| update resources config with no previous state for unreported regions', () => { - // setup - TEST_REGION_LIST = ['default', 'NA']; - ResourcesConfig.getInstance().setCodeLastDeployHashByRegion(TEST_PROFILE, 'NA', undefined); - ResourcesConfig.getInstance().setSkillInfraDeployState(TEST_PROFILE, undefined); - // call - skillInfraController._updateResourcesConfig(TEST_REGION_LIST, TEST_DEPLOY_RESULT); - // verify - expect(ResourcesConfig.getInstance().getCodeLastDeployHashByRegion(TEST_PROFILE, 'NA')).equal(undefined); - expect(ResourcesConfig.getInstance().getSkillInfraDeployState(TEST_PROFILE)).deep.equal({ default: {}, NA: undefined }); - expect(fse.writeFileSync.callCount).equal(2); - }); + it("| deploy delegate invoke skipped, expect invoke result called back", (done) => { + // setup + sinon.stub(hashUtils, "getHash").callsArgWith(1, null, TEST_HASH); + TEST_REPORTER.skipTask = sinon.stub(); + TEST_DD.invoke.callsArgWith(2, null, { + isDeploySkipped: true, + resultMessage: "skipped", + deployRegion: "deployRegion", + deployState: {}, + }); + // call + skillInfraController._deployInfraByRegion(TEST_REPORTER, TEST_DD, TEST_REGION, TEST_SKILL_NAME, TEST_DEPLOY_REGIONS, (err, res) => { + // verify + expect(res).deep.equal({ + isDeploySkipped: true, + resultMessage: "skipped", + deployRegion: "deployRegion", + deployState: {}, + }); + expect(err).equal(null); + expect(TEST_REPORTER.skipTask.calledOnce).equal(true); + expect(TEST_REPORTER.skipTask.args[0][0]).equal("skipped"); + done(); + }); + }); + it("| deploy delegate invoke partial succeed with reasons called back, expect invoke result called back along with the message", (done) => { + // setup + sinon.stub(hashUtils, "getHash").callsArgWith(1, null, TEST_HASH); + TEST_DD.invoke.callsArgWith(2, null, { + isCodeDeployed: true, + isAllStepSuccess: false, + resultMessage: "partial fail", + deployState: {}, + }); + // call + skillInfraController._deployInfraByRegion(TEST_REPORTER, TEST_DD, TEST_REGION, TEST_SKILL_NAME, TEST_DEPLOY_REGIONS, (err, res) => { + // verify + expect(res).equal(undefined); + expect(err).deep.equal({ + message: "partial fail", + context: { + isCodeDeployed: true, + isAllStepSuccess: false, + lastDeployHash: TEST_HASH, + resultMessage: "partial fail", + deployState: {}, + }, + }); + done(); + }); + }); + }); + + describe("# test class method: _updateResourcesConfig", () => { + let TEST_REGION_LIST, TEST_DEPLOY_RESULT; + + const skillInfraController = new SkillInfrastructureController(TEST_CONFIGURATION); + + beforeEach(() => { + TEST_REGION_LIST = ["default"]; + TEST_DEPLOY_RESULT = { + default: { + endpoint: { + url: "TEST_URL", + }, + lastDeployHash: "TEST_HASH", + deployState: {}, + }, + }; + new ResourcesConfig(FIXTURE_RESOURCES_CONFIG_FILE_PATH); + sinon.stub(fse, "writeFileSync"); + }); + afterEach(() => { + ResourcesConfig.dispose(); + sinon.restore(); }); - describe('# test class method: _ensureSkillManifestGotUpdated', () => { - const skillInfraController = new SkillInfrastructureController(TEST_CONFIGURATION); + it("| update resources config correctly", () => { + // call + skillInfraController._updateResourcesConfig(TEST_REGION_LIST, TEST_DEPLOY_RESULT); + // verify + expect(ResourcesConfig.getInstance().getCodeLastDeployHashByRegion(TEST_PROFILE, "default")).equal("TEST_HASH"); + expect(ResourcesConfig.getInstance().getSkillInfraDeployState(TEST_PROFILE)).deep.equal({default: {}}); + expect(fse.writeFileSync.callCount).equal(2); + }); - beforeEach(() => { - new ResourcesConfig(FIXTURE_RESOURCES_CONFIG_FILE_PATH); - new Manifest(FIXTURE_MANIFEST_FILE_PATH); - sinon.stub(fs, 'writeFileSync'); - }); + it("| update resources config using previous state for unreported regions", () => { + // setup + TEST_REGION_LIST = ["default", "NA"]; + ResourcesConfig.getInstance().setCodeLastDeployHashByRegion(TEST_PROFILE, "NA", "TEST_HASH"); + ResourcesConfig.getInstance().setSkillInfraDeployState(TEST_PROFILE, {default: {}, NA: {}}); + // call + skillInfraController._updateResourcesConfig(TEST_REGION_LIST, TEST_DEPLOY_RESULT); + // verify + expect(ResourcesConfig.getInstance().getCodeLastDeployHashByRegion(TEST_PROFILE, "NA")).equal("TEST_HASH"); + expect(ResourcesConfig.getInstance().getSkillInfraDeployState(TEST_PROFILE)).deep.equal({default: {}, NA: {}}); + expect(fse.writeFileSync.callCount).equal(2); + }); - afterEach(() => { - ResourcesConfig.dispose(); - Manifest.dispose(); - sinon.restore(); - }); + it("| update resources config with no previous state for unreported regions", () => { + // setup + TEST_REGION_LIST = ["default", "NA"]; + ResourcesConfig.getInstance().setCodeLastDeployHashByRegion(TEST_PROFILE, "NA", undefined); + ResourcesConfig.getInstance().setSkillInfraDeployState(TEST_PROFILE, undefined); + // call + skillInfraController._updateResourcesConfig(TEST_REGION_LIST, TEST_DEPLOY_RESULT); + // verify + expect(ResourcesConfig.getInstance().getCodeLastDeployHashByRegion(TEST_PROFILE, "NA")).equal(undefined); + expect(ResourcesConfig.getInstance().getSkillInfraDeployState(TEST_PROFILE)).deep.equal({default: {}, NA: undefined}); + expect(fse.writeFileSync.callCount).equal(2); + }); + }); - it('| deploy skill package fails, expect error called back', (done) => { - // setup - sinon.stub(profileHelper, 'resolveVendorId'); - sinon.stub(SkillMetadataController.prototype, 'deploySkillPackage').yields('error'); - // call - skillInfraController._ensureSkillManifestGotUpdated((err, res) => { - // verify - expect(res).equal(undefined); - expect(err).equal('error'); - done(); - }); - }); + describe("# test class method: _ensureSkillManifestGotUpdated", () => { + const skillInfraController = new SkillInfrastructureController(TEST_CONFIGURATION); - it('| resolve vendor id fails, expect error called back', (done) => { - // setup - sinon.stub(profileHelper, 'resolveVendorId').throws(new Error('error')); - // call - skillInfraController._ensureSkillManifestGotUpdated((err, res) => { - // verify - expect(res).equal(undefined); - expect(err.message).equal('error'); - done(); - }); - }); + beforeEach(() => { + new ResourcesConfig(FIXTURE_RESOURCES_CONFIG_FILE_PATH); + new Manifest(FIXTURE_MANIFEST_FILE_PATH); + sinon.stub(fs, "writeFileSync"); + }); - it('| deploy skill package succeeds, expect call back with no error', (done) => { - sinon.stub(profileHelper, 'resolveVendorId'); - sinon.stub(SkillMetadataController.prototype, 'deploySkillPackage').yields(); - // call - skillInfraController._ensureSkillManifestGotUpdated((err, res) => { - // verify - expect(res).equal(undefined); - expect(err).equal(undefined); - done(); - }); - }); + afterEach(() => { + ResourcesConfig.dispose(); + Manifest.dispose(); + sinon.restore(); }); - describe('# test class method: _getAlexaDeployRegions', () => { - const skillInfraController = new SkillInfrastructureController(TEST_CONFIGURATION); - - it('| alexaRegion is default, userConfig awsRegion is set, expect awsRegion is retrieved correctly.', (done) => { - // setup - const TEST_ALEXA_REGION = 'default'; - const USER_CONFIG_AWS_REGION = 'sa-east-1'; - const TEST_REGION_LIST = [TEST_ALEXA_REGION]; - const TEST_USER_CONFIG = { - awsRegion: USER_CONFIG_AWS_REGION - }; - // call - const deployRegions = skillInfraController._getAlexaDeployRegions(TEST_REGION_LIST, TEST_USER_CONFIG); - // verify - expect(deployRegions).deep.equal({ [TEST_ALEXA_REGION]: USER_CONFIG_AWS_REGION }); - done(); - }); + it("| update skill manifest fails, expect error called back", (done) => { + // setup + sinon.stub(profileHelper, "resolveVendorId"); + sinon.stub(SkillMetadataController.prototype, "updateSkillManifest").yields("error"); + // call + skillInfraController._ensureSkillManifestGotUpdated((err, res) => { + // verify + expect(res).equal(undefined); + expect(err).equal("error"); + done(); + }); + }); - it('| alexaRegion is default, userConfig awsRegion is NOT set, expect awsRegion is set based on Alexa and AWS region map.', (done) => { - // setup - const TEST_ALEXA_REGION = 'default'; - const MAPPING_ALEXA_DEFAULT_AWS_REGION = 'us-east-1'; - const TEST_REGION_LIST = [TEST_ALEXA_REGION]; - const TEST_USER_CONFIG = {}; - // call - const deployRegions = skillInfraController._getAlexaDeployRegions(TEST_REGION_LIST, TEST_USER_CONFIG); - // verify - expect(deployRegions).deep.equal({ [TEST_ALEXA_REGION]: MAPPING_ALEXA_DEFAULT_AWS_REGION }); - done(); - }); + it("| update skill manifest succeeds, expect call back with no error", (done) => { + sinon.stub(profileHelper, "resolveVendorId"); + sinon.stub(SkillMetadataController.prototype, "updateSkillManifest").yields(); + // call + skillInfraController._ensureSkillManifestGotUpdated((err, res) => { + // verify + expect(res).equal(undefined); + expect(err).equal(undefined); + done(); + }); + }); + }); + + describe("# test class method: _getAlexaDeployRegions", () => { + const skillInfraController = new SkillInfrastructureController(TEST_CONFIGURATION); + + it("| alexaRegion is default, userConfig awsRegion is set, expect awsRegion is retrieved correctly.", (done) => { + // setup + const TEST_ALEXA_REGION = "default"; + const USER_CONFIG_AWS_REGION = "sa-east-1"; + const TEST_REGION_LIST = [TEST_ALEXA_REGION]; + const TEST_USER_CONFIG = { + awsRegion: USER_CONFIG_AWS_REGION, + }; + // call + const deployRegions = skillInfraController._getAlexaDeployRegions(TEST_REGION_LIST, TEST_USER_CONFIG); + // verify + expect(deployRegions).deep.equal({[TEST_ALEXA_REGION]: USER_CONFIG_AWS_REGION}); + done(); + }); - it('| alexaRegion is not default, userConfig regionalOverrides awsRegion is set, expect awsRegion is retrieved correctly.', (done) => { - // setup - const TEST_ALEXA_REGION_EU = 'EU'; - const USER_CONFIG_AWS_REGION = 'eu-west-2'; - const TEST_REGION_LIST = [TEST_ALEXA_REGION_EU]; - const TEST_USER_CONFIG = { - regionalOverrides: { - EU: { - awsRegion: USER_CONFIG_AWS_REGION - } - } - }; - // call - const deployRegions = skillInfraController._getAlexaDeployRegions(TEST_REGION_LIST, TEST_USER_CONFIG); - // verify - expect(deployRegions).deep.equal({ [TEST_ALEXA_REGION_EU]: USER_CONFIG_AWS_REGION }); - done(); - }); + it("| alexaRegion is default, userConfig awsRegion is NOT set, expect awsRegion is set based on Alexa and AWS region map.", (done) => { + // setup + const TEST_ALEXA_REGION = "default"; + const MAPPING_ALEXA_DEFAULT_AWS_REGION = "us-east-1"; + const TEST_REGION_LIST = [TEST_ALEXA_REGION]; + const TEST_USER_CONFIG = {}; + // call + const deployRegions = skillInfraController._getAlexaDeployRegions(TEST_REGION_LIST, TEST_USER_CONFIG); + // verify + expect(deployRegions).deep.equal({[TEST_ALEXA_REGION]: MAPPING_ALEXA_DEFAULT_AWS_REGION}); + done(); + }); - it('| alexaRegion is not default, userConfig regionalOverrides awsRegion is NOT set, ' - + 'expect awsRegion is set based on Alexa and AWS region map.', (done) => { - // setup - const TEST_ALEXA_REGION_EU = 'EU'; - const MAPPING_ALEXA_EU_AWS_REGION = 'eu-west-1'; - const TEST_REGION_LIST = [TEST_ALEXA_REGION_EU]; - const TEST_USER_CONFIG = {}; - // call - const deployRegions = skillInfraController._getAlexaDeployRegions(TEST_REGION_LIST, TEST_USER_CONFIG); - // verify - expect(deployRegions).deep.equal({ [TEST_ALEXA_REGION_EU]: MAPPING_ALEXA_EU_AWS_REGION }); - done(); - }); + it("| alexaRegion is not default, userConfig regionalOverrides awsRegion is set, expect awsRegion is retrieved correctly.", (done) => { + // setup + const TEST_ALEXA_REGION_EU = "EU"; + const USER_CONFIG_AWS_REGION = "eu-west-2"; + const TEST_REGION_LIST = [TEST_ALEXA_REGION_EU]; + const TEST_USER_CONFIG = { + regionalOverrides: { + EU: { + awsRegion: USER_CONFIG_AWS_REGION, + }, + }, + }; + // call + const deployRegions = skillInfraController._getAlexaDeployRegions(TEST_REGION_LIST, TEST_USER_CONFIG); + // verify + expect(deployRegions).deep.equal({[TEST_ALEXA_REGION_EU]: USER_CONFIG_AWS_REGION}); + done(); }); + + it( + "| alexaRegion is not default, userConfig regionalOverrides awsRegion is NOT set, " + + "expect awsRegion is set based on Alexa and AWS region map.", + (done) => { + // setup + const TEST_ALEXA_REGION_EU = "EU"; + const MAPPING_ALEXA_EU_AWS_REGION = "eu-west-1"; + const TEST_REGION_LIST = [TEST_ALEXA_REGION_EU]; + const TEST_USER_CONFIG = {}; + // call + const deployRegions = skillInfraController._getAlexaDeployRegions(TEST_REGION_LIST, TEST_USER_CONFIG); + // verify + expect(deployRegions).deep.equal({[TEST_ALEXA_REGION_EU]: MAPPING_ALEXA_EU_AWS_REGION}); + done(); + }, + ); + }); }); diff --git a/test/unit/controller/skill-metadata-controller-test.js b/test/unit/controller/skill-metadata-controller-test.js index 7b9a84b2..52476e3b 100644 --- a/test/unit/controller/skill-metadata-controller-test.js +++ b/test/unit/controller/skill-metadata-controller-test.js @@ -1,1049 +1,1648 @@ -const { expect } = require('chai'); -const sinon = require('sinon'); -const path = require('path'); -const fs = require('fs-extra'); - -const httpClient = require('@src/clients/http-client'); -const AuthorizationController = require('@src/controllers/authorization-controller'); -const SkillMetadataController = require('@src/controllers/skill-metadata-controller'); -const CliError = require('@src/exceptions/cli-error'); -const CliWarn = require('@src/exceptions/cli-warn'); -const Manifest = require('@src/model/manifest'); -const ResourcesConfig = require('@src/model/resources-config'); -const CONSTANTS = require('@src/utils/constants'); -const hashUtils = require('@src/utils/hash-utils'); -const zipUtils = require('@src/utils/zip-utils'); -const jsonView = require('@src/view/json-view'); -const Messenger = require('@src/view/messenger'); - -describe('Controller test - skill metadata controller test', () => { - const FIXTURE_RESOURCES_CONFIG_FILE_PATH = path.join(process.cwd(), 'test', 'unit', 'fixture', 'model', 'regular-proj', 'ask-resources.json'); - const FIXTURE_MANIFEST_FILE_PATH = path.join(process.cwd(), 'test', 'unit', 'fixture', 'model', 'manifest.json'); - - const TEST_PROFILE = 'default'; // test file contains 'default' profile - const TEST_ROOT_PATH = 'root'; - const TEST_VENDOR_ID = 'vendorId'; - const TEST_IGNORE_HASH = false; - const TEST_SKILL_ID = 'skillId'; - const TEST_STAGE = 'stage'; - const TEST_PATH = 'path'; - const TEST_PACKAGE_URL = 'packageUrl'; - const TEST_CURRENT_HASH = 'currentHash'; - const TEST_UPLOAD_URL = 'uploadUrl'; - const TEST_EXPIRES_AT = 'expiresAt'; - const TEST_LOCATION_URL = 'locationUrl'; - const TEST_IMPORT_ID = 'importId'; - const TEST_EXPORT_ID = 'exportId'; - const TEST_FILE_CONTENT = 'fileContent'; - const TEST_CONFIGURATION = { - profile: TEST_PROFILE, - doDebug: false - }; - - describe('# inspect correctness for constructor', () => { - it('| initiate as a SkillMetadataController class', () => { - const skillMetaController = new SkillMetadataController(TEST_CONFIGURATION); - expect(skillMetaController).to.be.instanceOf(SkillMetadataController); - }); +const {expect} = require("chai"); +const Listr = require("listr"); +const sinon = require("sinon"); +const path = require("path"); +const fs = require("fs-extra"); + +const httpClient = require("../../../lib/clients/http-client"); +const AuthorizationController = require("../../../lib/controllers/authorization-controller"); +const SkillMetadataController = require("../../../lib/controllers/skill-metadata-controller"); +const CliError = require("../../../lib/exceptions/cli-error"); +const CliWarn = require("../../../lib/exceptions/cli-warn"); +const Manifest = require("../../../lib/model/manifest"); +const ResourcesConfig = require("../../../lib/model/resources-config"); +const CONSTANTS = require("../../../lib/utils/constants"); +const hashUtils = require("../../../lib/utils/hash-utils"); +const zipUtils = require("../../../lib/utils/zip-utils"); +const jsonView = require("../../../lib/view/json-view"); +const Messenger = require("../../../lib/view/messenger"); +const acUtil = require("../../../lib/utils/ac-util"); +const { ImportStatusView } = require("../../../lib/view/import-status/import-status-view"); +const SmapiClient = require("../../../lib/clients/smapi-client").default; + +describe("Controller test - skill metadata controller test", () => { + const FIXTURE_RESOURCES_CONFIG_FILE_PATH = path.join( + process.cwd(), + "test", + "unit", + "fixture", + "model", + "regular-proj", + "ask-resources.json", + ); + const FIXTURE_MANIFEST_FILE_PATH = path.join(process.cwd(), "test", "unit", "fixture", "model", "manifest.json"); + + const TEST_PROFILE = "default"; // test file contains 'default' profile + const TEST_ROOT_PATH = "root"; + const TEST_VENDOR_ID = "vendorId"; + const TEST_IGNORE_HASH = false; + const TEST_SKILL_ID = "skillId"; + const TEST_STAGE = "stage"; + const TEST_PATH = "path"; + const TEST_PACKAGE_URL = "packageUrl"; + const TEST_CURRENT_HASH = "currentHash"; + const TEST_UPLOAD_URL = "uploadUrl"; + const TEST_EXPIRES_AT = "expiresAt"; + const TEST_LOCATION_URL = "locationUrl"; + const TEST_IMPORT_ID = "importId"; + const TEST_EXPORT_ID = "exportId"; + const TEST_FILE_CONTENT = "fileContent"; + const TEST_CONFIGURATION = { + profile: TEST_PROFILE, + doDebug: false, + }; + let isAcSkillStub; + + beforeEach(() => { + new ResourcesConfig(FIXTURE_RESOURCES_CONFIG_FILE_PATH); + new Manifest(FIXTURE_MANIFEST_FILE_PATH); + sinon.stub(Listr.prototype, 'run').resolves(); + isAcSkillStub = sinon.stub(acUtil, "isAcSkill").returns(false); + }); + + afterEach(() => { + ResourcesConfig.dispose(); + Manifest.dispose(); + sinon.restore(); + }); + + describe("# inspect correctness for constructor", () => { + it("| initiate as a SkillMetadataController class", () => { + const skillMetaController = new SkillMetadataController(TEST_CONFIGURATION); + expect(skillMetaController).to.be.instanceOf(SkillMetadataController); }); + }); - describe('# test class method: deploySkillPackage', () => { - const skillMetaController = new SkillMetadataController(TEST_CONFIGURATION); + describe("# test class method: deploySkillPackage", () => { + let skillMetaController; - beforeEach(() => { - new ResourcesConfig(FIXTURE_RESOURCES_CONFIG_FILE_PATH); - }); - - afterEach(() => { - ResourcesConfig.dispose(); - sinon.restore(); - }); - - it('| skill package src is empty in ask-resources.json', (done) => { - // setup - ResourcesConfig.getInstance().setSkillMetaSrc(TEST_PROFILE, null); - // call - skillMetaController.deploySkillPackage(TEST_VENDOR_ID, TEST_IGNORE_HASH, (err, res) => { - // verify - expect(res).equal(undefined); - expect(err).equal('Skill package src is not found in ask-resources.json.'); - done(); - }); - }); + beforeEach(() => { + ResourcesConfig.getInstance().setSkillMetaSrc(TEST_PROFILE, TEST_PATH); + skillMetaController = new SkillMetadataController(TEST_CONFIGURATION); + sinon.stub(ImportStatusView.prototype, "displaySkillId").returns(); + sinon.stub(ImportStatusView.prototype, "displayImportId").returns(); + sinon.stub(ImportStatusView.prototype, "publishEvent").returns(); + }); - it('| skill package src is not a valid file path', (done) => { - // setup - ResourcesConfig.getInstance().setSkillMetaSrc(TEST_PROFILE, TEST_PATH); - sinon.stub(fs, 'existsSync').withArgs(TEST_PATH).returns(false); - // call - skillMetaController.deploySkillPackage(TEST_VENDOR_ID, TEST_IGNORE_HASH, (err, res) => { - // verify - expect(res).equal(undefined); - expect(err).equal(`File ${TEST_PATH} does not exist.`); - done(); - }); - }); + it("| skill package src is empty in ask-resources.json", (done) => { + // setup + ResourcesConfig.getInstance().setSkillMetaSrc(TEST_PROFILE, null); + // call + skillMetaController.deploySkillPackage(TEST_VENDOR_ID, TEST_IGNORE_HASH, (err, res) => { + // verify + expect(res).equal(undefined); + expect(err).equal("Skill package src is not found in ask-resources.json."); + done(); + }); + }); - it('| getHash fails with error', (done) => { - // setup - ResourcesConfig.getInstance().setSkillMetaSrc(TEST_PROFILE, TEST_PATH); - sinon.stub(fs, 'existsSync').withArgs(TEST_PATH).returns(true); - sinon.stub(hashUtils, 'getHash').callsArgWith(1, 'hashError', null); - // call - skillMetaController.deploySkillPackage(TEST_VENDOR_ID, TEST_IGNORE_HASH, (err, res) => { - // verify - expect(res).equal(undefined); - expect(err).equal('hashError'); - done(); - }); - }); + it("| skill package src is not a valid file path", (done) => { + // setup + ResourcesConfig.getInstance().setSkillMetaSrc(TEST_PROFILE, TEST_PATH); + sinon.stub(fs, "existsSync").withArgs(TEST_PATH).returns(false); + // call + skillMetaController.deploySkillPackage(TEST_VENDOR_ID, TEST_IGNORE_HASH, (err, res) => { + // verify + expect(res).equal(undefined); + expect(err).equal(`File ${TEST_PATH} does not exist.`); + done(); + }); + }); - it('| getHash result same as lastDeployHash, expect quit with warn message', (done) => { - // setup - const LAST_DEPLOY = 'lastDeploy'; - ResourcesConfig.getInstance().setSkillMetaSrc(TEST_PROFILE, TEST_PATH); - sinon.stub(fs, 'existsSync').withArgs(TEST_PATH).returns(true); - ResourcesConfig.getInstance().setSkillMetaLastDeployHash(TEST_PROFILE, LAST_DEPLOY); - sinon.stub(hashUtils, 'getHash').callsArgWith(1, null, LAST_DEPLOY); - // call - skillMetaController.deploySkillPackage(TEST_VENDOR_ID, TEST_IGNORE_HASH, (err, res) => { - // verify - expect(err).equal('The hash of current skill package folder does not change compared to the ' - + 'last deploy hash result, CLI will skip the deploy of skill package.'); - expect(res).equal(undefined); - done(); - }); - }); + it("| getHash fails with error", (done) => { + // setup + ResourcesConfig.getInstance().setSkillMetaSrc(TEST_PROFILE, TEST_PATH); + sinon.stub(fs, "existsSync").withArgs(TEST_PATH).returns(true); + sinon.stub(hashUtils, "getHash").callsArgWith(1, "hashError", null); + // call + skillMetaController.deploySkillPackage(TEST_VENDOR_ID, TEST_IGNORE_HASH, (err, res) => { + // verify + expect(res).equal(undefined); + expect(err).equal("hashError"); + done(); + }); + }); - it('| hash did not change and ignore hash flag passed, expect resourcesConfig updated correctly', (done) => { - // setup - const LAST_DEPLOY = 'lastDeploy'; - const IGNORE_HASH = true; - ResourcesConfig.getInstance().setSkillMetaSrc(TEST_PROFILE, TEST_PATH); - sinon.stub(fs, 'existsSync').withArgs(TEST_PATH).returns(true); - sinon.stub(hashUtils, 'getHash').callsArgWith(1, null, LAST_DEPLOY); - ResourcesConfig.getInstance().setSkillMetaLastDeployHash(TEST_PROFILE, LAST_DEPLOY); - sinon.stub(SkillMetadataController.prototype, 'putSkillPackage').callsArgWith(2, null, TEST_SKILL_ID); - ResourcesConfig.getInstance().setSkillId(TEST_PROFILE, TEST_SKILL_ID); - // call - skillMetaController.deploySkillPackage(TEST_VENDOR_ID, IGNORE_HASH, (err, res) => { - // verify - expect(err).equal(undefined); - expect(res).equal(undefined); - done(); - }); - }); + it("| getHash result same as lastDeployHash, expect quit with warn message", (done) => { + // setup + const LAST_DEPLOY = "lastDeploy"; + ResourcesConfig.getInstance().setSkillMetaSrc(TEST_PROFILE, TEST_PATH); + sinon.stub(fs, "existsSync").withArgs(TEST_PATH).returns(true); + ResourcesConfig.getInstance().setSkillMetaLastDeployHash(TEST_PROFILE, LAST_DEPLOY); + sinon.stub(hashUtils, "getHash").callsArgWith(1, null, LAST_DEPLOY); + // call + skillMetaController.deploySkillPackage(TEST_VENDOR_ID, TEST_IGNORE_HASH, (err, res) => { + // verify + expect(err).equal( + "The hash of current skill package folder does not change compared to the " + + "last deploy hash result, CLI will skip the deploy of skill package.", + ); + expect(res).equal(undefined); + done(); + }); + }); - it('| hash does change, skillId exists and putSkillPackage passes, expect resourcesConfig updated correctly', (done) => { - // setup - ResourcesConfig.getInstance().setSkillMetaSrc(TEST_PROFILE, TEST_PATH); - sinon.stub(fs, 'existsSync').withArgs(TEST_PATH).returns(true); - sinon.stub(hashUtils, 'getHash').callsArgWith(1, null, TEST_CURRENT_HASH); - sinon.stub(SkillMetadataController.prototype, 'putSkillPackage').callsArgWith(2, null, TEST_SKILL_ID); - ResourcesConfig.getInstance().setSkillId(TEST_PROFILE, TEST_SKILL_ID); - // call - skillMetaController.deploySkillPackage(TEST_VENDOR_ID, TEST_IGNORE_HASH, (err, res) => { - // verify - expect(ResourcesConfig.getInstance().getSkillMetaLastDeployHash(TEST_PROFILE)).equal(TEST_CURRENT_HASH); - expect(err).equal(undefined); - expect(res).equal(undefined); - done(); - }); - }); + it("| hash did not change and ignore hash flag passed, expect resourcesConfig updated correctly", (done) => { + // setup + const LAST_DEPLOY = "lastDeploy"; + const IGNORE_HASH = true; + ResourcesConfig.getInstance().setSkillMetaSrc(TEST_PROFILE, TEST_PATH); + sinon.stub(fs, "existsSync").withArgs(TEST_PATH).returns(true); + sinon.stub(hashUtils, "getHash").callsArgWith(1, null, LAST_DEPLOY); + ResourcesConfig.getInstance().setSkillMetaLastDeployHash(TEST_PROFILE, LAST_DEPLOY); + sinon.stub(SkillMetadataController.prototype, "putSkillPackage").callsArgWith(3, null, TEST_SKILL_ID); + ResourcesConfig.getInstance().setSkillId(TEST_PROFILE, TEST_SKILL_ID); + // call + skillMetaController.deploySkillPackage(TEST_VENDOR_ID, IGNORE_HASH, (err, res) => { + // verify + expect(err).equal(undefined); + expect(res).equal(undefined); + done(); + }); + }); - it('| hash does change, skillId not exists and putSkillPackage passes, expect resourcesConfig updated correctly', (done) => { - // setup - ResourcesConfig.getInstance().setSkillMetaSrc(TEST_PROFILE, TEST_PATH); - sinon.stub(fs, 'existsSync').withArgs(TEST_PATH).returns(true); - sinon.stub(hashUtils, 'getHash').callsArgWith(1, null, TEST_CURRENT_HASH); - sinon.stub(SkillMetadataController.prototype, 'putSkillPackage').callsArgWith(2, null, TEST_SKILL_ID); - ResourcesConfig.getInstance().setSkillId(TEST_PROFILE, ''); - // call - skillMetaController.deploySkillPackage(TEST_VENDOR_ID, TEST_IGNORE_HASH, (err, res) => { - // verify - expect(ResourcesConfig.getInstance().getSkillMetaLastDeployHash(TEST_PROFILE)).equal(TEST_CURRENT_HASH); - expect(ResourcesConfig.getInstance().getSkillId(TEST_PROFILE)).equal(TEST_SKILL_ID); - expect(err).equal(undefined); - expect(res).equal(undefined); - done(); - }); - }); + it("| hash does change, skillId exists and putSkillPackage passes, expect resourcesConfig updated correctly", (done) => { + // setup + ResourcesConfig.getInstance().setSkillMetaSrc(TEST_PROFILE, TEST_PATH); + sinon.stub(fs, "existsSync").withArgs(TEST_PATH).returns(true); + sinon.stub(hashUtils, "getHash").callsArgWith(1, null, TEST_CURRENT_HASH); + sinon.stub(SkillMetadataController.prototype, "putSkillPackage").callsArgWith(3, null, TEST_SKILL_ID); + ResourcesConfig.getInstance().setSkillId(TEST_PROFILE, TEST_SKILL_ID); + // call + skillMetaController.deploySkillPackage(TEST_VENDOR_ID, TEST_IGNORE_HASH, (err, res) => { + // verify + expect(ResourcesConfig.getInstance().getSkillMetaLastDeployHash(TEST_PROFILE)).equal(TEST_CURRENT_HASH); + expect(err).equal(undefined); + expect(res).equal(undefined); + done(); + }); + }); - it('| putSkillPackage fails, expect callback put error message', (done) => { - // setup - ResourcesConfig.getInstance().setSkillMetaSrc(TEST_PROFILE, TEST_PATH); - sinon.stub(fs, 'existsSync').withArgs(TEST_PATH).returns(true); - sinon.stub(hashUtils, 'getHash').callsArgWith(1, null, TEST_CURRENT_HASH); - sinon.stub(SkillMetadataController.prototype, 'putSkillPackage').callsArgWith(2, 'putErr'); - ResourcesConfig.getInstance().setSkillId(TEST_PROFILE, TEST_SKILL_ID); - // call - skillMetaController.deploySkillPackage(TEST_VENDOR_ID, TEST_IGNORE_HASH, (err, res) => { - // verify - expect(err).equal('putErr'); - expect(res).equal(undefined); - done(); - }); - }); + it("| hash does change, skillId not exists and putSkillPackage passes, expect resourcesConfig updated correctly", (done) => { + // setup + ResourcesConfig.getInstance().setSkillMetaSrc(TEST_PROFILE, TEST_PATH); + sinon.stub(fs, "existsSync").withArgs(TEST_PATH).returns(true); + sinon.stub(hashUtils, "getHash").callsArgWith(1, null, TEST_CURRENT_HASH); + sinon.stub(SkillMetadataController.prototype, "putSkillPackage").callsArgWith(3, null, TEST_SKILL_ID); + ResourcesConfig.getInstance().setSkillId(TEST_PROFILE, ""); + // call + skillMetaController.deploySkillPackage(TEST_VENDOR_ID, TEST_IGNORE_HASH, (err, res) => { + // verify + expect(ResourcesConfig.getInstance().getSkillMetaLastDeployHash(TEST_PROFILE)).equal(TEST_CURRENT_HASH); + expect(ResourcesConfig.getInstance().getSkillId(TEST_PROFILE)).equal(TEST_SKILL_ID); + expect(err).equal(undefined); + expect(res).equal(undefined); + done(); + }); }); - describe('# test class method enableSkill', () => { - const skillMetaController = new SkillMetadataController(TEST_CONFIGURATION); + it("| putSkillPackage fails, expect callback put error message", (done) => { + // setup + ResourcesConfig.getInstance().setSkillMetaSrc(TEST_PROFILE, TEST_PATH); + sinon.stub(fs, "existsSync").withArgs(TEST_PATH).returns(true); + sinon.stub(hashUtils, "getHash").callsArgWith(1, null, TEST_CURRENT_HASH); + sinon.stub(SkillMetadataController.prototype, "putSkillPackage").callsArgWith(3, "putErr"); + ResourcesConfig.getInstance().setSkillId(TEST_PROFILE, TEST_SKILL_ID); + // call + skillMetaController.deploySkillPackage(TEST_VENDOR_ID, TEST_IGNORE_HASH, (err, res) => { + // verify + expect(err).equal("putErr"); + expect(res).equal(undefined); + done(); + }); + }); + }); - beforeEach(() => { - new Manifest(FIXTURE_MANIFEST_FILE_PATH); - new ResourcesConfig(FIXTURE_RESOURCES_CONFIG_FILE_PATH); - sinon.stub(AuthorizationController.prototype, 'tokenRefreshAndRead').callsArgWith(1); - }); + describe("# test class method enableSkill", () => { + let skillMetaController; - afterEach(() => { - ResourcesConfig.dispose(); - Manifest.dispose(); - sinon.restore(); - }); + beforeEach(() => { + skillMetaController = new SkillMetadataController(TEST_CONFIGURATION); + sinon.stub(AuthorizationController.prototype, "tokenRefreshAndRead").callsArgWith(1); + }); - it('| callback error when skillId is not provided', (done) => { - // setup - ResourcesConfig.getInstance().setSkillId(TEST_PROFILE, ''); - // call - skillMetaController.enableSkill((err, res) => { - // verify - expect(err).equal(`[Fatal]: Failed to find the skillId for profile [${TEST_PROFILE}], + it("| callback error when skillId is not provided", (done) => { + // setup + ResourcesConfig.getInstance().setSkillId(TEST_PROFILE, ""); + // call + skillMetaController.enableSkill((err, res) => { + // verify + expect(err).equal(`[Fatal]: Failed to find the skillId for profile [${TEST_PROFILE}], please make sure the skill metadata deployment has succeeded with result of a valid skillId.`); - expect(res).equal(undefined); - done(); - }); - }); - - it('| return error when dominInfo is not provided', () => { - // setup - Manifest.getInstance().setApis({}); - const expectedErrMessage = 'Skill information is not valid. Please make sure "apis" field in the skill.json is not empty.'; - // call - expect(() => skillMetaController.validateDomain()).to.throw(CliError, expectedErrMessage); - }); - - it('| return error when dominInfo contains more than one domain', () => { - // setup - Manifest.getInstance().setApis({ - custom: {}, - smartHome: {} - }); - const expectedErrMessage = 'Skill with multiple api domains cannot be enabled. Skip the enable process.'; - // call - expect(() => skillMetaController.validateDomain()).to.throw(CliWarn, expectedErrMessage); - }); - - it('| return error when domain cannot be enabled', () => { - // setup - Manifest.getInstance().setApis({ - smartHome: {} - }); - const expectedErrMessage = 'Skill api domain "smartHome" cannot be enabled. Skip the enable process.'; - // call - expect(() => skillMetaController.validateDomain()).to.throw(CliWarn, expectedErrMessage); - }); - - it('| callback error when getSkillEnablement return error', (done) => { - // setup - sinon.stub(httpClient, 'request').callsArgWith(3, 'getSkillEnablementError'); // stub smapi request - skillMetaController.enableSkill((err, res) => { - // verify - expect(err).equal('getSkillEnablementError'); - expect(res).equal(undefined); - done(); - }); - }); + expect(res).equal(undefined); + done(); + }); + }); - it('| callback error when getSkillEnablement return error', (done) => { - // setup - const responseBody = { - Message: 'somehow fails' - }; - const response = { - statusCode: 300, - body: responseBody - }; - sinon.stub(httpClient, 'request').callsArgWith(3, null, response); // stub smapi request - skillMetaController.enableSkill((err, res) => { - // verify - expect(err).equal(jsonView.toString(responseBody)); - expect(res).equal(undefined); - done(); - }); - }); + it("| return error when domainInfo is not provided", () => { + // setup + Manifest.getInstance().setApis({}); + const expectedErrMessage = 'Skill information is not valid. Please make sure "apis" field in the skill.json is not empty.'; + // call + expect(() => skillMetaController.validateDomain()).to.throw(CliError, expectedErrMessage); + }); - it('| when skill already enabled, can callback skip enablement message', (done) => { - // setup - const response = { - statusCode: 200, - }; - sinon.stub(httpClient, 'request').callsArgWith(3, null, response); // stub smapi request - sinon.stub(Messenger.getInstance(), 'info'); - skillMetaController.enableSkill((err, res) => { - // verify - expect(err).equal(undefined); - expect(res).equal(undefined); - expect(Messenger.getInstance().info.args[0][0]).equal('Skill is already enabled, skip the enable process.'); - done(); - }); - }); + it("| return error when domainInfo contains more than one domain", () => { + // setup + Manifest.getInstance().setApis({ + custom: {}, + smartHome: {}, + }); + const expectedErrMessage = "Skill with multiple api domains cannot be enabled. Skipping the enable process.\n"; + // call + expect(() => skillMetaController.validateDomain()).to.throw(CliWarn, expectedErrMessage); + }); - it('| when skill is not enabled, can callback error when enalbe skill fail', (done) => { - // setup - const getEnablementResponse = { - statusCode: 404, - body: {} - }; - sinon.stub(httpClient, 'request') - .withArgs(sinon.match.any, 'get-skill-enablement') - .callsArgWith(3, null, getEnablementResponse); // stub smapi request - - httpClient.request - .withArgs(sinon.match.any, 'enable-skill') - .callsArgWith(3, 'enableSkillError'); // stub smapi request - - skillMetaController.enableSkill((err, res) => { - // verify - expect(err).equal('enableSkillError'); - expect(res).equal(undefined); - done(); - }); - }); + it("| return error when domain cannot be enabled", () => { + // setup + Manifest.getInstance().setApis({ + smartHome: {}, + }); + const expectedErrMessage = 'Skill api domain "smartHome" cannot be enabled. Skipping the enable process.\n'; + // call + expect(() => skillMetaController.validateDomain()).to.throw(CliWarn, expectedErrMessage); + }); - it('| when skill is not enabled, can callback error when statusCode >= 300', (done) => { - // setup - const getEnablementResponse = { - statusCode: 404, - body: {} - }; - const enableSkillResponseBody = { - Message: 'somehow fail' - }; - const enableSkillResponse = { - statusCode: 300, - body: enableSkillResponseBody - }; - sinon.stub(httpClient, 'request') - .withArgs(sinon.match.any, 'get-skill-enablement') - .callsArgWith(3, null, getEnablementResponse); // stub smapi request - - httpClient.request - .withArgs(sinon.match.any, 'enable-skill') - .callsArgWith(3, null, enableSkillResponse); // stub smapi request - - skillMetaController.enableSkill((err, res) => { - // verify - expect(err).equal(jsonView.toString(enableSkillResponseBody)); - expect(res).equal(undefined); - done(); - }); - }); + it("| callback error when getSkillEnablement return error", (done) => { + // setup + sinon.stub(httpClient, "request").callsArgWith(3, "getSkillEnablementError"); // stub smapi request + skillMetaController.enableSkill((err, res) => { + // verify + expect(err).equal("getSkillEnablementError"); + expect(res).equal(undefined); + done(); + }); + }); - it('| when skill is not enabled, can callback success enable skill message', (done) => { - // setup - const getEnablementResponse = { - statusCode: 404, - body: {} - }; - const enableSkillResponse = { - statusCode: 200, - }; - sinon.stub(Messenger.getInstance(), 'info'); - sinon.stub(httpClient, 'request') - .withArgs(sinon.match.any, 'get-skill-enablement') - .callsArgWith(3, null, getEnablementResponse); // stub smapi request - - httpClient.request - .withArgs(sinon.match.any, 'enable-skill') - .callsArgWith(3, null, enableSkillResponse); // stub smapi request - - skillMetaController.enableSkill((err, res) => { - // verify - expect(err).equal(undefined); - expect(res).equal(undefined); - expect(Messenger.getInstance().info.args[0][0]).equal('Skill is enabled successfully.'); - done(); - }); - }); + it("| callback error when getSkillEnablement return error", (done) => { + // setup + const responseBody = { + Message: "somehow fails", + }; + const response = { + statusCode: 300, + body: responseBody, + }; + sinon.stub(httpClient, "request").callsArgWith(3, null, response); // stub smapi request + skillMetaController.enableSkill((err, res) => { + // verify + expect(err).equal(jsonView.toString(responseBody)); + expect(res).equal(undefined); + done(); + }); }); - describe('# test class method: putSkillPackage', () => { - const skillMetaController = new SkillMetadataController(TEST_CONFIGURATION); + it("| when skill already enabled, can callback skip enablement message", (done) => { + // setup + const response = { + statusCode: 200, + }; + sinon.stub(httpClient, "request").callsArgWith(3, null, response); // stub smapi request + sinon.stub(Messenger.getInstance(), "info"); + skillMetaController.enableSkill((err, res) => { + // verify + expect(err).equal(undefined); + expect(res).equal(undefined); + expect(Messenger.getInstance().info.args[0][0]).equal("Skill is already enabled, skipping the enable process.\n"); + done(); + }); + }); - beforeEach(() => { - new ResourcesConfig(FIXTURE_RESOURCES_CONFIG_FILE_PATH); - }); + it("| when skill is not enabled, can callback error when enable skill fail", (done) => { + // setup + const getEnablementResponse = { + statusCode: 404, + body: {}, + }; + sinon.stub(httpClient, "request").withArgs(sinon.match.any, "get-skill-enablement").callsArgWith(3, null, getEnablementResponse); // stub smapi request + + httpClient.request.withArgs(sinon.match.any, "enable-skill").callsArgWith(3, "enableSkillError"); // stub smapi request + + skillMetaController.enableSkill((err, res) => { + // verify + expect(err).equal("enableSkillError"); + expect(res).equal(undefined); + done(); + }); + }); - afterEach(() => { - ResourcesConfig.dispose(); - sinon.restore(); - }); + it("| when skill is not enabled, can callback error when statusCode >= 300", (done) => { + // setup + const getEnablementResponse = { + statusCode: 404, + body: {}, + }; + const enableSkillResponseBody = { + Message: "somehow fail", + }; + const enableSkillResponse = { + statusCode: 300, + body: enableSkillResponseBody, + }; + sinon.stub(httpClient, "request").withArgs(sinon.match.any, "get-skill-enablement").callsArgWith(3, null, getEnablementResponse); // stub smapi request + + httpClient.request.withArgs(sinon.match.any, "enable-skill").callsArgWith(3, null, enableSkillResponse); // stub smapi request + + skillMetaController.enableSkill((err, res) => { + // verify + expect(err).equal(jsonView.toString(enableSkillResponseBody)); + expect(res).equal(undefined); + done(); + }); + }); - it('| upload of skill package fails, expect callback with error', (done) => { - // setup - ResourcesConfig.getInstance().setSkillMetaSrc(TEST_PROFILE, TEST_PATH); - sinon.stub(SkillMetadataController.prototype, 'uploadSkillPackage').callsArgWith(1, 'uploadErr'); - // call - skillMetaController.putSkillPackage(TEST_SKILL_ID, TEST_VENDOR_ID, (err, res) => { - // verify - expect(SkillMetadataController.prototype.uploadSkillPackage.args[0][0]).equal(TEST_PATH); - expect(res).equal(undefined); - expect(err).equal('uploadErr'); - done(); - }); - }); + it("| when skill is not enabled, can callback success enable skill message", (done) => { + // setup + const getEnablementResponse = { + statusCode: 404, + body: {}, + }; + const enableSkillResponse = { + statusCode: 200, + }; + sinon.stub(Messenger.getInstance(), "info"); + sinon.stub(httpClient, "request").withArgs(sinon.match.any, "get-skill-enablement").callsArgWith(3, null, getEnablementResponse); // stub smapi request + + httpClient.request.withArgs(sinon.match.any, "enable-skill").callsArgWith(3, null, enableSkillResponse); // stub smapi request + + skillMetaController.enableSkill((err, res) => { + // verify + expect(err).equal(undefined); + expect(res).equal(undefined); + expect(Messenger.getInstance().info.args[0][0]).equal("Skill is enabled successfully.\n"); + done(); + }); + }); + }); - it('| import skill pacakge faild, expect callback with error', (done) => { - // setup - ResourcesConfig.getInstance().setSkillMetaSrc(TEST_PROFILE, TEST_PATH); - sinon.stub(SkillMetadataController.prototype, 'uploadSkillPackage').callsArgWith(1, null, { - uploadUrl: TEST_UPLOAD_URL - }); - sinon.stub(SkillMetadataController.prototype, '_importPackage').callsArgWith(3, 'importErr'); - // call - skillMetaController.putSkillPackage(TEST_SKILL_ID, TEST_VENDOR_ID, (err, res) => { - // verify - expect(SkillMetadataController.prototype._importPackage.args[0][0]).equal(TEST_SKILL_ID); - expect(SkillMetadataController.prototype._importPackage.args[0][1]).equal(TEST_VENDOR_ID); - expect(SkillMetadataController.prototype._importPackage.args[0][2]).equal(TEST_UPLOAD_URL); - expect(res).equal(undefined); - expect(err).equal('importErr'); - done(); - }); - }); + describe("# test class method: putSkillPackage", () => { + let skillMetaController; - it('| poll skill pacakge faild, expect callback with error', (done) => { - // setup - ResourcesConfig.getInstance().setSkillMetaSrc(TEST_PROFILE, TEST_PATH); - sinon.stub(SkillMetadataController.prototype, 'uploadSkillPackage').callsArgWith(1, null, { - uploadUrl: TEST_UPLOAD_URL - }); - sinon.stub(SkillMetadataController.prototype, '_importPackage').callsArgWith(3, null, { - headers: { location: TEST_LOCATION_URL } - }); - sinon.stub(SkillMetadataController.prototype, '_pollImportStatus').callsArgWith(1, 'pollErr'); - // call - skillMetaController.putSkillPackage(TEST_SKILL_ID, TEST_VENDOR_ID, (err, res) => { - // verify - expect(SkillMetadataController.prototype._pollImportStatus.args[0][0]).equal(TEST_LOCATION_URL); - expect(res).equal(undefined); - expect(err).equal('pollErr'); - done(); - }); - }); + beforeEach(() => { + skillMetaController = new SkillMetadataController(TEST_CONFIGURATION); + }); - it('| poll skill pacakge replies with non succeed result, expect callback with error response', (done) => { - // setup - ResourcesConfig.getInstance().setSkillMetaSrc(TEST_PROFILE, TEST_PATH); - sinon.stub(SkillMetadataController.prototype, 'uploadSkillPackage').callsArgWith(1, null, { - uploadUrl: TEST_UPLOAD_URL - }); - sinon.stub(SkillMetadataController.prototype, '_importPackage').callsArgWith(3, null, { - headers: { location: TEST_LOCATION_URL } - }); - sinon.stub(SkillMetadataController.prototype, '_pollImportStatus').callsArgWith(1, null, { - body: { status: CONSTANTS.SKILL.PACKAGE_STATUS.FAILED } - }); - // call - skillMetaController.putSkillPackage(TEST_SKILL_ID, TEST_VENDOR_ID, (err, res) => { - // verify - expect(SkillMetadataController.prototype._pollImportStatus.args[0][0]).equal(TEST_LOCATION_URL); - expect(res).equal(undefined); - expect(err).equal(jsonView.toString({ status: CONSTANTS.SKILL.PACKAGE_STATUS.FAILED })); - done(); - }); - }); - it('| poll skill pacakge finished, expect callback skillId', (done) => { - // setup - ResourcesConfig.getInstance().setSkillMetaSrc(TEST_PROFILE, TEST_PATH); - sinon.stub(SkillMetadataController.prototype, 'uploadSkillPackage').callsArgWith(1, null, { - uploadUrl: TEST_UPLOAD_URL - }); - sinon.stub(SkillMetadataController.prototype, '_importPackage').callsArgWith(3, null, { - headers: { location: TEST_LOCATION_URL } - }); - sinon.stub(SkillMetadataController.prototype, '_pollImportStatus').callsArgWith(1, null, { - body: { - status: CONSTANTS.SKILL.PACKAGE_STATUS.SUCCEEDED, - skill: { skillId: TEST_SKILL_ID } - } - }); - // call - skillMetaController.putSkillPackage(TEST_SKILL_ID, TEST_VENDOR_ID, (err, res) => { - // verify - expect(SkillMetadataController.prototype._pollImportStatus.args[0][0]).equal(TEST_LOCATION_URL); - expect(err).equal(null); - expect(res).equal(TEST_SKILL_ID); - done(); - }); - }); + it("| upload of skill package fails, expect callback with error", (done) => { + // setup + ResourcesConfig.getInstance().setSkillMetaSrc(TEST_PROFILE, TEST_PATH); + sinon.stub(SkillMetadataController.prototype, "uploadSkillPackage").callsArgWith(1, "uploadErr"); + // call + skillMetaController.putSkillPackage(TEST_PATH, TEST_SKILL_ID, TEST_VENDOR_ID, (err, res) => { + // verify + expect(SkillMetadataController.prototype.uploadSkillPackage.args[0][0]).equal(TEST_PATH); + expect(res).equal(undefined); + expect(err).equal("uploadErr"); + done(); + }); }); - describe('# test class method: getSkillPackage', () => { - const skillMetaController = new SkillMetadataController(TEST_CONFIGURATION); - - beforeEach(() => { - }); + it("| import skill package failed, expect callback with error", (done) => { + // setup + ResourcesConfig.getInstance().setSkillMetaSrc(TEST_PROFILE, TEST_PATH); + sinon.stub(SkillMetadataController.prototype, "uploadSkillPackage").callsArgWith(1, null, { + uploadUrl: TEST_UPLOAD_URL, + }); + sinon.stub(SkillMetadataController.prototype, "_importPackage").callsArgWith(3, "importErr"); + // call + skillMetaController.putSkillPackage(TEST_PATH, TEST_SKILL_ID, TEST_VENDOR_ID, (err, res) => { + // verify + expect(SkillMetadataController.prototype._importPackage.args[0][0]).equal(TEST_SKILL_ID); + expect(SkillMetadataController.prototype._importPackage.args[0][1]).equal(TEST_VENDOR_ID); + expect(SkillMetadataController.prototype._importPackage.args[0][2]).equal(TEST_UPLOAD_URL); + expect(res).equal(undefined); + expect(err).equal("importErr"); + done(); + }); + }); - afterEach(() => { - sinon.restore(); - }); + it("| poll skill package failed, expect callback with error", (done) => { + // setup + ResourcesConfig.getInstance().setSkillMetaSrc(TEST_PROFILE, TEST_PATH); + sinon.stub(SkillMetadataController.prototype, "uploadSkillPackage").callsArgWith(1, null, { + uploadUrl: TEST_UPLOAD_URL, + }); + sinon.stub(SkillMetadataController.prototype, "_importPackage").callsArgWith(3, null, { + headers: {location: TEST_LOCATION_URL}, + }); + sinon.stub(SkillMetadataController.prototype, "_pollImportStatus").callsArgWith(1, "pollErr"); + sinon.stub(ImportStatusView.prototype, "displayImportId").returns(); + + // call + skillMetaController.putSkillPackage(TEST_PATH, TEST_SKILL_ID, TEST_VENDOR_ID, (err, res) => { + // verify + expect(SkillMetadataController.prototype._pollImportStatus.args[0][0]).equal(TEST_LOCATION_URL); + expect(res).equal(undefined); + expect(err).equal("pollErr"); + done(); + }); + }); - it('| export package request fails, expect callback with error', (done) => { - // setup - sinon.stub(SkillMetadataController.prototype, '_exportPackage').callsArgWith(2, 'exportErr'); - // call - skillMetaController.getSkillPackage(TEST_ROOT_PATH, TEST_SKILL_ID, TEST_STAGE, (err, res) => { - // verify - expect(SkillMetadataController.prototype._exportPackage.args[0][0]).equal(TEST_SKILL_ID); - expect(SkillMetadataController.prototype._exportPackage.args[0][1]).equal(TEST_STAGE); - expect(res).equal(undefined); - expect(err).equal('exportErr'); - done(); - }); - }); + it("| poll skill package replies with non succeed result, expect callback with error response", (done) => { + // setup + ResourcesConfig.getInstance().setSkillMetaSrc(TEST_PROFILE, TEST_PATH); + sinon.stub(SkillMetadataController.prototype, "uploadSkillPackage").callsArgWith(1, null, { + uploadUrl: TEST_UPLOAD_URL, + }); + sinon.stub(SkillMetadataController.prototype, "_importPackage").callsArgWith(3, null, { + headers: {location: TEST_LOCATION_URL}, + }); + sinon.stub(SkillMetadataController.prototype, "_pollImportStatus").callsArgWith(1, null, { + body: {status: CONSTANTS.SKILL.PACKAGE_STATUS.FAILED}, + }); + // call + skillMetaController.putSkillPackage(TEST_PATH, TEST_SKILL_ID, TEST_VENDOR_ID, (err, res) => { + // verify + expect(SkillMetadataController.prototype._pollImportStatus.args[0][0]).equal(TEST_LOCATION_URL); + expect(res).equal(undefined); + expect(err).equal(jsonView.toString({status: CONSTANTS.SKILL.PACKAGE_STATUS.FAILED})); + done(); + }); + }); - it('| export package returns exportId but poll status fails, expect callback with error', (done) => { - // setup - sinon.stub(SkillMetadataController.prototype, '_exportPackage').callsArgWith(2, null, { - statusCode: 202, - headers: { - location: `${TEST_EXPORT_ID}` - } - }); - sinon.stub(SkillMetadataController.prototype, '_pollExportStatus').callsArgWith(1, 'polling error'); - // call - skillMetaController.getSkillPackage(TEST_ROOT_PATH, TEST_SKILL_ID, TEST_STAGE, (err, res) => { - // verify - expect(SkillMetadataController.prototype._pollExportStatus.args[0][0]).equal(TEST_EXPORT_ID); - expect(res).equal(undefined); - expect(err).equal('polling error'); - done(); - }); - }); + it("| poll skill package finished, expect callback skillId", (done) => { + // setup + ResourcesConfig.getInstance().setSkillMetaSrc(TEST_PROFILE, TEST_PATH); + sinon.stub(SkillMetadataController.prototype, "uploadSkillPackage").callsArgWith(1, null, { + uploadUrl: TEST_UPLOAD_URL, + }); + sinon.stub(SkillMetadataController.prototype, "_importPackage").callsArgWith(3, null, { + headers: {location: TEST_LOCATION_URL}, + }); + sinon.stub(SkillMetadataController.prototype, "_pollImportStatus").callsArgWith(1, null, { + body: { + status: CONSTANTS.SKILL.PACKAGE_STATUS.SUCCEEDED, + skill: {skillId: TEST_SKILL_ID}, + }, + }); + // call + skillMetaController.putSkillPackage(TEST_PATH, TEST_SKILL_ID, TEST_VENDOR_ID, (err, res) => { + // verify + expect(SkillMetadataController.prototype._pollImportStatus.args[0][0]).equal(TEST_LOCATION_URL); + expect(err).equal(null); + expect(res).equal(TEST_SKILL_ID); + done(); + }); + }); + }); - it('| package exported successfully but unzip fails, expect callback zip error', (done) => { - // setup - sinon.stub(SkillMetadataController.prototype, '_exportPackage').callsArgWith(2, null, { - statusCode: 202, - headers: { - location: `${TEST_EXPORT_ID}` - } - }); - sinon.stub(SkillMetadataController.prototype, '_pollExportStatus').callsArgWith(1, null, { - statusCode: 200, - body: { - skill: { - location: TEST_PACKAGE_URL - } - } - }); - sinon.stub(zipUtils, 'unzipRemoteZipFile').callsArgWith(3, 'unzip error'); - // call - skillMetaController.getSkillPackage(TEST_ROOT_PATH, TEST_SKILL_ID, TEST_STAGE, (err, res) => { - // verify - expect(SkillMetadataController.prototype._pollExportStatus.args[0][0]).equal(TEST_EXPORT_ID); - expect(res).equal(undefined); - expect(err).equal('unzip error'); - done(); - }); - }); + describe("# test class method: getSkillPackage", () => { + let skillMetaController; - it('| package exported successfully and unzip works, expect no error returned', (done) => { - // setup - sinon.stub(SkillMetadataController.prototype, '_exportPackage').callsArgWith(2, null, { - statusCode: 202, - headers: { - location: `${TEST_EXPORT_ID}` - } - }); - sinon.stub(SkillMetadataController.prototype, '_pollExportStatus').callsArgWith(1, null, { - statusCode: 200, - body: { - skill: { - location: TEST_PACKAGE_URL - } - } - }); - sinon.stub(zipUtils, 'unzipRemoteZipFile').callsArgWith(3, null); - // call - skillMetaController.getSkillPackage(TEST_ROOT_PATH, TEST_SKILL_ID, TEST_STAGE, (err, res) => { - // verify - expect(SkillMetadataController.prototype._pollExportStatus.args[0][0]).equal(TEST_EXPORT_ID); - expect(res).equal(undefined); - expect(err).equal(null); - done(); - }); - }); + beforeEach(() => { + ResourcesConfig.getInstance().setSkillMetaSrc(TEST_PROFILE, TEST_PATH); + skillMetaController = new SkillMetadataController(TEST_CONFIGURATION); }); - describe('# test class method: uploadSkillPackage', () => { - const skillMetaController = new SkillMetadataController(TEST_CONFIGURATION); + it("| export package request fails, expect callback with error", (done) => { + // setup + sinon.stub(SkillMetadataController.prototype, "_exportPackage").callsArgWith(2, "exportErr"); + // call + skillMetaController.getSkillPackage(TEST_ROOT_PATH, TEST_SKILL_ID, TEST_STAGE, (err, res) => { + // verify + expect(SkillMetadataController.prototype._exportPackage.args[0][0]).equal(TEST_SKILL_ID); + expect(SkillMetadataController.prototype._exportPackage.args[0][1]).equal(TEST_STAGE); + expect(res).equal(undefined); + expect(err).equal("exportErr"); + done(); + }); + }); - beforeEach(() => { - new ResourcesConfig(FIXTURE_RESOURCES_CONFIG_FILE_PATH); - }); + it("| export package returns exportId but poll status fails, expect callback with error", (done) => { + // setup + sinon.stub(SkillMetadataController.prototype, "_exportPackage").callsArgWith(2, null, { + statusCode: 202, + headers: { + location: `${TEST_EXPORT_ID}`, + }, + }); + sinon.stub(SkillMetadataController.prototype, "_pollExportStatus").callsArgWith(1, "polling error"); + // call + skillMetaController.getSkillPackage(TEST_ROOT_PATH, TEST_SKILL_ID, TEST_STAGE, (err, res) => { + // verify + expect(SkillMetadataController.prototype._pollExportStatus.args[0][0]).equal(TEST_EXPORT_ID); + expect(res).equal(undefined); + expect(err).equal("polling error"); + done(); + }); + }); - afterEach(() => { - ResourcesConfig.dispose(); - sinon.restore(); - }); + it("| package exported successfully but unzip fails, expect callback zip error", (done) => { + // setup + sinon.stub(SkillMetadataController.prototype, "_exportPackage").callsArgWith(2, null, { + statusCode: 202, + headers: { + location: `${TEST_EXPORT_ID}`, + }, + }); + sinon.stub(SkillMetadataController.prototype, "_pollExportStatus").callsArgWith(1, null, { + statusCode: 200, + body: { + skill: { + location: TEST_PACKAGE_URL, + }, + }, + }); + sinon.stub(zipUtils, "unzipRemoteZipFile").callsArgWith(3, "unzip error"); + // call + skillMetaController.getSkillPackage(TEST_ROOT_PATH, TEST_SKILL_ID, TEST_STAGE, (err, res) => { + // verify + expect(SkillMetadataController.prototype._pollExportStatus.args[0][0]).equal(TEST_EXPORT_ID); + expect(res).equal(undefined); + expect(err).equal("unzip error"); + done(); + }); + }); - it('| create upload url fails, expect callback error', (done) => { - // setup - sinon.stub(SkillMetadataController.prototype, '_createUploadUrl').callsArgWith(0, 'createUploadErr'); - // call - skillMetaController.uploadSkillPackage(TEST_PATH, (err, res) => { - // verify - expect(res).equal(undefined); - expect(err).equal('createUploadErr'); - done(); - }); - }); + it("| package exported successfully and unzip works, expect no error returned", (done) => { + // setup + sinon.stub(SkillMetadataController.prototype, "_exportPackage").callsArgWith(2, null, { + statusCode: 202, + headers: { + location: `${TEST_EXPORT_ID}`, + }, + }); + sinon.stub(SkillMetadataController.prototype, "_pollExportStatus").callsArgWith(1, null, { + statusCode: 200, + body: { + skill: { + location: TEST_PACKAGE_URL, + }, + }, + }); + sinon.stub(zipUtils, "unzipRemoteZipFile").callsArgWith(3, null); + // call + skillMetaController.getSkillPackage(TEST_ROOT_PATH, TEST_SKILL_ID, TEST_STAGE, (err, res) => { + // verify + expect(SkillMetadataController.prototype._pollExportStatus.args[0][0]).equal(TEST_EXPORT_ID); + expect(res).equal(undefined); + expect(err).equal(null); + done(); + }); + }); + }); - it('| create zip fails, expect callback error', (done) => { - // setup - sinon.stub(SkillMetadataController.prototype, '_createUploadUrl').callsArgWith(0, null, { - uploadUrl: TEST_UPLOAD_URL - }); - sinon.stub(zipUtils, 'createTempZip').callsArgWith(2, 'zipErr'); - // call - skillMetaController.uploadSkillPackage(TEST_PATH, (err, res) => { - // verify - expect(zipUtils.createTempZip.args[0][0]).equal(TEST_PATH); - expect(res).equal(undefined); - expect(err).equal('zipErr'); - done(); - }); - }); + describe("# test class method: uploadSkillPackage", () => { + let skillMetaController; - it('| upload zip file fails, expect callback error', (done) => { - // setup - sinon.stub(fs, 'readFileSync').withArgs(TEST_PATH).returns(TEST_FILE_CONTENT); - sinon.stub(SkillMetadataController.prototype, '_createUploadUrl').callsArgWith(0, null, { - uploadUrl: TEST_UPLOAD_URL - }); - sinon.stub(zipUtils, 'createTempZip').callsArgWith(2, null, TEST_PATH); - sinon.stub(fs, 'removeSync'); - sinon.stub(httpClient, 'putByUrl').callsArgWith(4, 'uploadErr'); - // call - skillMetaController.uploadSkillPackage(TEST_PATH, (err, res) => { - // verify - expect(httpClient.putByUrl.args[0][0]).equal(TEST_UPLOAD_URL); - expect(httpClient.putByUrl.args[0][1]).equal(TEST_FILE_CONTENT); - expect(httpClient.putByUrl.args[0][2]).equal('upload-skill-package'); - expect(httpClient.putByUrl.args[0][3]).equal(false); - expect(res).equal(undefined); - expect(err).equal('uploadErr'); - done(); - }); - }); + beforeEach(() => { + skillMetaController = new SkillMetadataController(TEST_CONFIGURATION); + }); - it('| upload zip file meets error, expect callback error', (done) => { - // setup - sinon.stub(zipUtils, 'createTempZip').callsArgWith(2, null, TEST_PATH); - sinon.stub(fs, 'readFileSync').withArgs(TEST_PATH).returns(TEST_FILE_CONTENT); - sinon.stub(SkillMetadataController.prototype, '_createUploadUrl').callsArgWith(0, null, { - uploadUrl: TEST_UPLOAD_URL - }); - sinon.stub(fs, 'removeSync'); - sinon.stub(httpClient, 'putByUrl').callsArgWith(4, null, { - statusCode: 401 - }); - // call - skillMetaController.uploadSkillPackage(TEST_PATH, (err, res) => { - // verify - expect(httpClient.putByUrl.args[0][0]).equal(TEST_UPLOAD_URL); - expect(httpClient.putByUrl.args[0][1]).equal(TEST_FILE_CONTENT); - expect(httpClient.putByUrl.args[0][2]).equal('upload-skill-package'); - expect(httpClient.putByUrl.args[0][3]).equal(false); - expect(res).equal(undefined); - expect(err).equal('[Error]: Upload of skill package failed. Please try again with --debug to see more details.'); - done(); - }); - }); + it("| create upload url fails, expect callback error", (done) => { + // setup + sinon.stub(SkillMetadataController.prototype, "_createUploadUrl").callsArgWith(0, "createUploadErr"); + // call + skillMetaController.uploadSkillPackage(TEST_PATH, (err, res) => { + // verify + expect(res).equal(undefined); + expect(err).equal("createUploadErr"); + done(); + }); + }); - it('| upload skill package succeeds, expect callback upload result', (done) => { - // setup - sinon.stub(zipUtils, 'createTempZip').callsArgWith(2, null, TEST_PATH); - sinon.stub(fs, 'readFileSync').withArgs(TEST_PATH).returns(TEST_FILE_CONTENT); - sinon.stub(SkillMetadataController.prototype, '_createUploadUrl').callsArgWith(0, null, { - uploadUrl: TEST_UPLOAD_URL - }); - sinon.stub(fs, 'removeSync'); - sinon.stub(httpClient, 'putByUrl').callsArgWith(4, null, { statusCode: 202 }); - // call - skillMetaController.uploadSkillPackage(TEST_PATH, (err, res) => { - // verify - expect(httpClient.putByUrl.args[0][0]).equal(TEST_UPLOAD_URL); - expect(httpClient.putByUrl.args[0][1]).equal(TEST_FILE_CONTENT); - expect(httpClient.putByUrl.args[0][2]).equal('upload-skill-package'); - expect(httpClient.putByUrl.args[0][3]).equal(false); - expect(err).equal(null); - expect(res).deep.equal({ - uploadUrl: TEST_UPLOAD_URL - }); - done(); - }); - }); + it("| create zip fails, expect callback error", (done) => { + // setup + sinon.stub(SkillMetadataController.prototype, "_createUploadUrl").callsArgWith(0, null, { + uploadUrl: TEST_UPLOAD_URL, + }); + sinon.stub(zipUtils, "createTempZip").callsArgWith(1, "zipErr"); + // call + skillMetaController.uploadSkillPackage(TEST_PATH, (err, res) => { + // verify + expect(zipUtils.createTempZip.args[0][0]).equal(TEST_PATH); + expect(res).equal(undefined); + expect(err).equal("zipErr"); + done(); + }); }); - describe('# test class method: getInteractionModelLocales', () => { - const skillMetaController = new SkillMetadataController(TEST_CONFIGURATION); + it("| upload zip file fails, expect callback error", (done) => { + // setup + sinon.stub(fs, "readFileSync").withArgs(TEST_PATH).returns(TEST_FILE_CONTENT); + sinon.stub(SkillMetadataController.prototype, "_createUploadUrl").callsArgWith(0, null, { + uploadUrl: TEST_UPLOAD_URL, + }); + sinon.stub(zipUtils, "createTempZip").callsArgWith(1, null, TEST_PATH); + sinon.stub(fs, "removeSync"); + sinon.stub(httpClient, "putByUrl").callsArgWith(4, "uploadErr"); + // call + skillMetaController.uploadSkillPackage(TEST_PATH, (err, res) => { + // verify + expect(httpClient.putByUrl.args[0][0]).equal(TEST_UPLOAD_URL); + expect(httpClient.putByUrl.args[0][1]).equal(TEST_FILE_CONTENT); + expect(httpClient.putByUrl.args[0][2]).equal("upload-skill-package"); + expect(httpClient.putByUrl.args[0][3]).equal(false); + expect(res).equal(undefined); + expect(err).equal("uploadErr"); + done(); + }); + }); - beforeEach(() => { - new ResourcesConfig(FIXTURE_RESOURCES_CONFIG_FILE_PATH); - }); + it("| upload zip file meets error, expect callback error", (done) => { + // setup + sinon.stub(zipUtils, "createTempZip").callsArgWith(1, null, TEST_PATH); + sinon.stub(fs, "readFileSync").withArgs(TEST_PATH).returns(TEST_FILE_CONTENT); + sinon.stub(SkillMetadataController.prototype, "_createUploadUrl").callsArgWith(0, null, { + uploadUrl: TEST_UPLOAD_URL, + }); + sinon.stub(fs, "removeSync"); + sinon.stub(httpClient, "putByUrl").callsArgWith(4, null, { + statusCode: 401, + }); + // call + skillMetaController.uploadSkillPackage(TEST_PATH, (err, res) => { + // verify + expect(httpClient.putByUrl.args[0][0]).equal(TEST_UPLOAD_URL); + expect(httpClient.putByUrl.args[0][1]).equal(TEST_FILE_CONTENT); + expect(httpClient.putByUrl.args[0][2]).equal("upload-skill-package"); + expect(httpClient.putByUrl.args[0][3]).equal(false); + expect(res).equal(undefined); + expect(err).equal("[Error]: Upload of skill package failed. Please try again with --debug to see more details."); + done(); + }); + }); - afterEach(() => { - ResourcesConfig.dispose(); - sinon.restore(); - }); + it("| upload skill package succeeds, expect callback upload result", (done) => { + // setup + sinon.stub(zipUtils, "createTempZip").callsArgWith(1, null, TEST_PATH); + sinon.stub(fs, "readFileSync").withArgs(TEST_PATH).returns(TEST_FILE_CONTENT); + sinon.stub(SkillMetadataController.prototype, "_createUploadUrl").callsArgWith(0, null, { + uploadUrl: TEST_UPLOAD_URL, + }); + sinon.stub(fs, "removeSync"); + sinon.stub(httpClient, "putByUrl").callsArgWith(4, null, {statusCode: 202}); + // call + skillMetaController.uploadSkillPackage(TEST_PATH, (err, res) => { + // verify + expect(httpClient.putByUrl.args[0][0]).equal(TEST_UPLOAD_URL); + expect(httpClient.putByUrl.args[0][1]).equal(TEST_FILE_CONTENT); + expect(httpClient.putByUrl.args[0][2]).equal("upload-skill-package"); + expect(httpClient.putByUrl.args[0][3]).equal(false); + expect(err).equal(null); + expect(res).deep.equal({ + uploadUrl: TEST_UPLOAD_URL, + }); + done(); + }); + }); + }); - it('| returns the correct list when there is no file in the model folder', () => { - // setup - sinon.stub(path, 'join').returns(''); - sinon.stub(fs, 'readdirSync').returns([]); - // call & verify - expect(skillMetaController.getInteractionModelLocales()).deep.equal({}); - }); + describe("# test class method: getInteractionModelLocales", () => { + let skillMetaController; - it('| returns the correct result when some locale exist some do not', () => { - // setup - sinon.stub(fs, 'readdirSync').returns(['a/b/en-US.json', '/d/e/en.json', '/f/g/en-US', 'en-US', 'de-DE.json']); - // call & verify - expect(skillMetaController.getInteractionModelLocales()['en-US'].endsWith(path.join('a', 'b', 'en-US.json'))).equal(true); - expect(skillMetaController.getInteractionModelLocales()['de-DE'].endsWith('de-DE.json')).equal(true); - }); + beforeEach(() => { + skillMetaController = new SkillMetadataController(TEST_CONFIGURATION); }); - describe('# test class method: _createUploadUrl', () => { - const skillMetaController = new SkillMetadataController(TEST_CONFIGURATION); + it("| returns the correct list when there is no file in the model folder", () => { + // setup + sinon.stub(path, "join").returns(""); + sinon.stub(fs, "readdirSync").returns([]); + // call & verify + expect(skillMetaController.getInteractionModelLocales()).deep.equal({}); + }); - beforeEach(() => { - new ResourcesConfig(FIXTURE_RESOURCES_CONFIG_FILE_PATH); - sinon.stub(AuthorizationController.prototype, 'tokenRefreshAndRead').callsArgWith(1); - }); + it("| returns the correct result when some locale exist some do not", () => { + // setup + sinon.stub(fs, "readdirSync").returns(["a/b/en-US.json", "/d/e/en.json", "/f/g/en-US", "en-US", "de-DE.json"]); + // call & verify + expect(skillMetaController.getInteractionModelLocales()["en-US"].endsWith(path.join("a", "b", "en-US.json"))).equal(true); + expect(skillMetaController.getInteractionModelLocales()["de-DE"].endsWith("de-DE.json")).equal(true); + }); + }); - afterEach(() => { - ResourcesConfig.dispose(); - sinon.restore(); - }); + describe("# test class method: _createUploadUrl", () => { + let skillMetaController; - it('| skillPackageSrc create upload fails, expect callback error', (done) => { - // setup - sinon.stub(httpClient, 'request').callsArgWith(3, 'createUploadErr'); // stub smapi request - // call - skillMetaController._createUploadUrl((err, res) => { - // verify - expect(res).equal(undefined); - expect(err).equal('createUploadErr'); - done(); - }); - }); + beforeEach(() => { + skillMetaController = new SkillMetadataController(TEST_CONFIGURATION); + sinon.stub(AuthorizationController.prototype, "tokenRefreshAndRead").callsArgWith(1); + }); - it('| skillPackageSrc create upload returns error response, expect callback error', (done) => { - // setup - sinon.stub(httpClient, 'request').callsArgWith(3, null, { - statusCode: 403, - body: { - error: 'message' - } - }); // stub smapi request - // call - skillMetaController._createUploadUrl((err, res) => { - // verify - expect(res).equal(undefined); - expect(err).equal(jsonView.toString({ error: 'message' })); - done(); - }); - }); + it("| skillPackageSrc create upload fails, expect callback error", (done) => { + // setup + sinon.stub(httpClient, "request").callsArgWith(3, "createUploadErr"); // stub smapi request + // call + skillMetaController._createUploadUrl((err, res) => { + // verify + expect(res).equal(undefined); + expect(err).equal("createUploadErr"); + done(); + }); + }); - it('| skillPackageSrc create upload succeeds, expect callback with createUpload response', (done) => { - // setup - sinon.stub(httpClient, 'request').callsArgWith(3, null, { - statusCode: 200, - headers: {}, - body: { - uploadUrl: TEST_UPLOAD_URL, - expiresAt: TEST_EXPIRES_AT - } - }); // stub smapi request - // call - skillMetaController._createUploadUrl((err, res) => { - // verify - expect(err).equal(null); - expect(res).deep.equal({ - uploadUrl: TEST_UPLOAD_URL, - expiresAt: TEST_EXPIRES_AT - }); - done(); - }); - }); + it("| skillPackageSrc create upload returns error response, expect callback error", (done) => { + // setup + sinon.stub(httpClient, "request").callsArgWith(3, null, { + statusCode: 403, + body: { + error: "message", + }, + }); // stub smapi request + // call + skillMetaController._createUploadUrl((err, res) => { + // verify + expect(res).equal(undefined); + expect(err).equal(jsonView.toString({error: "message"})); + done(); + }); }); - describe('# test class method: _importPackage', () => { - const skillMetaController = new SkillMetadataController(TEST_CONFIGURATION); + it("| skillPackageSrc create upload succeeds, expect callback with createUpload response", (done) => { + // setup + sinon.stub(httpClient, "request").callsArgWith(3, null, { + statusCode: 200, + headers: {}, + body: { + uploadUrl: TEST_UPLOAD_URL, + expiresAt: TEST_EXPIRES_AT, + }, + }); // stub smapi request + // call + skillMetaController._createUploadUrl((err, res) => { + // verify + expect(err).equal(null); + expect(res).deep.equal({ + uploadUrl: TEST_UPLOAD_URL, + expiresAt: TEST_EXPIRES_AT, + }); + done(); + }); + }); + }); - beforeEach(() => { - new ResourcesConfig(FIXTURE_RESOURCES_CONFIG_FILE_PATH); - sinon.stub(AuthorizationController.prototype, 'tokenRefreshAndRead').callsArgWith(1); - }); + describe("# test class method: _importPackage", () => { + let skillMetaController; - afterEach(() => { - ResourcesConfig.dispose(); - sinon.restore(); - }); + beforeEach(() => { + skillMetaController = new SkillMetadataController(TEST_CONFIGURATION); + sinon.stub(AuthorizationController.prototype, "tokenRefreshAndRead").callsArgWith(1); + }); - it('| import package fails, expect callback error', (done) => { - // setup - sinon.stub(httpClient, 'request').callsArgWith(3, 'importErr'); // stub smapi request - // call - skillMetaController._importPackage(TEST_SKILL_ID, TEST_VENDOR_ID, TEST_LOCATION_URL, (err, res) => { - // verify - expect(res).equal(undefined); - expect(err).equal('importErr'); - done(); - }); - }); + it("| import package fails, expect callback error", (done) => { + // setup + sinon.stub(httpClient, "request").callsArgWith(3, "importErr"); // stub smapi request + // call + skillMetaController._importPackage(TEST_SKILL_ID, TEST_VENDOR_ID, TEST_LOCATION_URL, (err, res) => { + // verify + expect(res).equal(undefined); + expect(err).equal("importErr"); + done(); + }); + }); - it('| import package returns error response, expect callback error', (done) => { - // setup - sinon.stub(httpClient, 'request').callsArgWith(3, null, { - statusCode: 403, - body: { - error: 'message' - } - }); // stub smapi request - // call - skillMetaController._importPackage(TEST_SKILL_ID, TEST_VENDOR_ID, TEST_LOCATION_URL, (err, res) => { - // verify - expect(res).equal(undefined); - expect(err).equal(jsonView.toString({ error: 'message' })); - done(); - }); - }); + it("| import package returns error response, expect callback error", (done) => { + // setup + sinon.stub(httpClient, "request").callsArgWith(3, null, { + statusCode: 403, + body: { + error: "message", + }, + }); // stub smapi request + // call + skillMetaController._importPackage(TEST_SKILL_ID, TEST_VENDOR_ID, TEST_LOCATION_URL, (err, res) => { + // verify + expect(res).equal(undefined); + expect(err).equal(jsonView.toString({error: "message"})); + done(); + }); + }); - it('| import package succeeds, expect callback with createUpload response', (done) => { - // setup - sinon.stub(httpClient, 'request').callsArgWith(3, null, { - statusCode: 200, - headers: {}, - body: { - response: 'response' - } - }); // stub smapi request - // call - skillMetaController._importPackage(TEST_SKILL_ID, TEST_VENDOR_ID, TEST_LOCATION_URL, (err, res) => { - // verify - expect(err).equal(null); - expect(res).deep.equal({ - statusCode: 200, - headers: {}, - body: { - response: 'response' - } - }); - done(); - }); - }); + it("| import package succeeds, expect callback with createUpload response", (done) => { + // setup + sinon.stub(httpClient, "request").callsArgWith(3, null, { + statusCode: 200, + headers: {}, + body: { + response: "response", + }, + }); // stub smapi request + // call + skillMetaController._importPackage(TEST_SKILL_ID, TEST_VENDOR_ID, TEST_LOCATION_URL, (err, res) => { + // verify + expect(err).equal(null); + expect(res).deep.equal({ + statusCode: 200, + headers: {}, + body: { + response: "response", + }, + }); + done(); + }); }); + }); - describe('# test class method: _exportPackage', () => { - const skillMetaController = new SkillMetadataController(TEST_CONFIGURATION); + describe("# test class method: _exportPackage", () => { + let skillMetaController; - beforeEach(() => { - sinon.stub(AuthorizationController.prototype, 'tokenRefreshAndRead').callsArgWith(1); - }); + beforeEach(() => { + skillMetaController = new SkillMetadataController(TEST_CONFIGURATION); + sinon.stub(AuthorizationController.prototype, "tokenRefreshAndRead").callsArgWith(1); + }); - afterEach(() => { - sinon.restore(); - }); + it("| export package fails, expect callback error", (done) => { + // setup + sinon.stub(httpClient, "request").callsArgWith(3, "exportErr"); // stub smapi request + // call + skillMetaController._exportPackage(TEST_SKILL_ID, CONSTANTS.SKILL.STAGE.DEVELOPMENT, (err, res) => { + // verify + expect(res).equal(undefined); + expect(err).equal("exportErr"); + done(); + }); + }); - it('| export package fails, expect callback error', (done) => { - // setup - sinon.stub(httpClient, 'request').callsArgWith(3, 'exportErr'); // stub smapi request - // call - skillMetaController._exportPackage(TEST_SKILL_ID, CONSTANTS.SKILL.STAGE.DEVELOPMENT, (err, res) => { - // verify - expect(res).equal(undefined); - expect(err).equal('exportErr'); - done(); - }); - }); + it("| export package returns error response, expect callback error", (done) => { + // setup + sinon.stub(httpClient, "request").callsArgWith(3, null, { + statusCode: 403, + body: { + error: "message", + }, + }); // stub smapi request + // call + skillMetaController._exportPackage(TEST_SKILL_ID, CONSTANTS.SKILL.STAGE.DEVELOPMENT, (err, res) => { + // verify + expect(res).equal(undefined); + expect(err).equal(jsonView.toString({error: "message"})); + done(); + }); + }); - it('| export package returns error response, expect callback error', (done) => { - // setup - sinon.stub(httpClient, 'request').callsArgWith(3, null, { - statusCode: 403, - body: { - error: 'message' - } - }); // stub smapi request - // call - skillMetaController._exportPackage(TEST_SKILL_ID, CONSTANTS.SKILL.STAGE.DEVELOPMENT, (err, res) => { - // verify - expect(res).equal(undefined); - expect(err).equal(jsonView.toString({ error: 'message' })); - done(); - }); - }); + it("| export package succeeds, expect callback with export response", (done) => { + // setup + sinon.stub(httpClient, "request").callsArgWith(3, null, { + statusCode: 200, + headers: {}, + body: { + response: "response", + }, + }); // stub smapi request + // call + skillMetaController._exportPackage(TEST_SKILL_ID, CONSTANTS.SKILL.STAGE.DEVELOPMENT, (err, res) => { + // verify + expect(err).equal(null); + expect(res).deep.equal({ + statusCode: 200, + headers: {}, + body: { + response: "response", + }, + }); + done(); + }); + }); + }); + + describe("# test class method: _pollImportStatus", () => { + const smapiImportStatusResponse200 = { + statusCode: 200, + body: { + status: "SUCCEEDED", + skill: { + resources: [ + { + name: "InteractionModel.en-US", + status: "SUCCEEDED", + }, + { + name: "InteractionModel.en-CA", + status: "SUCCEEDED", + }, + { + name: "Manifest", + status: "SUCCEEDED", + }, + ], + skillId: TEST_SKILL_ID, + }, + }, + headers: {}, + }; + const smapiImportStatusResponseInProgress = { + statusCode: 200, + body: { + status: "IN_PROGRESS", + skill: { + resources: [ + { + name: "InteractionModel.en-US", + status: "IN_PROGRESS", + }, + { + name: "InteractionModel.en-CA", + status: "IN_PROGRESS", + }, + { + name: "Manifest", + status: "IN_PROGRESS", + }, + ], + skillId: TEST_SKILL_ID, + }, + }, + headers: {}, + }; + const smapiImportStatusResponse200Failed = { + statusCode: 200, + body: { + status: "FAILED", + skill: { + resources: [ + { + name: "InteractionModel.en-US", + status: "FAILED", + }, + { + name: "InteractionModel.en-CA", + status: "FAILED", + }, + { + name: "Manifest", + status: "FAILED", + }, + ], + skillId: TEST_SKILL_ID, + }, + }, + headers: {}, + }; + const smapiImportStatusResponse403 = { + statusCode: 403, + body: { + error: "message", + }, + }; + const smapiImportStatusResponse200EmptyResources = { + statusCode: 200, + body: { + status: "SUCCEEDED", + skill: { + resources: [], + skillId: TEST_SKILL_ID, + }, + }, + headers: {}, + }; + const smapiImportStatusResponseWithWarningsInProgress = { + statusCode: 200, + body: { + status: "IN_PROGRESS", + skill: { + resources: [ + { + name: "InteractionModel.en-US", + status: "IN_PROGRESS", + }, + ], + skillId: TEST_SKILL_ID, + }, + warnings: [ + { + message: "test-warning", + }, + ], + }, + headers: {}, + }; + const smapiImportStatusResponseWithWarnings200 = { + statusCode: 200, + body: { + status: "SUCCEEDED", + skill: { + resources: [ + { + name: "InteractionModel.en-US", + status: "SUCCEEDED", + }, + ], + skillId: TEST_SKILL_ID, + }, + warnings: [ + { + message: "test-warning", + }, + ], + }, + headers: {}, + }; + let requestStub; + let importStatusStub; + let skillMetaController; + + beforeEach(() => { + skillMetaController = new SkillMetadataController(TEST_CONFIGURATION); + sinon.stub(AuthorizationController.prototype, "tokenRefreshAndRead").callsArgWith(1); + sinon.stub(ImportStatusView.prototype, "displayImportId").returns(); + requestStub = sinon.stub(httpClient, "request"); + }); - it('| export package succeeds, expect callback with export response', (done) => { - // setup - sinon.stub(httpClient, 'request').callsArgWith(3, null, { - statusCode: 200, - headers: {}, - body: { - response: 'response' - } - }); // stub smapi request - // call - skillMetaController._exportPackage(TEST_SKILL_ID, CONSTANTS.SKILL.STAGE.DEVELOPMENT, (err, res) => { - // verify - expect(err).equal(null); - expect(res).deep.equal({ - statusCode: 200, - headers: {}, - body: { - response: 'response' - } - }); - done(); - }); - }); + it("| poll status with getImportStatus fails, expect callback error", (done) => { + // setup + requestStub.callsArgWith(3, "pollErr"); // stub smapi request + // call + skillMetaController._pollImportStatus(TEST_IMPORT_ID, (err, res) => { + // verify + expect(res).equal(null); + expect(err).equal("pollErr"); + done(); + }); + }).timeout(20000); + + it("| poll status with getImportStatus return error response, expect callback error", (done) => { + // setup + requestStub.callsArgWith(3, null, { + statusCode: 403, + body: { + error: "message", + }, + }); // stub smapi request + // call + skillMetaController._pollImportStatus(TEST_IMPORT_ID, (err, res) => { + // verify + expect(res).equal(null); + expect(err).equal(jsonView.toString({error: "message"})); + done(); + }); + }).timeout(20000); + + it("| poll status with getImportStatus return success, expect callback with getImportStatus response", (done) => { + // setup + requestStub.callsArgWith(3, null, { + statusCode: 200, + body: { + status: CONSTANTS.SKILL.PACKAGE_STATUS.SUCCEEDED, + }, + headers: {}, + }); // stub smapi request + // call + skillMetaController._pollImportStatus(TEST_IMPORT_ID, (err, res) => { + // verify + expect(err).equal(null); + expect(res).deep.equal({ + statusCode: 200, + body: { + status: CONSTANTS.SKILL.PACKAGE_STATUS.SUCCEEDED, + }, + headers: {}, + }); + done(); + }); + }).timeout(20000); + + it("| poll status with getImportStatus warnings, expect warnings logged", (done) => { + // setup + requestStub.callsArgWith(3, null, smapiImportStatusResponseWithWarnings200); + + // call + skillMetaController._pollImportStatus(TEST_IMPORT_ID, (err, res) => { + // verify + expect(err).equal(null); + expect(res).deep.equal(smapiImportStatusResponseWithWarnings200); + done(); + }); + }).timeout(3000); + + it("| poll status retries with getImportStatus warnings, expects warnings logged once", (done) => { + // setup + requestStub + .onCall(0) + .callsArgWith(3, null, smapiImportStatusResponseWithWarningsInProgress) + .onCall(1) + .callsArgWith(3, null, smapiImportStatusResponseWithWarnings200); + + // call + skillMetaController._pollImportStatus(TEST_IMPORT_ID, (err, res) => { + // verify + expect(err).equal(null); + expect(res).deep.equal(smapiImportStatusResponseWithWarnings200); + done(); + }); + }).timeout(3000); + + describe("for Alexa Conversation builds ", () => { + const smapiSkillStatusResponse200 = { + statusCode: 200, + body: { + interactionModel: { + "en-US": { + lastUpdateRequest: { + status: "SUCCEEDED", + buildDetails: { + steps: [ + { + name: "LANGUAGE_MODEL_QUICK_BUILD", + status: "SUCCEEDED", + }, + { + name: "LANGUAGE_MODEL_FULL_BUILD", + status: "SUCCEEDED", + }, + { + name: "ALEXA_CONVERSATIONS_QUICK_BUILD", + status: "SUCCEEDED", + }, + { + name: "ALEXA_CONVERSATIONS_FULL_BUILD", + status: "SUCCEEDED", + }, + ], + }, + }, + }, + }, + }, + headers: {}, + }; + const smapiSkillStatusResponse200QuickBuildSucceeded = { + statusCode: 200, + body: { + interactionModel: { + "en-US": { + lastUpdateRequest: { + status: "IN_PROGRESS", + buildDetails: { + steps: [ + { + name: "ALEXA_CONVERSATIONS_QUICK_BUILD", + status: "SUCCEEDED", + }, + { + name: "ALEXA_CONVERSATIONS_FULL_BUILD", + }, + ], + }, + }, + }, + }, + }, + headers: {}, + }; + const smapiSkillStatusResponse200InProgress = { + statusCode: 200, + body: { + interactionModel: { + "en-US": { + lastUpdateRequest: { + status: "IN_PROGRESS", + buildDetails: { + steps: [ + { + name: "ALEXA_CONVERSATIONS_QUICK_BUILD", + status: "IN_PROGRESS", + }, + ], + }, + }, + }, + }, + }, + headers: {}, + }; + const smapiSkillStatusResponse200BothLocalesInProgress = { + statusCode: 200, + body: { + interactionModel: { + "en-US": { + lastUpdateRequest: { + status: "IN_PROGRESS", + buildDetails: { + steps: [ + { + name: "ALEXA_CONVERSATIONS_QUICK_BUILD", + status: "IN_PROGRESS", + }, + ], + }, + }, + }, + "en-CA": { + lastUpdateRequest: { + status: "IN_PROGRESS", + buildDetails: { + steps: [ + { + name: "ALEXA_CONVERSATIONS_QUICK_BUILD", + status: "IN_PROGRESS", + }, + ], + }, + }, + }, + }, + }, + headers: {}, + }; + const smapiSkillStatusResponse200Failed = { + statusCode: 200, + body: { + interactionModel: { + "en-US": { + lastUpdateRequest: { + status: "FAILED", + buildDetails: { + steps: [ + { + name: "LANGUAGE_MODEL_QUICK_BUILD", + status: "SUCCEEDED", + }, + { + name: "LANGUAGE_MODEL_FULL_BUILD", + status: "FAILED", + }, + { + name: "ALEXA_CONVERSATIONS_QUICK_BUILD", + status: "SUCCEEDED", + }, + { + name: "ALEXA_CONVERSATIONS_FULL_BUILD", + status: "FAILED", + }, + ], + }, + }, + }, + "en-CA": { + lastUpdateRequest: { + status: "FAILED", + buildDetails: { + steps: [ + { + name: "LANGUAGE_MODEL_QUICK_BUILD", + status: "FAILED", + }, + { + name: "LANGUAGE_MODEL_FULL_BUILD", + status: "FAILED", + }, + { + name: "ALEXA_CONVERSATIONS_QUICK_BUILD", + status: "FAILED", + }, + { + name: "ALEXA_CONVERSATIONS_FULL_BUILD", + status: "FAILED", + }, + ], + }, + }, + }, + }, + }, + headers: {}, + }; + const smapiSkillStatusNoACBuildResponse200 = { + statusCode: 200, + body: { + interactionModel: { + "en-US": { + lastUpdateRequest: { + status: "SUCCEEDED", + buildDetails: { + steps: [ + { + name: "LANGUAGE_MODEL_QUICK_BUILD", + status: "SUCCEEDED", + }, + { + name: "LANGUAGE_MODEL_FULL_BUILD", + status: "SUCCEEDED", + }, + ], + }, + }, + }, + }, + }, + headers: {}, + }; + const smapiImportStatusResponse200EmptySkillID = { + statusCode: 200, + body: { + status: "SUCCEEDED", + skill: { + resources: [ + { + name: "InteractionModel.en-US", + status: "SUCCEEDED", + }, + { + name: "InteractionModel.en-CA", + status: "SUCCEEDED", + }, + ], + skillId: "", + }, + }, + headers: {}, + }; + let skillStatusStub; + + beforeEach(() => { + isAcSkillStub.returns(true); + }); + + it("| poll import status with skill status with no AC Build information, expect callback with no AC Build information", (done) => { + // setup + skillStatusStub = requestStub.withArgs(sinon.match.any, "get-skill-status"); + importStatusStub = requestStub.withArgs(sinon.match.any, "get-import-status"); + skillStatusStub.callsArgWith(3, null, smapiSkillStatusNoACBuildResponse200); + importStatusStub.callsArgWith(3, null, smapiImportStatusResponse200); + // call + skillMetaController._pollImportStatus(TEST_IMPORT_ID, (err, res) => { + // verify + expect(err).equal(null); + expect(res).deep.equal(smapiImportStatusResponse200); + done(); + }); + }); + + it("| poll import status with skill status with AC Build In Progress, expect callback with no AC Build information", (done) => { + // setup + skillStatusStub = requestStub.withArgs(sinon.match.any, "get-skill-status"); + importStatusStub = requestStub.withArgs(sinon.match.any, "get-import-status"); + skillStatusStub.callsArgWith(3, null, smapiSkillStatusResponse200InProgress); + importStatusStub.callsArgWith(3, null, smapiImportStatusResponse200); + // call + skillMetaController._pollImportStatus(TEST_IMPORT_ID, (err, res) => { + // verify + expect(err).equal(null); + expect(res).deep.equal(smapiImportStatusResponse200); + done(); + }); + }); + + it("| poll import status with multiple retries, expect callback with correct response", (done) => { + // setup + requestStub + .onCall(0) + .callsArgWith(3, null, smapiImportStatusResponseInProgress) + .onCall(1) + .callsArgWith(3, null, smapiSkillStatusResponse200QuickBuildSucceeded) + .onCall(2) + .callsArgWith(3, null, smapiImportStatusResponse200) + .onCall(3) + .callsArgWith(3, null, smapiSkillStatusResponse200); + // call + skillMetaController._pollImportStatus(TEST_IMPORT_ID, (err, res) => { + // verify + expect(err).equal(null); + expect(res).deep.equal(smapiImportStatusResponse200); + done(); + }); + }).timeout(20000000); + + it("| poll status with getImportStatus return error response, expect callback error", (done) => { + // setup + skillStatusStub = requestStub.withArgs(sinon.match.any, "get-skill-status"); + importStatusStub = requestStub.withArgs(sinon.match.any, "get-import-status"); + skillStatusStub.callsArgWith(3, null, smapiSkillStatusResponse200); + importStatusStub.callsArgWith(3, null, smapiImportStatusResponse403); + // call + skillMetaController._pollImportStatus(TEST_IMPORT_ID, (err, res) => { + // verify + expect(res).equal(null); + expect(err).equal(jsonView.toString({error: "message"})); + expect(skillStatusStub.called).equal(false); + done(); + }); + }); + + it("| poll import status with getSkillStatus fails, expect callback error", (done) => { + // setup + skillStatusStub = requestStub.withArgs(sinon.match.any, "get-skill-status"); + importStatusStub = requestStub.withArgs(sinon.match.any, "get-import-status"); + skillStatusStub.callsArgWith(3, "skillStatusErr"); + importStatusStub.callsArgWith(3, null, smapiImportStatusResponse200); + // call + skillMetaController._pollImportStatus(TEST_IMPORT_ID, (err, res) => { + // verify + expect(res).equal(null); + expect(err).equal("skillStatusErr"); + done(); + }); + }); + + it("| poll import status with getSkillStatus build failures", (done) => { + // setup + requestStub + .onCall(0) + .callsArgWith(3, null, smapiImportStatusResponseInProgress) + .onCall(1) + .callsArgWith(3, null, smapiSkillStatusResponse200BothLocalesInProgress) + .onCall(2) + .callsArgWith(3, null, smapiImportStatusResponse200Failed) + .onCall(3) + .callsArgWith(3, null, smapiSkillStatusResponse200Failed); + + // call + skillMetaController._pollImportStatus(TEST_IMPORT_ID, (err, res) => { + // verify + expect(err).equal(null); + expect(res).deep.equal(smapiImportStatusResponse200Failed); + done(); + }); + }).timeout(3000); + + it("| poll status smapi calls return success, expect GetSkillStatus calls", (done) => { + // setup + requestStub + .onCall(0) + .callsArgWith(3, null, smapiImportStatusResponseInProgress) + .onCall(1) + .callsArgWith(3, null, smapiSkillStatusResponse200InProgress) + .onCall(2) + .callsArgWith(3, null, smapiImportStatusResponse200) + .onCall(3) + .callsArgWith(3, null, smapiSkillStatusResponse200); + // call + skillMetaController._pollImportStatus(TEST_IMPORT_ID, (err, res) => { + // verify + expect(err).equal(null); + expect(res).deep.equal(smapiImportStatusResponse200); + done(); + }); + }).timeout(3000); + + it("| poll status smapi calls return empty SkillID, expect no GetSkillStatus calls", (done) => { + // setup + requestStub + .onCall(0) + .callsArgWith(3, null, smapiImportStatusResponse200EmptySkillID) + .onCall(1) + .callsArgWith(3, null, smapiSkillStatusResponse200InProgress) + .onCall(2) + .callsArgWith(3, null, smapiImportStatusResponse200EmptySkillID) + .onCall(3) + .callsArgWith(3, null, smapiSkillStatusResponse200); + + // call + skillMetaController._pollImportStatus(TEST_IMPORT_ID, (err, res) => { + // verify + expect(err).equal(null); + expect(res).deep.equal(smapiImportStatusResponse200EmptySkillID); + expect(requestStub.callCount).equals(1); + done(); + }); + }); + + it("| poll status smapi calls doesn't print any messages if the import status doesn't go to in progress", (done) => { + // setup + skillStatusStub = requestStub.withArgs(sinon.match.any, "get-skill-status"); + importStatusStub = requestStub.withArgs(sinon.match.any, "get-import-status"); + skillStatusStub.callsArgWith(3, null, smapiSkillStatusResponse200); + importStatusStub.callsArgWith(3, null, smapiImportStatusResponse200EmptyResources); + + // call + skillMetaController._pollImportStatus(TEST_IMPORT_ID, (err, res) => { + // verify + expect(err).equal(null); + expect(res).deep.equal(smapiImportStatusResponse200EmptyResources); + expect(requestStub.callCount).equals(2); + done(); + }); + }).timeout(20000); }); + }); - describe('# test class method: _pollImportStatus', () => { - const skillMetaController = new SkillMetadataController(TEST_CONFIGURATION); + describe("# test class method: _pollExportStatus", () => { + let skillMetaController; - beforeEach(() => { - new ResourcesConfig(FIXTURE_RESOURCES_CONFIG_FILE_PATH); - sinon.stub(AuthorizationController.prototype, 'tokenRefreshAndRead').callsArgWith(1); - }); + beforeEach(() => { + skillMetaController = new SkillMetadataController(TEST_CONFIGURATION); + sinon.stub(AuthorizationController.prototype, "tokenRefreshAndRead").callsArgWith(1); + }); - afterEach(() => { - ResourcesConfig.dispose(); - sinon.restore(); - }); + it("| poll status with getExportStatus fails, expect callback error", (done) => { + // setup + sinon.stub(httpClient, "request").callsArgWith(3, "pollErr"); // stub smapi request + // call + skillMetaController._pollExportStatus(TEST_EXPORT_ID, (err, res) => { + // verify + expect(res).equal(null); + expect(err).equal("pollErr"); + done(); + }); + }); - it('| poll status with getImportStatus fails, expect callback error', (done) => { - // setup - sinon.stub(httpClient, 'request').callsArgWith(3, 'pollErr'); // stub smapi request - // call - skillMetaController._pollImportStatus(TEST_IMPORT_ID, (err, res) => { - // verify - expect(res).equal(null); - expect(err).equal('pollErr'); - done(); - }); - }).timeout(20000); - - it('| poll status with getImportStatus return error response, expect callback error', (done) => { - // setup - sinon.stub(httpClient, 'request').callsArgWith(3, null, { - statusCode: 403, - body: { - error: 'message' - } - }); // stub smapi request - // call - skillMetaController._pollImportStatus(TEST_IMPORT_ID, (err, res) => { - // verify - expect(res).equal(null); - expect(err).equal(jsonView.toString({ error: 'message' })); - done(); - }); - }).timeout(20000); - - it('| poll status with getImportStatus return success, expect callback with getImportStatus response', (done) => { - // setup - sinon.stub(httpClient, 'request').callsArgWith(3, null, { - statusCode: 200, - body: { - status: CONSTANTS.SKILL.PACKAGE_STATUS.SUCCEEDED - }, - headers: {} - }); // stub smapi request - // call - skillMetaController._pollImportStatus(TEST_IMPORT_ID, (err, res) => { - // verify - expect(err).equal(null); - expect(res).deep.equal({ - statusCode: 200, - body: { - status: CONSTANTS.SKILL.PACKAGE_STATUS.SUCCEEDED - }, - headers: {} - }); - done(); - }); - }).timeout(20000); + it("| poll status with getExportStatus return error response, expect callback error", (done) => { + // setup + sinon.stub(httpClient, "request").callsArgWith(3, null, { + statusCode: 403, + body: { + error: "message", + }, + }); // stub smapi request + // call + skillMetaController._pollExportStatus(TEST_EXPORT_ID, (err, res) => { + // verify + expect(res).equal(null); + expect(err).equal(jsonView.toString({error: "message"})); + done(); + }); }); - describe('# test class method: _pollExportStatus', () => { - const skillMetaController = new SkillMetadataController(TEST_CONFIGURATION); + it("| poll status with getExportStatus return success, expect callback with getExportStatus response", (done) => { + // setup + const response = { + statusCode: 200, + body: { + status: CONSTANTS.SKILL.PACKAGE_STATUS.SUCCEEDED, + }, + headers: {}, + }; + sinon.stub(httpClient, "request").callsArgWith(3, null, response); // stub smapi request + // call + skillMetaController._pollExportStatus(TEST_EXPORT_ID, (err, res) => { + // verify + expect(err).equal(null); + expect(res).deep.equal(response); + done(); + }); + }); + }); - beforeEach(() => { - sinon.stub(AuthorizationController.prototype, 'tokenRefreshAndRead').callsArgWith(1); - }); + describe("# test class method: updateSkillManifest", () => { + let skillMetaController; - afterEach(() => { - sinon.restore(); - }); + beforeEach(() => { + skillMetaController = new SkillMetadataController(TEST_CONFIGURATION); + sinon.stub(AuthorizationController.prototype, "tokenRefreshAndRead").callsArgWith(1); + ResourcesConfig.getInstance().setSkillId(TEST_PROFILE, null); + }); - it('| poll status with getExportStatus fails, expect callback error', (done) => { - // setup - sinon.stub(httpClient, 'request').callsArgWith(3, 'pollErr'); // stub smapi request - // call - skillMetaController._pollExportStatus(TEST_EXPORT_ID, (err, res) => { - // verify - expect(res).equal(null); - expect(err).equal('pollErr'); - done(); - }); - }); + it("| smapi update manifest fails, expect callback error", (done) => { + // setup + sinon.stub(httpClient, "request").callsArgWith(3, "smapiError"); + + // call + skillMetaController.updateSkillManifest((err, res) => { + // verify + expect(res).equal(undefined); + expect(err).equal("smapiError"); + done(); + }); + }); - it('| poll status with getExportStatus return error response, expect callback error', (done) => { - // setup - sinon.stub(httpClient, 'request').callsArgWith(3, null, { - statusCode: 403, - body: { - error: 'message' - } - }); // stub smapi request - // call - skillMetaController._pollExportStatus(TEST_EXPORT_ID, (err, res) => { - // verify - expect(res).equal(null); - expect(err).equal(jsonView.toString({ error: 'message' })); - done(); - }); - }); + it("| update manifest callback with error when poll skill status fails", (done) => { + // setup + sinon.stub(httpClient, "request").callsArgWith(3, null, {}); + sinon.stub(SkillMetadataController.prototype, "_pollSkillManifestStatus").callsArgWith(2, "TEST_ERROR"); + + // call + skillMetaController.updateSkillManifest((err, res) => { + // verify + expect(err).equal("TEST_ERROR"); + done(); + }); + }); - it('| poll status with getExportStatus return success, expect callback with getExportStatus response', (done) => { - // setup - sinon.stub(httpClient, 'request').callsArgWith(3, null, { - statusCode: 200, - body: { - status: CONSTANTS.SKILL.PACKAGE_STATUS.SUCCEEDED - }, - headers: {} - }); // stub smapi request - // call - skillMetaController._pollExportStatus(TEST_EXPORT_ID, (err, res) => { - // verify - expect(err).equal(null); - expect(res).deep.equal({ - statusCode: 200, - body: { - status: CONSTANTS.SKILL.PACKAGE_STATUS.SUCCEEDED - }, - headers: {} - }); - done(); - }); - }); + it("| update manifest callsback with error when poll status is failed", (done) => { + // setup + const pollResponse = { + body: { + manifest: { + lastUpdateRequest: { + status: "FAILED", + }, + }, + }, + }; + + sinon.stub(SkillMetadataController.prototype, "_pollSkillManifestStatus").callsArgWith(2, undefined, pollResponse); + sinon.stub(httpClient, "request").callsArgWith(3, null, {}); + + // call + skillMetaController.updateSkillManifest((err, res) => { + // verify + expect(err).equal("[Error]: Updating skill manifest but received non-success message from SMAPI: FAILED"); + done(); + }); + }); + + it("| update manifest calls back when poll skill status succeeds", (done) => { + // setup + const pollResponse = { + body: { + manifest: { + lastUpdateRequest: { + status: CONSTANTS.SKILL.SKILL_STATUS.SUCCEEDED, + }, + }, + }, + }; + + sinon.stub(SkillMetadataController.prototype, "_pollSkillManifestStatus").callsArgWith(2, undefined, pollResponse); + sinon.stub(httpClient, "request").callsArgWith(3, null, {}); + + // call + skillMetaController.updateSkillManifest((err, res) => { + // verify + expect(err).equal(undefined); + done(); + }); }); + }); }); diff --git a/test/unit/controller/skill-simulation-controller-test.js b/test/unit/controller/skill-simulation-controller-test.js deleted file mode 100644 index f3dcd2dc..00000000 --- a/test/unit/controller/skill-simulation-controller-test.js +++ /dev/null @@ -1,191 +0,0 @@ -const { expect } = require('chai'); -const sinon = require('sinon'); - -const jsonView = require('@src/view/json-view'); - -const SkillSimulationController = require('@src/controllers/skill-simulation-controller'); - -describe('Controller test - skill simulation controller test', () => { - describe('# test constructor', () => { - it('| constructor with config parameter returns SkillSimulationCotroller object', () => { - // call - const simulationController = new SkillSimulationController({ - profile: 'default', - debug: true, - skillId: 'a1b2c3', - locale: 'en-US', - stage: 'DEVELOPMENT' - }); - // verify - expect(simulationController).to.be.instanceOf(SkillSimulationController); - }); - - it('| constructor with empty config object returns SkillSimulationController object', () => { - // call - const simulationController = new SkillSimulationController({}); - // verify - expect(simulationController).to.be.instanceOf(SkillSimulationController); - }); - - it('| constructor with no args throws exception', () => { - try { - // call - new SkillSimulationController(); - } catch (err) { - // verify - expect(err).to.match(new RegExp('Cannot have an undefined configuration.')); - } - }); - }); - - describe('# test class method - startSkillSimulation', () => { - let simulateSkillStub; - let simulationController; - const TEST_MSG = 'TEST_MSG'; - - before(() => { - simulationController = new SkillSimulationController({}); - simulateSkillStub = sinon.stub(simulationController.smapiClient.skill.test, 'simulateSkill'); - }); - - after(() => { - sinon.restore(); - }); - - it('| test for SMAPI.test.simulateSkill gives correct 200 response', (done) => { - // setup - const TEST_RES = { - statusCode: 200, - headers: {}, - body: { - id: 'a1b2c3', - status: 'IN_PROGRESS', - result: null - } - }; - simulateSkillStub.callsArgWith(6, null, TEST_RES); - // call - simulationController.startSkillSimulation(TEST_MSG, true, (err, response) => { - // verify - expect(err).equal(null); - expect(response.statusCode).equal(200); - done(); - }); - }); - - it('| test for SMAPI.test.simulateSkill gives correct 300+ error', (done) => { - // setup - const TEST_RES = { - statusCode: 400, - headers: {}, - body: { - message: TEST_MSG - } - }; - simulateSkillStub.callsArgWith(6, null, TEST_RES); - // call - simulationController.startSkillSimulation(TEST_MSG, true, (err, response) => { - // verify - expect(err).to.equal(jsonView.toString(TEST_RES.body)); - expect(response).to.equal(undefined); - done(); - }); - }); - - it('| test for SMAPI.test.simulateSkill gives correct error', (done) => { - // setup - simulateSkillStub.callsArgWith(6, TEST_MSG, null); - // call - simulationController.startSkillSimulation(TEST_MSG, true, (err, response) => { - // verify - expect(err).to.equal(TEST_MSG); - expect(response).to.equal(undefined); - done(); - }); - }); - }); - - describe('# test class method - getSkillSimulationResult', () => { - let simulationController; - let getSimulationStub; - const TEST_MSG = 'TEST_MSG'; - - beforeEach(() => { - simulationController = new SkillSimulationController({}); - getSimulationStub = sinon.stub(simulationController.smapiClient.skill.test, 'getSimulation'); - }); - - afterEach(() => { - sinon.restore(); - }); - - it('| getSimulation polling terminates on SUCCESSFUL status received', (done) => { - // setup - const TEST_RES = { - statusCode: 200, - headers: {}, - body: { - status: 'SUCCESSFUL' - } - }; - getSimulationStub.callsArgWith(3, null, TEST_RES); - // call - simulationController.getSkillSimulationResult('', (err, response) => { - // verify - expect(err).equal(null); - expect(response.body.status).equal('SUCCESSFUL'); - done(); - }); - }); - - it('| getSimulation polling terminates on statusCode greater than 300', (done) => { - // setup - const TEST_RES = { - statusCode: 400, - headers: {}, - body: { - status: 'SUCCESSFUL' - } - }; - getSimulationStub.callsArgWith(3, null, TEST_RES); - // call - simulationController.getSkillSimulationResult('', (err, response) => { - // verify - expect(err).equal(jsonView.toString(TEST_RES.body)); - expect(response).equal(undefined); - done(); - }); - }); - - it('| getSimulation polling terminates on FAILED status received', (done) => { - // setup - const TEST_RES = { - statusCode: 200, - headers: {}, - body: { - status: 'FAILED' - } - }; - getSimulationStub.callsArgWith(3, null, TEST_RES); - // call - simulationController.getSkillSimulationResult('', (err, response) => { - // verify - expect(err).equal(null); - expect(response.body.status).equal('FAILED'); - done(); - }); - }); - - it('| getSimulation polling terminates when max retry is reached from request error', (done) => { - // setup - getSimulationStub.callsArgWith(3, TEST_MSG); - // call - simulationController.getSkillSimulationResult('', (err, response) => { - // verify - expect(err).equal(TEST_MSG); - expect(response).equal(undefined); - done(); - }); - }); - }); -}); diff --git a/test/unit/controller/skill-simulation-controller.spec.ts b/test/unit/controller/skill-simulation-controller.spec.ts new file mode 100644 index 00000000..5d1d2753 --- /dev/null +++ b/test/unit/controller/skill-simulation-controller.spec.ts @@ -0,0 +1,183 @@ +import {expect} from "chai"; +import sinon from "sinon"; + +import jsonView from "../../../lib/view/json-view"; + +import {SkillSimulationController, SkillSimulationControllerProps} from "../../../lib/controllers/skill-simulation-controller"; + +const skillSimulatorBaseProps: SkillSimulationControllerProps = { + profile: "default", + debug: true, + skillId: "a1b2c3", + locale: "en-US", + stage: "DEVELOPMENT", + saveSkillIo: "", +}; + +describe("Controller test - skill simulation controller test", () => { + describe("# test constructor", () => { + it("| constructor with config parameter returns SkillSimulationCotroller object", () => { + // call + const simulationController = new SkillSimulationController(skillSimulatorBaseProps); + // verify + expect(simulationController).to.be.instanceOf(SkillSimulationController); + }); + + it("| constructor with empty config object returns SkillSimulationController object", () => { + // call + const simulationController = new SkillSimulationController({} as any); + // verify + expect(simulationController).to.be.instanceOf(SkillSimulationController); + }); + + it("| constructor with no args throws exception", () => { + try { + // call + new SkillSimulationController({} as any); + } catch (err) { + // verify + expect(err).to.match(new RegExp("Cannot have an undefined configuration.")); + } + }); + }); + + describe("# test class method - startSkillSimulation", () => { + let simulateSkillStub: sinon.SinonStub; + let simulationController: SkillSimulationController; + const TEST_MSG = "TEST_MSG"; + + before(() => { + simulationController = new SkillSimulationController(skillSimulatorBaseProps); + simulateSkillStub = sinon.stub(simulationController.smapiClient.skill.test, "simulateSkill"); + }); + + after(() => { + sinon.restore(); + }); + + it("| test for SMAPI.test.simulateSkill gives correct 200 response", async () => { + // setup + const TEST_RES = { + statusCode: 200, + headers: {}, + body: { + id: "a1b2c3", + status: "IN_PROGRESS", + result: null, + }, + }; + simulateSkillStub.resolves(TEST_RES); + // call + const response = await simulationController.startSkillSimulation(TEST_MSG, true); + + expect(response.statusCode).equal(200); + }); + + it("| test for SMAPI.test.simulateSkill gives correct 300+ error", async () => { + // setup + const TEST_RES = { + statusCode: 400, + headers: {}, + body: { + message: TEST_MSG, + }, + }; + simulateSkillStub.resolves(TEST_RES); + // call + await expect(simulationController.startSkillSimulation(TEST_MSG, true)).rejectedWith(jsonView.toString(TEST_RES.body)); + }); + + it("| test for SMAPI.test.simulateSkill gives correct error", async () => { + // setup + simulateSkillStub.rejects(Error(TEST_MSG)); + // call + await expect(simulationController.startSkillSimulation(TEST_MSG, true)).rejectedWith(TEST_MSG); + }); + }); + + describe("# test class method - getSkillSimulationResult", () => { + let simulationController: SkillSimulationController; + let getSimulationStub: sinon.SinonStub; + const TEST_MSG = "TEST_MSG"; + + beforeEach(() => { + simulationController = new SkillSimulationController(skillSimulatorBaseProps); + getSimulationStub = sinon.stub(simulationController.smapiClient.skill.test, "getSimulation"); + }); + + afterEach(() => { + sinon.restore(); + }); + + it("| getSimulation polling terminates on SUCCESSFUL status received", async () => { + // setup + const TEST_RES = { + statusCode: 200, + headers: {}, + body: { + status: "SUCCESSFUL", + }, + }; + getSimulationStub.resolves(TEST_RES); + // call + const response = await simulationController.getSkillSimulationResult(""); + // verify + expect(response.body.status).equal("SUCCESSFUL"); + }); + + it("| getSimulation polling terminates on statusCode greater than 300", async () => { + // setup + const TEST_RES = { + statusCode: 400, + headers: {}, + body: { + status: "SUCCESSFUL", + }, + }; + getSimulationStub.resolves(TEST_RES); + // call + try { + await simulationController.getSkillSimulationResult(""); + } catch (err) { + // verify + expect((err as any).message).equal(jsonView.toString(TEST_RES.body)); + } + }); + + it("| getSimulation polling terminates on FAILED status received", async () => { + // setup + const TEST_RES = { + statusCode: 200, + headers: {}, + body: { + status: "FAILED", + result: { + error: { + message: "error msg", + }, + }, + }, + }; + getSimulationStub.resolves(TEST_RES); + // call + try { + await simulationController.getSkillSimulationResult(""); + } catch (err) { + // verify + expect((err as any).message).equal("Failed to simulate skill. Error: error msg"); + } + }); + + it("| getSimulation polling terminates when max retry is reached from request error", async () => { + // setup + getSimulationStub.rejects(TEST_MSG); + // call + try { + await simulationController.getSkillSimulationResult(""); + } catch (err) { + // verify + expect((err as any).message).equal(TEST_MSG); + } + }); + }); +}); diff --git a/test/unit/controller/skill-simulation-controller.test.ts b/test/unit/controller/skill-simulation-controller.test.ts new file mode 100644 index 00000000..964348a2 --- /dev/null +++ b/test/unit/controller/skill-simulation-controller.test.ts @@ -0,0 +1,183 @@ +import {expect} from "chai"; +import sinon from "sinon"; + +import jsonView from "../../../lib/view/json-view"; + +import {SkillSimulationController, SkillSimulationControllerProps} from "../../../lib/controllers/skill-simulation-controller"; + +const skillSimulatorBaseProps: SkillSimulationControllerProps = { + profile: "default", + debug: true, + skillId: "a1b2c3", + locale: "en-US", + stage: "DEVELOPMENT", + saveSkillIo: "", +}; + +describe("Controller test - skill simulation controller test", () => { + describe("# test constructor", () => { + it("| constructor with config parameter returns SkillSimulationCotroller object", () => { + // call + const simulationController = new SkillSimulationController(skillSimulatorBaseProps); + // verify + expect(simulationController).to.be.instanceOf(SkillSimulationController); + }); + + it("| constructor with empty config object returns SkillSimulationController object", () => { + // call + const simulationController = new SkillSimulationController({} as any); + // verify + expect(simulationController).to.be.instanceOf(SkillSimulationController); + }); + + it("| constructor with no args throws exception", () => { + try { + // call + new SkillSimulationController({} as any); + } catch (err) { + // verify + expect(err).to.match(new RegExp("Cannot have an undefined configuration.")); + } + }); + }); + + describe("# test class method - startSkillSimulation", () => { + let simulateSkillStub: sinon.SinonStub; + let simulationController: SkillSimulationController; + const TEST_MSG = "TEST_MSG"; + + before(() => { + simulationController = new SkillSimulationController(skillSimulatorBaseProps); + simulateSkillStub = sinon.stub(simulationController.smapiClient.skill.test, "simulateSkill"); + }); + + after(() => { + sinon.restore(); + }); + + it("| test for SMAPI.test.simulateSkill gives correct 200 response", async () => { + // setup + const TEST_RES = { + statusCode: 200, + headers: {}, + body: { + id: "a1b2c3", + status: "IN_PROGRESS", + result: null, + }, + }; + simulateSkillStub.resolves(TEST_RES); + // call + const response = await simulationController.startSkillSimulation(TEST_MSG, true); + + expect(response.statusCode).equal(200); + }); + + it("| test for SMAPI.test.simulateSkill gives correct 300+ error", async () => { + // setup + const TEST_RES = { + statusCode: 400, + headers: {}, + body: { + message: TEST_MSG, + }, + }; + simulateSkillStub.resolves(TEST_RES); + // call + await expect(simulationController.startSkillSimulation(TEST_MSG, true)).rejectedWith(jsonView.toString(TEST_RES.body)); + }); + + it("| test for SMAPI.test.simulateSkill gives correct error", async () => { + // setup + simulateSkillStub.rejects(Error(TEST_MSG)); + // call + await expect(simulationController.startSkillSimulation(TEST_MSG, true)).rejectedWith(TEST_MSG); + }); + }); + + describe("# test class method - getSkillSimulationResult", () => { + let simulationController: SkillSimulationController; + let getSimulationStub: sinon.SinonStub; + const TEST_MSG = "TEST_MSG"; + + beforeEach(() => { + simulationController = new SkillSimulationController(skillSimulatorBaseProps); + getSimulationStub = sinon.stub(simulationController.smapiClient.skill.test, "getSimulation"); + }); + + afterEach(() => { + sinon.restore(); + }); + + it("| getSimulation polling terminates on SUCCESSFUL status received", async () => { + // setup + const TEST_RES = { + statusCode: 200, + headers: {}, + body: { + status: "SUCCESSFUL", + }, + }; + getSimulationStub.resolves(TEST_RES); + // call + const response = await simulationController.getSkillSimulationResult(""); + // verify + expect(response.body.status).equal("SUCCESSFUL"); + }); + + it("| getSimulation polling terminates on statusCode greater than 300", async () => { + // setup + const TEST_RES = { + statusCode: 400, + headers: {}, + body: { + status: "SUCCESSFUL", + }, + }; + getSimulationStub.resolves(TEST_RES); + // call + try { + await simulationController.getSkillSimulationResult(""); + } catch (err) { + // verify + expect((err as any).message).equal(jsonView.toString(TEST_RES.body)); + } + }); + + it("| getSimulation polling terminates on FAILED status received", async () => { + // setup + const TEST_RES = { + statusCode: 200, + headers: {}, + body: { + status: "FAILED", + result: { + error: { + message: "error msg", + }, + }, + }, + }; + getSimulationStub.resolves(TEST_RES); + // call + try { + await simulationController.getSkillSimulationResult(""); + } catch (err) { + // verify + expect((err as any).message).equal("Failed to simulate skill. Error: error msg"); + } + }); + + it("| getSimulation polling terminates when max retry is reached from request error", async () => { + // setup + getSimulationStub.rejects(TEST_MSG); + // call + try { + await simulationController.getSkillSimulationResult(""); + } catch (err) { + // verify + expect((err as any).message).equal(TEST_MSG); + } + }); + }); +}); \ No newline at end of file diff --git a/test/unit/fixture/controller/valid-deploy-delegate-instance.js b/test/unit/fixture/controller/valid-deploy-delegate-instance.js index 615b8793..898c58de 100644 --- a/test/unit/fixture/controller/valid-deploy-delegate-instance.js +++ b/test/unit/fixture/controller/valid-deploy-delegate-instance.js @@ -1,4 +1,4 @@ module.exports = { - bootstrap: () => 'bootstrap', - invoke: () => 'invoke' + bootstrap: () => "bootstrap", + invoke: () => "invoke", }; diff --git a/test/unit/fixture/dialog-evaluate/test-project-1/.ask/ask-states.json b/test/unit/fixture/dialog-evaluate/test-project-1/.ask/ask-states.json new file mode 100644 index 00000000..18048d0e --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-1/.ask/ask-states.json @@ -0,0 +1,8 @@ +{ + "askcliStatesVersion": "2020-03-31", + "profiles": { + "TEST_PROFILE": { + "skillId": "TEST_SKILL_ID" + } + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-1/ask-resources.json b/test/unit/fixture/dialog-evaluate/test-project-1/ask-resources.json new file mode 100644 index 00000000..649c901b --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-1/ask-resources.json @@ -0,0 +1,10 @@ +{ + "askcliResourcesVersion": "2020-03-31", + "profiles": { + "TEST_PROFILE": { + "skillMetadata": { + "src": "./skill-package" + } + } + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/conversations/ALexaPrize.acdl b/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/conversations/ALexaPrize.acdl new file mode 100644 index 00000000..086efb02 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/conversations/ALexaPrize.acdl @@ -0,0 +1,203 @@ +namespace com.alexaprize + +import com.amazon.alexa.ask.conversations.Affirm +import com.amazon.alexa.ask.conversations.Deny +import com.amazon.alexa.ask.conversations.Invoke +import com.amazon.alexa.ask.conversations.Notify +import com.amazon.alexa.ask.conversations.Offer +import com.amazon.alexa.ask.conversations.expect +import com.amazon.alexa.ask.conversations.response +import com.amazon.alexa.ask.conversations.utterances +import com.amazon.alexa.schema.Boolean +import com.amazon.alexa.schema.Nothing +import com.amazon.alexa.schema.String +import com.amazon.ask.types.builtins.AMAZON.NUMBER +import prompts.alexa_prize_preconditions_apla +import slotTypes.TopicType + +type ConversationDetails { + optional TopicType Topic +} + +letsChatEvent = utterances( + samples = [ + "let's chat", + "i want to chat", + "chat", + "talk", + "let's chat about {Topic}", + "i want to talk about {Topic}", + "can we talk about {Topic}" + ] +) + +affirmEvent = utterances( + samples = [ + "yes", + "yup", + "yeah", + "sure", + "alright" + ] +) + +denyEvent = utterances( + samples = [ + "no", + "nope", + "not really", + "not", + "naah" + ] +) + +type AlexaPrizePreconditions { + NUMBER isLocaleSupported + NUMBER isDeviceSupported + NUMBER isFalseWake + NUMBER isSocialBotAvailable + NUMBER isAlexaPrizeEnabled + NUMBER isTopicBanned + String handoffPromptOverride +} + +type AlexaPrizePreconditionsPayload { + AlexaPrizePreconditions result +} + +type HandoffResults { + String handoffPromptOverride +} + +type HandoffResultsPayload { + HandoffResults result +} + +action AlexaPrizePreconditions checkPreconditionsAndHandoff(TopicType Topic = nothing) + +action HandoffResults intentConfirmedHandoff() + +action HandoffResults intentDeniedHandoff() + +dialog Nothing AlexaPrizeDialog() { + sample { + preconditionsResult = checkPrecondition() + isHandoffPossible = (((preconditionsResult.isDeviceSupported == 1 && preconditionsResult.isLocaleSupported == 1) && preconditionsResult.isSocialBotAvailable == 1) && preconditionsResult.isAlexaPrizeEnabled == 1) + if (isHandoffPossible) { + isConfirmationNeeded = (preconditionsResult.isFalseWake == 1 || preconditionsResult.isTopicBanned == 1) + responses( + isConfirmationNeeded = isConfirmationNeeded, + preconditionsResult = preconditionsResult + ) + } else { + response( + response = alexa_prize_preconditions_apla, + act = Notify { + actionName = checkPreconditionsAndHandoff, + success = false + }, + payload = AlexaPrizePreconditionsPayload { + result = preconditionsResult + } + ) + } + } +} + +dialog AlexaPrizePreconditions checkPrecondition() { + sample { + chatRequest = expect( + act = Invoke, + event = letsChatEvent + ) + checkPreconditionsAndHandoff( + Topic = chatRequest.Topic + ) + } + sample { + expect( + act = Invoke, + event = letsChatEvent + ) + preconditionsResult = checkPreconditionsAndHandoff() + } +} + +dialog Nothing responses(Boolean isConfirmationNeeded, AlexaPrizePreconditions preconditionsResult) { + sample { + if (isConfirmationNeeded) { + handoffResult( + preconditionsResult = preconditionsResult + ) + } else { + response( + response = alexa_prize_preconditions_apla, + act = Notify { + actionName = checkPreconditionsAndHandoff + }, + payload = AlexaPrizePreconditionsPayload { + result = preconditionsResult + } + ) + } + } +} + +dialog Nothing handoffResult(AlexaPrizePreconditions preconditionsResult) { + sample { + response( + response = alexa_prize_preconditions_apla, + act = Notify { + actionName = checkPreconditionsAndHandoff + }, + nextAct = Offer { + actionName = intentConfirmedHandoff + }, + payload = AlexaPrizePreconditionsPayload { + result = preconditionsResult + } + ) + expect( + act = Affirm, + event = affirmEvent + ) + handoffResults = intentConfirmedHandoff() + response( + response = alexa_prize_preconditions_apla, + act = Notify { + actionName = intentConfirmedHandoff + }, + payload = HandoffResultsPayload { + result = handoffResults + } + ) + } + sample { + response( + response = alexa_prize_preconditions_apla, + act = Notify { + actionName = checkPreconditionsAndHandoff + }, + nextAct = Offer { + actionName = intentDeniedHandoff + }, + payload = AlexaPrizePreconditionsPayload { + result = preconditionsResult + } + ) + expect( + act = Deny, + event = denyEvent + ) + handoffResults = intentDeniedHandoff() + response( + response = alexa_prize_preconditions_apla, + act = Notify { + actionName = intentDeniedHandoff + }, + payload = HandoffResultsPayload { + result = handoffResults + } + ) + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/conversations/Dialog_NonDeployable.acdl b/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/conversations/Dialog_NonDeployable.acdl new file mode 100644 index 00000000..275632d7 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/conversations/Dialog_NonDeployable.acdl @@ -0,0 +1,81 @@ +namespace dialogs_non_deployable + +import apis.getEmployeeDetails +import com.amazon.alexa.ask.conversations.Inform +import com.amazon.alexa.ask.conversations.Request +import com.amazon.alexa.ask.conversations.expect +import com.amazon.alexa.ask.conversations.response +import com.amazon.ask.types.builtins.AMAZON.DATE +import com.amazon.ask.types.builtins.AMAZON.NUMBER +import prompts.request_dob_getDate_apla +import prompts.request_getEmploeeID_apla +import prompts.request_name_apla +import slotTypes.complexNames +import types.complexResult +import utteracesets.informComplexNameEvent +import utteracesets.informDOBEvent +import utteracesets.informEmployeeIDEvent + +dialog complexNames getName() { + sample { + response( + response = request_name_apla, + act = Request { + arguments = [ + getEmployeeDetails.arguments.name1 + ] + } + ) + complexNamesReturn = expect( + act = Inform, + event = informComplexNameEvent + ) + complexNamesReturn.name + } +} + +dialog NUMBER getEmploeeID() { + sample { + response( + response = request_getEmploeeID_apla, + act = Request { + arguments = [ + getEmployeeDetails.arguments.emplyee1id + ] + } + ) + empID = expect( + act = Inform, + event = informEmployeeIDEvent + ) + empID.emplyee1id + } +} + +dialog DATE getDate() { + sample { + response( + response = request_dob_getDate_apla, + act = Request { + arguments = [ + getEmployeeDetails.arguments.a_dateOfBirth + ] + } + ) + dobEvent = expect( + act = Inform, + event = informDOBEvent + ) + dobEvent.a_dateOfBirth + } +} + +dialog complexResult a_getEmployeeDetails(complexNames name1, NUMBER emplyee1id, DATE a_dateOfBirth) { + sample { + complexResultEvent = getEmployeeDetails( + name1 = name1, + emplyee1id = emplyee1id, + a_dateOfBirth = a_dateOfBirth + ) + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/conversations/Dialogs_reusableDialogsUsage_NonDeployableDialogs.acdl b/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/conversations/Dialogs_reusableDialogsUsage_NonDeployableDialogs.acdl new file mode 100644 index 00000000..b810c926 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/conversations/Dialogs_reusableDialogsUsage_NonDeployableDialogs.acdl @@ -0,0 +1,45 @@ +namespace reusableDialogs.NonDeployableDialogs + +import apis.getEmployeeDetails +import com.amazon.alexa.ask.conversations.Invoke +import com.amazon.alexa.ask.conversations.Notify +import com.amazon.alexa.ask.conversations.expect +import com.amazon.alexa.ask.conversations.response +import com.amazon.alexa.schema.Nothing +import dialogs_non_deployable.a_getEmployeeDetails +import dialogs_non_deployable.getDate +import dialogs_non_deployable.getEmploeeID +import dialogs_non_deployable.getName +import prompts.getEmployeePosition_success_apla +import types.complexResult +import utteracesets.who_are_you + +type PayLoadresult { + complexResult result +} + +dialog Nothing dilaog_getEmployeePosition() { + sample { + expect( + act = Invoke, + event = who_are_you + ) + complexNamesEvent = getName() + NUMBEREvent = getEmploeeID() + DATEEvent = getDate() + resultOne = a_getEmployeeDetails( + name1 = complexNamesEvent, + emplyee1id = NUMBEREvent, + a_dateOfBirth = DATEEvent + ) + response( + response = getEmployeePosition_success_apla, + act = Notify { + actionName = getEmployeeDetails + }, + payload = PayLoadresult { + result = resultOne + } + ) + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/conversations/Weather.acdl b/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/conversations/Weather.acdl new file mode 100644 index 00000000..c4c30976 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/conversations/Weather.acdl @@ -0,0 +1,137 @@ +namespace com.weatherbot + +import com.amazon.alexa.ask.conversations.Invoke +import com.amazon.alexa.ask.conversations.Notify +import com.amazon.alexa.ask.conversations.RequestArguments +import com.amazon.alexa.ask.conversations.ensure +import com.amazon.alexa.ask.conversations.expect +import com.amazon.alexa.ask.conversations.response +import com.amazon.alexa.ask.conversations.utterances +import com.amazon.alexa.schema.Nothing +import com.amazon.alexa.schema.Thing +import com.amazon.ask.types.builtins.AMAZON.DATE +import com.amazon.ask.types.builtins.AMAZON.NUMBER +import com.amazon.ask.types.builtins.AMAZON.US_CITY +import prompts.request_city_apla +import prompts.request_date_apla +import prompts.weather_apla +import slotTypes.myCustomCities + +type CityAndDate { + optional myCustomCities cityNameChanged + optional US_CITY cityName + optional DATE date +} + +getWeatherEvent = utterances( + samples = [ + "What's the weather {date} in {cityNameChanged}", + "What's the weather {date} in {cityName}", + "what is the weather {date}", + "how is weather" + ] +) + +type WeatherResult { + optional myCustomCities cityNameChanged + optional US_CITY cityName + NUMBER highTemp + NUMBER lowTemp +} + +type ResponsePayload { + WeatherResult weatherResult +} + +action WeatherResult getWeather(DATE date, US_CITY cityName = nothing, myCustomCities cityNameChanged = nothing) + +dialog Nothing Weather() { + sample { + weatherRequest = expect( + act = Invoke, + event = getWeatherEvent + ) + ensure( + requestArgs = [ + RequestArguments { + arguments = [ + getWeather.arguments.cityNameChanged + ], + response = request_city_apla + }, + RequestArguments { + arguments = [ + getWeather.arguments.cityName + ], + response = request_city_apla + }, + RequestArguments { + arguments = [ + getWeather.arguments.date + ], + response = request_date_apla + } + ] + ) + weatherResult = getWeather( + date = weatherRequest.date, + cityName = weatherRequest.cityName + ) + response( + response = weather_apla, + act = Notify { + actionName = getWeather + }, + payload = ResponsePayload { + weatherResult = weatherResult + } + ) + } + sample { + weatherRequest = expect( + act = Invoke, + event = getWeatherEvent + ) + ensure( + requestArgs = [ + RequestArguments { + arguments = [ + getWeather.arguments.cityNameChanged + ], + response = request_city_apla + }, + RequestArguments { + arguments = [ + getWeather.arguments.cityName + ], + response = request_city_apla + }, + RequestArguments { + arguments = [ + getWeather.arguments.date + ], + response = request_date_apla + } + ] + ) + weatherResult = getWeather( + date = weatherRequest.date, + cityNameChanged = weatherRequest.cityNameChanged + ) + response( + response = weather_apla, + act = Notify { + actionName = getWeather + }, + payload = ResponsePayload { + weatherResult = weatherResult + } + ) + } +} + +dialog Nothing ComplexTest() { + sample { + Weather() + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/conversations/apis.acdl b/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/conversations/apis.acdl new file mode 100644 index 00000000..072d682e --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/conversations/apis.acdl @@ -0,0 +1,15 @@ +namespace apis + +import com.amazon.alexa.schema.Nothing +import com.amazon.ask.types.builtins.AMAZON.DATE +import com.amazon.ask.types.builtins.AMAZON.NUMBER +import slotTypes.complexNames +import slotTypes.signs +import types.complexResult +import types.result_one + +action Nothing secondEarthAPI() + +action result_one favColorSign_Name(complexNames name, signs sign = nothing) + +action complexResult getEmployeeDetails(complexNames name1, NUMBER emplyee1id, DATE a_dateOfBirth = nothing) diff --git a/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/conversations/apisNamepaceLambda.acdl b/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/conversations/apisNamepaceLambda.acdl new file mode 100644 index 00000000..553a40c5 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/conversations/apisNamepaceLambda.acdl @@ -0,0 +1,22 @@ +namespace com.weatherbot.apis + +import com.amazon.ask.types.builtins.AMAZON.Food +import com.amazon.ask.types.builtins.AMAZON.NUMBER +import slotTypes.myColors + +type result { + Food fruitName + NUMBER price +} + +type payloadgetFruitPriceEvent { + result result +} + +action result fruitNameAPI(Food fruitName) + +action resultthree colorFruitName(myColors colorName) + +type resultthree { + Food fruitName +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/conversations/conversation_empty.acdl b/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/conversations/conversation_empty.acdl new file mode 100644 index 00000000..4189bdda --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/conversations/conversation_empty.acdl @@ -0,0 +1,114 @@ +namespace com.numberbot + +import com.amazon.alexa.ask.conversations.APLA +import com.amazon.alexa.ask.conversations.Action +import com.amazon.alexa.ask.conversations.Bye +import com.amazon.alexa.ask.conversations.Invoke +import com.amazon.alexa.ask.conversations.Notify +import com.amazon.alexa.ask.conversations.Offer +import com.amazon.alexa.ask.conversations.RequestArguments +import com.amazon.alexa.ask.conversations.ensure +import com.amazon.alexa.ask.conversations.expect +import com.amazon.alexa.ask.conversations.response +import com.amazon.alexa.ask.conversations.utterances +import com.amazon.alexa.schema.Nothing +import com.amazon.alexa.schema.Number +import com.amazon.alexa.schema.Thing +import com.amazon.ask.types.builtins.AMAZON.NUMBER +import prompts.AlexaConversationsBye +import prompts.numericfeedback_apla +import prompts.rating_apla + +type NumPayload { + Number num +} + +type RatingRequest { + NUMBER rating +} + +InformRatingEvent = utterances( + samples = [ + "my score is {rating}", + "that was a {rating} conversation", + "i rate you a {rating}", + "{rating}" + ] +) + +getStart = utterances( + samples = [ + "give me a number please" + ] +) + +action Nothing saveRating(Number rating) + +action Number getNumber() + +dialog Nothing GetFeedback(APLA feedback_prompt, Number num, Action notifyAction) { + sample { + response( + response = feedback_prompt, + act = Notify { + actionName = notifyAction, + success = true + }, + nextAct = Offer { + actionName = saveRating, + arguments = [ + saveRating.arguments.rating + ] + }, + payload = NumPayload { + num = num + } + ) + myRating = expect( + act = Invoke, + event = InformRatingEvent + ) + ensure( + requestArgs = [ + RequestArguments { + arguments = [ + saveRating.arguments.rating + ], + response = rating_apla + } + ] + ) + saveRating( + rating = myRating.rating + ) + } +} + +dialog Number levelOne() { + sample { + expect( + act = Invoke, + event = getStart + ) + num = getNumber() + } +} + +dialog Nothing MainDialog() { + sample { + num = levelOne() + GetFeedback( + feedback_prompt = numericfeedback_apla, + num = num, + notifyAction = getNumber + ) + response( + response = AlexaConversationsBye, + act = Notify { + actionName = saveRating, + success = true + }, + nextAct = Bye {} + ) + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/conversations/fruitNameApi.acdl b/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/conversations/fruitNameApi.acdl new file mode 100644 index 00000000..4664f2f2 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/conversations/fruitNameApi.acdl @@ -0,0 +1,34 @@ +namespace test + +import com.amazon.alexa.ask.conversations.utterances +import com.amazon.ask.types.builtins.AMAZON.Food + +type fruitNameShell { + Food fruitName +} + +type paylaodCompleFruit { + Food fruitName +} + +getFruitPriceEvent = utterances( + samples = [ + "what is the price of the fruit", + "what is the price of fruit" + ] +) + +informfruitNameEvent = utterances( + samples = [ + "{fruitName}", + "fruit name is {fruitName}", + "fruit is {fruitName}" + ] +) + +affirmFruitAPIEvent = utterances( + samples = [ + "uh huh", + "yup" + ] +) diff --git a/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/conversations/soaDialog.acdl b/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/conversations/soaDialog.acdl new file mode 100644 index 00000000..30a83432 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/conversations/soaDialog.acdl @@ -0,0 +1,123 @@ +namespace soaACDl + +import com.amazon.alexa.ask.conversations.Inform +import com.amazon.alexa.ask.conversations.Invoke +import com.amazon.alexa.ask.conversations.Notify +import com.amazon.alexa.ask.conversations.Request +import com.amazon.alexa.ask.conversations.expect +import com.amazon.alexa.ask.conversations.received +import com.amazon.alexa.ask.conversations.response +import com.amazon.alexa.ask.conversations.utterances +import com.amazon.alexa.schema.Nothing +import com.weatherbot.apis.colorFruitName +import com.weatherbot.apis.resultthree +import prompts.request_colorName_multiple_apla +import prompts.success_colorFruitAPI_apla +import slotTypes.myColors + +type payloadMultipleDialogEvent { + resultthree result +} + +MultipleDialogEvent = utterances( + samples = [ + "i want to buy a fruit" + ] +) + +informColorMultipleEvent = utterances( + samples = [ + "{colorName}", + "color is {colorName}", + "color {colorName}" + ] +) + +affirmMultipleColorEvent = utterances( + samples = [ + "do it" + ] +) + +type colorNameShell { + myColors colorName +} + +type payloadsOAConfirmArgs { + myColors colorName +} + +type colorEvent0 { + myColors colorName +} + +interaction { + actual { + result1 = received( + act = Inform, + utterance = "{armadillo|colorName}" + ) + resultEvent11 = colorFruitName( + colorName = result1.colorName + ) + response( + response = success_colorFruitAPI_apla, + act = Notify { + actionName = colorFruitName + }, + payload = payloadMultipleDialogEvent { + result = resultEvent11 + } + ) + } expected { + result1 = received( + act = Inform, + utterance = "{armadillo|colorName}" + ) + resultEvent11 = colorFruitName( + colorName = result1.colorName + ) + response( + response = success_colorFruitAPI_apla, + act = Notify { + actionName = colorFruitName + }, + payload = payloadMultipleDialogEvent { + result = resultEvent11 + } + ) + } +} + +dialog Nothing sOA() { + sample { + expect( + act = Invoke, + event = MultipleDialogEvent + ) + response( + response = request_colorName_multiple_apla, + act = Request { + arguments = [ + colorFruitName.arguments.colorName + ] + } + ) + colorEvent = expect( + act = Inform, + event = informColorMultipleEvent + ) + resultEvent = colorFruitName( + colorName = colorEvent.colorName + ) + response( + response = success_colorFruitAPI_apla, + act = Notify { + actionName = colorFruitName + }, + payload = payloadMultipleDialogEvent { + result = resultEvent + } + ) + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/conversations/types.acdl b/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/conversations/types.acdl new file mode 100644 index 00000000..3cc656d2 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/conversations/types.acdl @@ -0,0 +1,43 @@ +namespace types + +import com.amazon.ask.types.builtins.AMAZON.Color +import com.amazon.ask.types.builtins.AMAZON.DATE +import com.amazon.ask.types.builtins.AMAZON.Food +import com.amazon.ask.types.builtins.AMAZON.NUMBER +import slotTypes.complexNames +import slotTypes.myColors +import slotTypes.position +import slotTypes.signs + +type result_one { + Color colorName + complexNames name + signs sign +} + +type complexResult { + complexNames name1 + DATE a_dateOfBirth + NUMBER emplyee1id + position position +} + +type nameShell { + complexNames name +} + +type dobshell { + DATE a_dateOfBirth +} + +type employeeIDshell { + NUMBER emplyee1id +} + +type fruitNameShell { + Food fruitName +} + +type colorEvent0 { + myColors colorName +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/conversations/utteracesets.acdl b/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/conversations/utteracesets.acdl new file mode 100644 index 00000000..5f8fe09b --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/conversations/utteracesets.acdl @@ -0,0 +1,82 @@ +namespace utteracesets + +import com.amazon.alexa.ask.conversations.utterances +import types.dobshell +import types.employeeIDshell +import types.fruitNameShell +import types.nameShell + +getFruitPriceEvent = utterances( + samples = [ + "what is the price of the fruit", + "what is the price of fruit" + ] +) + +affirmFruitAPIEvent = utterances( + samples = [ + "yeah" + ] +) + +informfruitNameEvent = utterances( + samples = [ + "{fruitName}", + "fruit name is {fruitName}", + "fruit is {fruitName}" + ] +) + +delegateToSkill = utterances( + samples = [ + "get me to paradise", + "take me to paradise" + ] +) + +getFavColorEvent = utterances( + samples = [ + "what is my favourite color", + "tell my favourite color" + ] +) + +affirmFavColorEvent = utterances( + samples = [ + "correct" + ] +) + +who_are_you = utterances( + samples = [ + "who are you", + "who is that", + "find his designation" + ] +) + +informComplexNameEvent = utterances( + samples = [ + "{name}", + "name is {name}", + "i am {name}" + ] +) + +informDOBEvent = utterances( + samples = [ + "date of birth is {a_dateOfBirth}", + "birth date is {a_dateOfBirth}" + ] +) + +informEmployeeIDEvent = utterances( + samples = [ + "employee i.d. is {emplyee1id}", + "employee identification is {emplyee1id}", + "identification is {emplyee1id}", + "employee id is {emplyee1id}", + "i.d. is {emplyee1id}", + "id is {emplyee1id}" + ] +) diff --git a/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/interactionModels/custom/en-US.json b/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/interactionModels/custom/en-US.json new file mode 100644 index 00000000..7df58746 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/interactionModels/custom/en-US.json @@ -0,0 +1,919 @@ +{ + "interactionModel": { + "languageModel": { + "invocationName": "serious working test skill", + "intents": [ + { + "name": "AMAZON.CancelIntent", + "samples": [] + }, + { + "name": "AMAZON.HelpIntent", + "samples": [] + }, + { + "name": "AMAZON.StopIntent", + "samples": [] + }, + { + "name": "GetWeatherIntent", + "samples": ["what is the weather", "how is the weather", "tell me the weather"] + }, + { + "name": "AMAZON.NavigateHomeIntent", + "samples": [] + }, + { + "name": "AMAZON.FallbackIntent", + "samples": [] + } + ], + "types": [ + { + "values": [ + { + "id": "movies", + "name": { + "value": "movies", + "synonyms": [] + } + }, + { + "id": "politics", + "name": { + "value": "politics", + "synonyms": [] + } + }, + { + "id": "sports", + "name": { + "value": "sports", + "synonyms": [] + } + }, + { + "id": "hobbies", + "name": { + "value": "hobbies", + "synonyms": [] + } + }, + { + "id": "astronomy", + "name": { + "value": "astronomy", + "synonyms": [] + } + }, + { + "id": "physics", + "name": { + "value": "physics", + "synonyms": [] + } + }, + { + "id": "los_angeles_dodgers", + "name": { + "value": "los angeles dodgers" + } + }, + { + "id": "president_emmanuel_macron", + "name": { + "value": "president emmanuel macron" + } + }, + { + "id": "emmanuel_macron", + "name": { + "value": "emmanuel macron" + } + }, + { + "id": "tax_cuts", + "name": { + "value": "tax cuts" + } + }, + { + "id": "middle_class", + "name": { + "value": "middle class" + } + }, + { + "id": "inequality_divide", + "name": { + "value": "inequality divide" + } + }, + { + "id": "wealth_inequality", + "name": { + "value": "wealth inequality" + } + }, + { + "id": "n._p._r.", + "name": { + "value": "n. p. r." + } + }, + { + "id": "president_trump", + "name": { + "value": "president trump" + } + }, + { + "id": "fox", + "name": { + "value": "fox" + } + }, + { + "id": "police_officers", + "name": { + "value": "police officers" + } + }, + { + "id": "jerome_hall", + "name": { + "value": "jerome hall" + } + }, + { + "id": "diversity_training_program", + "name": { + "value": "diversity training program" + } + }, + { + "id": "read_preble", + "name": { + "value": "read preble" + } + }, + { + "id": "christopher_preble", + "name": { + "value": "christopher preble" + } + }, + { + "id": "pacific_rim", + "name": { + "value": "pacific rim" + } + }, + { + "id": "washington_nationals", + "name": { + "value": "washington nationals" + } + }, + { + "id": "michael_cohen", + "name": { + "value": "michael cohen" + } + }, + { + "id": "john_wall", + "name": { + "value": "john wall" + } + }, + { + "id": "united_states", + "name": { + "value": "united states" + } + }, + { + "id": "washington_wizards", + "name": { + "value": "washington wizards" + } + }, + { + "id": "bryce_harper", + "name": { + "value": "bryce harper" + } + }, + { + "id": "capitals_playoff_hockey_capitals", + "name": { + "value": "capitals playoff hockey capitals" + } + }, + { + "id": "james_b._comey", + "name": { + "value": "james b. comey" + } + }, + { + "id": "mike_pompeo", + "name": { + "value": "mike pompeo" + } + }, + { + "id": "tom_toles", + "name": { + "value": "tom toles" + } + }, + { + "id": "white_house", + "name": { + "value": "white house" + } + }, + { + "id": "manny_machado", + "name": { + "value": "manny machado" + } + }, + { + "id": "national_league_east", + "name": { + "value": "national league east" + } + }, + { + "id": "otto_porter_jr._now", + "name": { + "value": "otto porter jr. now" + } + }, + { + "id": "hillary_clinton", + "name": { + "value": "hillary clinton" + } + }, + { + "id": "trea_turner", + "name": { + "value": "trea turner" + } + }, + { + "id": "max_scherzer", + "name": { + "value": "max scherzer" + } + }, + { + "id": "donald_trump", + "name": { + "value": "donald trump" + } + }, + { + "id": "bryce_harper_nationals", + "name": { + "value": "bryce harper nationals" + } + }, + { + "id": "michael_a._taylor", + "name": { + "value": "michael a. taylor" + } + }, + { + "id": "news_media", + "name": { + "value": "news media" + } + }, + { + "id": "conservative_political_action_conference", + "name": { + "value": "conservative political action conference" + } + }, + { + "id": "mainstream_media", + "name": { + "value": "mainstream media" + } + }, + { + "id": "baltimore_orioles", + "name": { + "value": "baltimore orioles" + } + }, + { + "id": "sean_hannity", + "name": { + "value": "sean hannity" + } + }, + { + "id": "privilege", + "name": { + "value": "privilege" + } + }, + { + "id": "sarah_hart", + "name": { + "value": "sarah hart" + } + }, + { + "id": "matt_kemp", + "name": { + "value": "matt kemp" + } + }, + { + "id": "stephen_strasburg", + "name": { + "value": "stephen strasburg" + } + }, + { + "id": "police_misconduct", + "name": { + "value": "police misconduct" + } + }, + { + "id": "sarah_huckabee_sanders", + "name": { + "value": "sarah huckabee sanders" + } + }, + { + "id": "washington_wizards_april", + "name": { + "value": "washington wizards april" + } + }, + { + "id": "environmental_protection_agency_administrator_scott_pruitt", + "name": { + "value": "environmental protection agency administrator scott pruitt" + } + }, + { + "id": "dodger_stadium", + "name": { + "value": "dodger stadium" + } + }, + { + "id": "environmental_protection_agency", + "name": { + "value": "environmental protection agency" + } + }, + { + "id": "barbara_bush", + "name": { + "value": "barbara bush" + } + }, + { + "id": "lewis_\"scooter\"_libby", + "name": { + "value": "lewis \"scooter\" libby" + } + }, + { + "id": "lewis_scooter_libby", + "name": { + "value": "lewis scooter libby" + } + }, + { + "id": "game_3._lowry", + "name": { + "value": "game 3. lowry" + } + }, + { + "id": "columbus_blue_jackets", + "name": { + "value": "columbus blue jackets" + } + }, + { + "id": "john_tortorella", + "name": { + "value": "john tortorella" + } + }, + { + "id": "george_w._bush", + "name": { + "value": "george w. bush" + } + }, + { + "id": "george_h.w._bush", + "name": { + "value": "george h.w. bush" + } + }, + { + "id": "jarrett_hurd", + "name": { + "value": "jarrett hurd" + } + }, + { + "id": "said_fred_hurd_sr.", + "name": { + "value": "said fred hurd sr." + } + }, + { + "id": "fred_hurd_sr.", + "name": { + "value": "fred hurd sr." + } + }, + { + "id": "san_antonio", + "name": { + "value": "san antonio" + } + }, + { + "id": "san_antonio_spurs", + "name": { + "value": "san antonio spurs" + } + }, + { + "id": "gregg_popovich", + "name": { + "value": "gregg popovich" + } + }, + { + "id": "kawhi_leonard", + "name": { + "value": "kawhi leonard" + } + }, + { + "id": "tim_bontemps_seth_jones", + "name": { + "value": "tim bontemps seth jones" + } + }, + { + "id": "consumer_sentiment_index", + "name": { + "value": "consumer sentiment index" + } + }, + { + "id": "pew_research_center", + "name": { + "value": "pew research center" + } + }, + { + "id": "conference_board_consumer_confidence_survey", + "name": { + "value": "conference board consumer confidence survey" + } + }, + { + "id": "speech_rights", + "name": { + "value": "speech rights" + } + }, + { + "id": "first_amendment", + "name": { + "value": "first amendment" + } + }, + { + "id": "golden_state", + "name": { + "value": "golden state" + } + }, + { + "id": "north_korea", + "name": { + "value": "north korea" + } + }, + { + "id": "woman_pilot", + "name": { + "value": "woman pilot" + } + }, + { + "id": "airline_pilot_population", + "name": { + "value": "airline pilot population" + } + }, + { + "id": "air_transport_pilot", + "name": { + "value": "air transport pilot" + } + }, + { + "id": "southwest_airlines", + "name": { + "value": "southwest airlines" + } + }, + { + "id": "democratic_national_committee", + "name": { + "value": "democratic national committee" + } + }, + { + "id": "senate_foreign_relations_committee", + "name": { + "value": "senate foreign relations committee" + } + }, + { + "id": "cia_director_mike_pompeo", + "name": { + "value": "cia director mike pompeo" + } + }, + { + "id": "playoff_overtime_games", + "name": { + "value": "playoff overtime games" + } + }, + { + "id": "lord_jesus", + "name": { + "value": "lord jesus" + } + }, + { + "id": "lgbtq_community", + "name": { + "value": "lgbtq community" + } + }, + { + "id": "health_and_human_services_department", + "name": { + "value": "health and human services department" + } + }, + { + "id": "group_prayer", + "name": { + "value": "group prayer" + } + }, + { + "id": "princess_charlotte_elizabeth_diana", + "name": { + "value": "princess charlotte elizabeth diana" + } + }, + { + "id": "term_war_economy", + "name": { + "value": "term war economy" + } + }, + { + "id": "melissa_kirk", + "name": { + "value": "melissa kirk" + } + }, + { + "id": "captain_america", + "name": { + "value": "captain america" + } + }, + { + "id": "draft_position", + "name": { + "value": "draft position" + } + }, + { + "id": "elysee_mbem-bosse", + "name": { + "value": "elysee mbem-bosse" + } + }, + { + "id": "water_crisis", + "name": { + "value": "water crisis" + } + }, + { + "id": "nationals_pitchers", + "name": { + "value": "nationals pitchers" + } + }, + { + "id": "sen._jennifer_t._wexton", + "name": { + "value": "sen. jennifer t. wexton" + } + }, + { + "id": "interest_rates", + "name": { + "value": "interest rates" + } + }, + { + "id": "town_crier", + "name": { + "value": "town crier" + } + }, + { + "id": "nancy_goes_millennial", + "name": { + "value": "nancy goes millennial" + } + }, + { + "id": "steve_rogers", + "name": { + "value": "steve rogers" + } + }, + { + "id": "game_3._lebron_james", + "name": { + "value": "game 3. lebron james" + } + }, + { + "id": "anthony_rendon", + "name": { + "value": "anthony rendon" + } + }, + { + "id": "buckingham_palace", + "name": { + "value": "buckingham palace" + } + }, + { + "id": "travis_reinking_suspected", + "name": { + "value": "travis reinking suspected" + } + }, + { + "id": "detroit_free_press", + "name": { + "value": "detroit free press" + } + }, + { + "id": "national_rifle_association", + "name": { + "value": "national rifle association" + } + }, + { + "id": "ed_harris", + "name": { + "value": "ed harris" + } + }, + { + "id": "overtime_playoff_games", + "name": { + "value": "overtime playoff games" + } + }, + { + "id": "republican_sen._bob_corker", + "name": { + "value": "republican sen. bob corker" + } + }, + { + "id": "electricity_sector_reforms", + "name": { + "value": "electricity sector reforms" + } + }, + { + "id": "baltimore_manager_buck_showalter", + "name": { + "value": "baltimore manager buck showalter" + } + }, + { + "id": "sen._joe_manchin_iii", + "name": { + "value": "sen. joe manchin iii" + } + }, + { + "id": "car_seat_belts", + "name": { + "value": "car seat belts" + } + }, + { + "id": "andrews_mcmeel.", + "name": { + "value": "andrews mcmeel." + } + }, + { + "id": "north_africa_program", + "name": { + "value": "north africa program" + } + }, + { + "id": "state_prosecutor_lobby", + "name": { + "value": "state prosecutor lobby" + } + }, + { + "id": "cape_town", + "name": { + "value": "cape town" + } + }, + { + "id": "data_privacy_law", + "name": { + "value": "data privacy law" + } + }, + { + "id": "president_trump_down", + "name": { + "value": "president trump down" + } + }, + { + "id": "christian_kirk", + "name": { + "value": "christian kirk" + } + }, + { + "id": "mitch_mcconnell", + "name": { + "value": "mitch mcconnell" + } + }, + { + "id": "federal_reserve", + "name": { + "value": "federal reserve" + } + } + ], + "name": "TopicType" + }, + { + "values": [ + { + "name": { + "value": "cancer" + } + }, + { + "name": { + "value": "scorpio" + } + }, + { + "name": { + "value": "scorpion" + } + } + ], + "name": "signs" + }, + { + "values": [ + { + "name": { + "value": "satheesh" + } + }, + { + "name": { + "value": "raman" + } + }, + { + "name": { + "value": "yadhu" + } + } + ], + "name": "complexNames" + }, + { + "values": [ + { + "name": { + "value": "tester" + } + }, + { + "name": { + "value": "engineer" + } + }, + { + "name": { + "value": "manager" + } + } + ], + "name": "position" + }, + { + "values": [ + { + "name": { + "value": "blue" + } + }, + { + "name": { + "value": "red" + } + }, + { + "name": { + "value": "rocket" + } + } + ], + "name": "myColors" + }, + { + "values": [ + { + "name": { + "value": "flower city" + } + }, + { + "name": { + "value": "temple city" + } + }, + { + "name": { + "value": "ramapuram" + } + }, + { + "name": { + "value": "guindy" + } + }, + { + "name": { + "value": "porur" + } + } + ], + "name": "myCustomCities" + } + ] + } + }, + "version": "34" +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/display/confirm_city_apl_display/document.json b/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/display/confirm_city_apl_display/document.json new file mode 100644 index 00000000..6fea1ff7 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/display/confirm_city_apl_display/document.json @@ -0,0 +1,331 @@ +{ + "type": "APL", + "version": "1.1", + "settings": {}, + "theme": "dark", + "import": [ + { + "name": "alexa-layouts", + "version": "1.0.0" + } + ], + "resources": [ + { + "description": "Stock color for the light theme", + "colors": { + "colorTextPrimary": "#151920" + } + }, + { + "description": "Stock color for the dark theme", + "when": "${viewport.theme == 'dark'}", + "colors": { + "colorTextPrimary": "#f0f1ef" + } + }, + { + "description": "Standard font sizes", + "dimensions": { + "textSizeBody": 48, + "textSizePrimary": 27, + "textSizeSecondary": 23, + "textSizeDetails": 20, + "textSizeSecondaryHint": 25 + } + }, + { + "description": "Common spacing values", + "dimensions": { + "spacingThin": 6, + "spacingSmall": 12, + "spacingMedium": 24, + "spacingLarge": 48, + "spacingExtraLarge": 72 + } + }, + { + "description": "Common margins and padding", + "dimensions": { + "marginTop": 40, + "marginLeft": 60, + "marginRight": 60, + "marginBottom": 40 + } + } + ], + "styles": { + "textStyleBase": { + "description": "Base font description; set color", + "values": [ + { + "color": "@colorTextPrimary" + } + ] + }, + "textStyleBase0": { + "description": "Thin version of basic font", + "extend": "textStyleBase", + "values": { + "fontWeight": "100" + } + }, + "textStyleBase1": { + "description": "Light version of basic font", + "extend": "textStyleBase", + "values": { + "fontWeight": "300" + } + }, + "textStyleBase2": { + "description": "Regular version of basic font", + "extend": "textStyleBase", + "values": { + "fontWeight": "500" + } + }, + "mixinBody": { + "values": { + "fontSize": "@textSizeBody" + } + }, + "mixinPrimary": { + "values": { + "fontSize": "@textSizePrimary" + } + }, + "mixinDetails": { + "values": { + "fontSize": "@textSizeDetails" + } + }, + "mixinSecondary": { + "values": { + "fontSize": "@textSizeSecondary" + } + }, + "textStylePrimary": { + "extend": ["textStyleBase1", "mixinPrimary"] + }, + "textStyleSecondary": { + "extend": ["textStyleBase0", "mixinSecondary"] + }, + "textStyleBody": { + "extend": ["textStyleBase1", "mixinBody"] + }, + "textStyleSecondaryHint": { + "values": { + "fontFamily": "Bookerly", + "fontStyle": "italic", + "fontSize": "@textSizeSecondaryHint", + "color": "@colorTextPrimary" + } + }, + "textStyleDetails": { + "extend": ["textStyleBase2", "mixinDetails"] + } + }, + "onMount": [], + "graphics": {}, + "commands": {}, + "layouts": { + "ListTemplate1": { + "parameters": ["backgroundImage", "title", "logo", "hintText", "listData"], + "item": [ + { + "type": "Container", + "width": "100vw", + "height": "100vh", + "direction": "column", + "items": [ + { + "type": "Image", + "source": "${backgroundImage}", + "scale": "best-fill", + "width": "100vw", + "height": "100vh", + "position": "absolute" + }, + { + "type": "AlexaHeader", + "headerTitle": "${title}", + "headerAttributionImage": "${logo}" + }, + { + "type": "Sequence", + "grow": 1, + "height": "80vh", + "scrollDirection": "vertical", + "paddingLeft": "@marginLeft", + "paddingRight": "@marginRight", + "data": "${listData}", + "numbered": true, + "items": [ + { + "type": "VerticalListItem", + "image": "${data.image.sources[0].url}", + "primaryText": "${data.textContent.primaryText.text}", + "secondaryText": "${data.textContent.secondaryText.text}", + "tertiaryText": "${data.textContent.tertiaryText.text}" + } + ] + } + ] + } + ] + }, + "VerticalListItem": { + "parameters": ["primaryText", "secondaryText", "tertiaryText", "image"], + "item": [ + { + "when": "${viewport.shape == 'round'}", + "type": "Container", + "direction": "row", + "height": 200, + "width": 500, + "alignItems": "center", + "items": [ + { + "type": "Text", + "text": "${ordinal}", + "paddingBottom": "20dp", + "color": "white", + "spacing": "5dp" + }, + { + "type": "Image", + "when": "${image}", + "source": "${image}", + "height": 150, + "width": 150, + "spacing": 15, + "scale": "best-fit", + "align": "top" + }, + { + "type": "Container", + "direction": "column", + "spacing": 25, + "items": [ + { + "type": "Text", + "text": "${primaryText}", + "style": "textStyleDetail", + "grow": 1, + "shrink": 1, + "fontWeight": "300", + "maxLines": 1 + }, + { + "type": "Text", + "text": "${secondaryText}", + "style": "textStyleCaption", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + }, + { + "type": "Text", + "text": "${tertiaryText}", + "style": "textStyleDetails", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + } + ] + } + ] + }, + { + "type": "Container", + "direction": "row", + "height": 125, + "width": 800, + "alignItems": "center", + "items": [ + { + "type": "Text", + "text": "${ordinal}", + "paddingBottom": "20dp", + "color": "white", + "spacing": "5dp" + }, + { + "type": "Image", + "when": "${image}", + "source": "${image}", + "height": 100, + "width": 100, + "align": "top", + "spacing": 50, + "scale": "best-fit" + }, + { + "type": "Container", + "spacing": 30, + "direction": "column", + "items": [ + { + "type": "Text", + "text": "${primaryText}", + "style": "textStyleBody", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + }, + { + "type": "Text", + "text": "${secondaryText}", + "style": "textStyleDetails", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + } + ] + }, + { + "type": "Text", + "text": "${tertiaryText}", + "style": "textStyleBody", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "textAlign": "right", + "maxLines": 1 + } + ] + } + ] + } + }, + "mainTemplate": { + "parameters": ["payload"], + "item": [ + { + "type": "Container", + "id": "BookCabSimpleDialogAPL", + "items": [ + { + "type": "TouchWrapper", + "onPress": { + "type": "SendEvent", + "arguments": ["delegateToColtraneOld"] + }, + "item": { + "type": "Text", + "id": "BookCabSimpleDialogAPL", + "paddingTop": "100", + "paddingLeft": "100", + "color": "green", + "size": 50, + "text": "which city ?" + } + } + ] + } + ] + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/display/confirm_date_apl_display/document.json b/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/display/confirm_date_apl_display/document.json new file mode 100644 index 00000000..d41ea236 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/display/confirm_date_apl_display/document.json @@ -0,0 +1,331 @@ +{ + "type": "APL", + "version": "1.1", + "settings": {}, + "theme": "dark", + "import": [ + { + "name": "alexa-layouts", + "version": "1.0.0" + } + ], + "resources": [ + { + "description": "Stock color for the light theme", + "colors": { + "colorTextPrimary": "#151920" + } + }, + { + "description": "Stock color for the dark theme", + "when": "${viewport.theme == 'dark'}", + "colors": { + "colorTextPrimary": "#f0f1ef" + } + }, + { + "description": "Standard font sizes", + "dimensions": { + "textSizeBody": 48, + "textSizePrimary": 27, + "textSizeSecondary": 23, + "textSizeDetails": 20, + "textSizeSecondaryHint": 25 + } + }, + { + "description": "Common spacing values", + "dimensions": { + "spacingThin": 6, + "spacingSmall": 12, + "spacingMedium": 24, + "spacingLarge": 48, + "spacingExtraLarge": 72 + } + }, + { + "description": "Common margins and padding", + "dimensions": { + "marginTop": 40, + "marginLeft": 60, + "marginRight": 60, + "marginBottom": 40 + } + } + ], + "styles": { + "textStyleBase": { + "description": "Base font description; set color", + "values": [ + { + "color": "@colorTextPrimary" + } + ] + }, + "textStyleBase0": { + "description": "Thin version of basic font", + "extend": "textStyleBase", + "values": { + "fontWeight": "100" + } + }, + "textStyleBase1": { + "description": "Light version of basic font", + "extend": "textStyleBase", + "values": { + "fontWeight": "300" + } + }, + "textStyleBase2": { + "description": "Regular version of basic font", + "extend": "textStyleBase", + "values": { + "fontWeight": "500" + } + }, + "mixinBody": { + "values": { + "fontSize": "@textSizeBody" + } + }, + "mixinPrimary": { + "values": { + "fontSize": "@textSizePrimary" + } + }, + "mixinDetails": { + "values": { + "fontSize": "@textSizeDetails" + } + }, + "mixinSecondary": { + "values": { + "fontSize": "@textSizeSecondary" + } + }, + "textStylePrimary": { + "extend": ["textStyleBase1", "mixinPrimary"] + }, + "textStyleSecondary": { + "extend": ["textStyleBase0", "mixinSecondary"] + }, + "textStyleBody": { + "extend": ["textStyleBase1", "mixinBody"] + }, + "textStyleSecondaryHint": { + "values": { + "fontFamily": "Bookerly", + "fontStyle": "italic", + "fontSize": "@textSizeSecondaryHint", + "color": "@colorTextPrimary" + } + }, + "textStyleDetails": { + "extend": ["textStyleBase2", "mixinDetails"] + } + }, + "onMount": [], + "graphics": {}, + "commands": {}, + "layouts": { + "ListTemplate1": { + "parameters": ["backgroundImage", "title", "logo", "hintText", "listData"], + "item": [ + { + "type": "Container", + "width": "100vw", + "height": "100vh", + "direction": "column", + "items": [ + { + "type": "Image", + "source": "${backgroundImage}", + "scale": "best-fill", + "width": "100vw", + "height": "100vh", + "position": "absolute" + }, + { + "type": "AlexaHeader", + "headerTitle": "${title}", + "headerAttributionImage": "${logo}" + }, + { + "type": "Sequence", + "grow": 1, + "height": "80vh", + "scrollDirection": "vertical", + "paddingLeft": "@marginLeft", + "paddingRight": "@marginRight", + "data": "${listData}", + "numbered": true, + "items": [ + { + "type": "VerticalListItem", + "image": "${data.image.sources[0].url}", + "primaryText": "${data.textContent.primaryText.text}", + "secondaryText": "${data.textContent.secondaryText.text}", + "tertiaryText": "${data.textContent.tertiaryText.text}" + } + ] + } + ] + } + ] + }, + "VerticalListItem": { + "parameters": ["primaryText", "secondaryText", "tertiaryText", "image"], + "item": [ + { + "when": "${viewport.shape == 'round'}", + "type": "Container", + "direction": "row", + "height": 200, + "width": 500, + "alignItems": "center", + "items": [ + { + "type": "Text", + "text": "${ordinal}", + "paddingBottom": "20dp", + "color": "white", + "spacing": "5dp" + }, + { + "type": "Image", + "when": "${image}", + "source": "${image}", + "height": 150, + "width": 150, + "spacing": 15, + "scale": "best-fit", + "align": "top" + }, + { + "type": "Container", + "direction": "column", + "spacing": 25, + "items": [ + { + "type": "Text", + "text": "${primaryText}", + "style": "textStyleDetail", + "grow": 1, + "shrink": 1, + "fontWeight": "300", + "maxLines": 1 + }, + { + "type": "Text", + "text": "${secondaryText}", + "style": "textStyleCaption", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + }, + { + "type": "Text", + "text": "${tertiaryText}", + "style": "textStyleDetails", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + } + ] + } + ] + }, + { + "type": "Container", + "direction": "row", + "height": 125, + "width": 800, + "alignItems": "center", + "items": [ + { + "type": "Text", + "text": "${ordinal}", + "paddingBottom": "20dp", + "color": "white", + "spacing": "5dp" + }, + { + "type": "Image", + "when": "${image}", + "source": "${image}", + "height": 100, + "width": 100, + "align": "top", + "spacing": 50, + "scale": "best-fit" + }, + { + "type": "Container", + "spacing": 30, + "direction": "column", + "items": [ + { + "type": "Text", + "text": "${primaryText}", + "style": "textStyleBody", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + }, + { + "type": "Text", + "text": "${secondaryText}", + "style": "textStyleDetails", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + } + ] + }, + { + "type": "Text", + "text": "${tertiaryText}", + "style": "textStyleBody", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "textAlign": "right", + "maxLines": 1 + } + ] + } + ] + } + }, + "mainTemplate": { + "parameters": ["payload"], + "item": [ + { + "type": "Container", + "id": "BookCabSimpleDialogAPL", + "items": [ + { + "type": "TouchWrapper", + "onPress": { + "type": "SendEvent", + "arguments": ["delegateToColtraneOld"] + }, + "item": { + "type": "Text", + "id": "BookCabSimpleDialogAPL", + "paddingTop": "100", + "paddingLeft": "100", + "color": "green", + "size": 50, + "text": "which date ?" + } + } + ] + } + ] + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/display/confirm_weather_apla_display/document.json b/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/display/confirm_weather_apla_display/document.json new file mode 100644 index 00000000..3bcc0e4a --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/display/confirm_weather_apla_display/document.json @@ -0,0 +1,379 @@ +{ + "type": "APL", + "version": "1.1", + "settings": {}, + "theme": "dark", + "import": [ + { + "name": "alexa-layouts", + "version": "1.0.0" + } + ], + "resources": [ + { + "description": "Stock color for the light theme", + "colors": { + "colorTextPrimary": "#151920" + } + }, + { + "description": "Stock color for the dark theme", + "when": "${viewport.theme == 'dark'}", + "colors": { + "colorTextPrimary": "#f0f1ef" + } + }, + { + "description": "Standard font sizes", + "dimensions": { + "textSizeBody": 48, + "textSizePrimary": 27, + "textSizeSecondary": 23, + "textSizeDetails": 20, + "textSizeSecondaryHint": 25 + } + }, + { + "description": "Common spacing values", + "dimensions": { + "spacingThin": 6, + "spacingSmall": 12, + "spacingMedium": 24, + "spacingLarge": 48, + "spacingExtraLarge": 72 + } + }, + { + "description": "Common margins and padding", + "dimensions": { + "marginTop": 40, + "marginLeft": 60, + "marginRight": 60, + "marginBottom": 40 + } + } + ], + "styles": { + "textStyleBase": { + "description": "Base font description; set color", + "values": [ + { + "color": "@colorTextPrimary" + } + ] + }, + "textStyleBase0": { + "description": "Thin version of basic font", + "extend": "textStyleBase", + "values": { + "fontWeight": "100" + } + }, + "textStyleBase1": { + "description": "Light version of basic font", + "extend": "textStyleBase", + "values": { + "fontWeight": "300" + } + }, + "textStyleBase2": { + "description": "Regular version of basic font", + "extend": "textStyleBase", + "values": { + "fontWeight": "500" + } + }, + "mixinBody": { + "values": { + "fontSize": "@textSizeBody" + } + }, + "mixinPrimary": { + "values": { + "fontSize": "@textSizePrimary" + } + }, + "mixinDetails": { + "values": { + "fontSize": "@textSizeDetails" + } + }, + "mixinSecondary": { + "values": { + "fontSize": "@textSizeSecondary" + } + }, + "textStylePrimary": { + "extend": ["textStyleBase1", "mixinPrimary"] + }, + "textStyleSecondary": { + "extend": ["textStyleBase0", "mixinSecondary"] + }, + "textStyleBody": { + "extend": ["textStyleBase1", "mixinBody"] + }, + "textStyleSecondaryHint": { + "values": { + "fontFamily": "Bookerly", + "fontStyle": "italic", + "fontSize": "@textSizeSecondaryHint", + "color": "@colorTextPrimary" + } + }, + "textStyleDetails": { + "extend": ["textStyleBase2", "mixinDetails"] + } + }, + "onMount": [], + "graphics": {}, + "commands": {}, + "layouts": { + "ListTemplate1": { + "parameters": ["backgroundImage", "title", "logo", "hintText", "listData"], + "item": [ + { + "type": "Container", + "width": "100vw", + "height": "100vh", + "direction": "column", + "items": [ + { + "type": "Image", + "source": "${backgroundImage}", + "scale": "best-fill", + "width": "100vw", + "height": "100vh", + "position": "absolute" + }, + { + "type": "AlexaHeader", + "headerTitle": "${title}", + "headerAttributionImage": "${logo}" + }, + { + "type": "Sequence", + "grow": 1, + "height": "80vh", + "scrollDirection": "vertical", + "paddingLeft": "@marginLeft", + "paddingRight": "@marginRight", + "data": "${listData}", + "numbered": true, + "items": [ + { + "type": "VerticalListItem", + "image": "${data.image.sources[0].url}", + "primaryText": "${data.textContent.primaryText.text}", + "secondaryText": "${data.textContent.secondaryText.text}", + "tertiaryText": "${data.textContent.tertiaryText.text}" + } + ] + } + ] + } + ] + }, + "VerticalListItem": { + "parameters": ["primaryText", "secondaryText", "tertiaryText", "image"], + "item": [ + { + "when": "${viewport.shape == 'round'}", + "type": "Container", + "direction": "row", + "height": 200, + "width": 500, + "alignItems": "center", + "items": [ + { + "type": "Text", + "text": "${ordinal}", + "paddingBottom": "20dp", + "color": "white", + "spacing": "5dp" + }, + { + "type": "Image", + "when": "${image}", + "source": "${image}", + "height": 150, + "width": 150, + "spacing": 15, + "scale": "best-fit", + "align": "top" + }, + { + "type": "Container", + "direction": "column", + "spacing": 25, + "items": [ + { + "type": "Text", + "text": "${primaryText}", + "style": "textStyleDetail", + "grow": 1, + "shrink": 1, + "fontWeight": "300", + "maxLines": 1 + }, + { + "type": "Text", + "text": "${secondaryText}", + "style": "textStyleCaption", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + }, + { + "type": "Text", + "text": "${tertiaryText}", + "style": "textStyleDetails", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + } + ] + } + ] + }, + { + "type": "Container", + "direction": "row", + "height": 125, + "width": 800, + "alignItems": "center", + "items": [ + { + "type": "Text", + "text": "${ordinal}", + "paddingBottom": "20dp", + "color": "white", + "spacing": "5dp" + }, + { + "type": "Image", + "when": "${image}", + "source": "${image}", + "height": 100, + "width": 100, + "align": "top", + "spacing": 50, + "scale": "best-fit" + }, + { + "type": "Container", + "spacing": 30, + "direction": "column", + "items": [ + { + "type": "Text", + "text": "${primaryText}", + "style": "textStyleBody", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + }, + { + "type": "Text", + "text": "${secondaryText}", + "style": "textStyleDetails", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + } + ] + }, + { + "type": "Text", + "text": "${tertiaryText}", + "style": "textStyleBody", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "textAlign": "right", + "maxLines": 1 + } + ] + } + ] + } + }, + "mainTemplate": { + "parameters": ["payload"], + "item": [ + { + "type": "Container", + "id": "BookCabSimpleDialogAPL", + "items": [ + { + "type": "TouchWrapper", + "onPress": { + "type": "SendEvent", + "arguments": ["delegateToSkillNew"] + }, + "item": { + "type": "Text", + "id": "BookCabSimpleDialogAPL", + "paddingTop": "100", + "paddingLeft": "100", + "color": "green", + "size": 50, + "text": "delegateToSkillNew" + } + }, + { + "type": "TouchWrapper", + "onPress": { + "type": "SendEvent", + "arguments": ["delegateToSkillOld"] + }, + "item": { + "type": "Text", + "id": "BookCabSimpleDialogAPL", + "paddingTop": "100", + "paddingLeft": "100", + "color": "green", + "size": 50, + "text": "delegateToSkillOld" + } + }, + { + "type": "TouchWrapper", + "onPress": { + "type": "SendEvent", + "arguments": ["delegateToColtraneNew"] + }, + "item": { + "type": "Text", + "id": "BookCabSimpleDialogAPL", + "paddingTop": "100", + "paddingLeft": "100", + "color": "green", + "size": 50, + "text": "delegateToColtraneNew" + } + }, + { + "type": "TouchWrapper", + "onPress": { + "type": "SendEvent", + "arguments": ["delegateToColtraneOld"] + }, + "item": { + "type": "Text", + "id": "BookCabSimpleDialogAPL", + "paddingTop": "100", + "paddingLeft": "100", + "color": "green", + "size": 50, + "text": "delegateToColtraneOld" + } + } + ] + } + ] + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/display/request_city_apl_display/document.json b/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/display/request_city_apl_display/document.json new file mode 100644 index 00000000..6fea1ff7 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/display/request_city_apl_display/document.json @@ -0,0 +1,331 @@ +{ + "type": "APL", + "version": "1.1", + "settings": {}, + "theme": "dark", + "import": [ + { + "name": "alexa-layouts", + "version": "1.0.0" + } + ], + "resources": [ + { + "description": "Stock color for the light theme", + "colors": { + "colorTextPrimary": "#151920" + } + }, + { + "description": "Stock color for the dark theme", + "when": "${viewport.theme == 'dark'}", + "colors": { + "colorTextPrimary": "#f0f1ef" + } + }, + { + "description": "Standard font sizes", + "dimensions": { + "textSizeBody": 48, + "textSizePrimary": 27, + "textSizeSecondary": 23, + "textSizeDetails": 20, + "textSizeSecondaryHint": 25 + } + }, + { + "description": "Common spacing values", + "dimensions": { + "spacingThin": 6, + "spacingSmall": 12, + "spacingMedium": 24, + "spacingLarge": 48, + "spacingExtraLarge": 72 + } + }, + { + "description": "Common margins and padding", + "dimensions": { + "marginTop": 40, + "marginLeft": 60, + "marginRight": 60, + "marginBottom": 40 + } + } + ], + "styles": { + "textStyleBase": { + "description": "Base font description; set color", + "values": [ + { + "color": "@colorTextPrimary" + } + ] + }, + "textStyleBase0": { + "description": "Thin version of basic font", + "extend": "textStyleBase", + "values": { + "fontWeight": "100" + } + }, + "textStyleBase1": { + "description": "Light version of basic font", + "extend": "textStyleBase", + "values": { + "fontWeight": "300" + } + }, + "textStyleBase2": { + "description": "Regular version of basic font", + "extend": "textStyleBase", + "values": { + "fontWeight": "500" + } + }, + "mixinBody": { + "values": { + "fontSize": "@textSizeBody" + } + }, + "mixinPrimary": { + "values": { + "fontSize": "@textSizePrimary" + } + }, + "mixinDetails": { + "values": { + "fontSize": "@textSizeDetails" + } + }, + "mixinSecondary": { + "values": { + "fontSize": "@textSizeSecondary" + } + }, + "textStylePrimary": { + "extend": ["textStyleBase1", "mixinPrimary"] + }, + "textStyleSecondary": { + "extend": ["textStyleBase0", "mixinSecondary"] + }, + "textStyleBody": { + "extend": ["textStyleBase1", "mixinBody"] + }, + "textStyleSecondaryHint": { + "values": { + "fontFamily": "Bookerly", + "fontStyle": "italic", + "fontSize": "@textSizeSecondaryHint", + "color": "@colorTextPrimary" + } + }, + "textStyleDetails": { + "extend": ["textStyleBase2", "mixinDetails"] + } + }, + "onMount": [], + "graphics": {}, + "commands": {}, + "layouts": { + "ListTemplate1": { + "parameters": ["backgroundImage", "title", "logo", "hintText", "listData"], + "item": [ + { + "type": "Container", + "width": "100vw", + "height": "100vh", + "direction": "column", + "items": [ + { + "type": "Image", + "source": "${backgroundImage}", + "scale": "best-fill", + "width": "100vw", + "height": "100vh", + "position": "absolute" + }, + { + "type": "AlexaHeader", + "headerTitle": "${title}", + "headerAttributionImage": "${logo}" + }, + { + "type": "Sequence", + "grow": 1, + "height": "80vh", + "scrollDirection": "vertical", + "paddingLeft": "@marginLeft", + "paddingRight": "@marginRight", + "data": "${listData}", + "numbered": true, + "items": [ + { + "type": "VerticalListItem", + "image": "${data.image.sources[0].url}", + "primaryText": "${data.textContent.primaryText.text}", + "secondaryText": "${data.textContent.secondaryText.text}", + "tertiaryText": "${data.textContent.tertiaryText.text}" + } + ] + } + ] + } + ] + }, + "VerticalListItem": { + "parameters": ["primaryText", "secondaryText", "tertiaryText", "image"], + "item": [ + { + "when": "${viewport.shape == 'round'}", + "type": "Container", + "direction": "row", + "height": 200, + "width": 500, + "alignItems": "center", + "items": [ + { + "type": "Text", + "text": "${ordinal}", + "paddingBottom": "20dp", + "color": "white", + "spacing": "5dp" + }, + { + "type": "Image", + "when": "${image}", + "source": "${image}", + "height": 150, + "width": 150, + "spacing": 15, + "scale": "best-fit", + "align": "top" + }, + { + "type": "Container", + "direction": "column", + "spacing": 25, + "items": [ + { + "type": "Text", + "text": "${primaryText}", + "style": "textStyleDetail", + "grow": 1, + "shrink": 1, + "fontWeight": "300", + "maxLines": 1 + }, + { + "type": "Text", + "text": "${secondaryText}", + "style": "textStyleCaption", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + }, + { + "type": "Text", + "text": "${tertiaryText}", + "style": "textStyleDetails", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + } + ] + } + ] + }, + { + "type": "Container", + "direction": "row", + "height": 125, + "width": 800, + "alignItems": "center", + "items": [ + { + "type": "Text", + "text": "${ordinal}", + "paddingBottom": "20dp", + "color": "white", + "spacing": "5dp" + }, + { + "type": "Image", + "when": "${image}", + "source": "${image}", + "height": 100, + "width": 100, + "align": "top", + "spacing": 50, + "scale": "best-fit" + }, + { + "type": "Container", + "spacing": 30, + "direction": "column", + "items": [ + { + "type": "Text", + "text": "${primaryText}", + "style": "textStyleBody", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + }, + { + "type": "Text", + "text": "${secondaryText}", + "style": "textStyleDetails", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + } + ] + }, + { + "type": "Text", + "text": "${tertiaryText}", + "style": "textStyleBody", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "textAlign": "right", + "maxLines": 1 + } + ] + } + ] + } + }, + "mainTemplate": { + "parameters": ["payload"], + "item": [ + { + "type": "Container", + "id": "BookCabSimpleDialogAPL", + "items": [ + { + "type": "TouchWrapper", + "onPress": { + "type": "SendEvent", + "arguments": ["delegateToColtraneOld"] + }, + "item": { + "type": "Text", + "id": "BookCabSimpleDialogAPL", + "paddingTop": "100", + "paddingLeft": "100", + "color": "green", + "size": 50, + "text": "which city ?" + } + } + ] + } + ] + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/display/request_date_apl_display/document.json b/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/display/request_date_apl_display/document.json new file mode 100644 index 00000000..d41ea236 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/display/request_date_apl_display/document.json @@ -0,0 +1,331 @@ +{ + "type": "APL", + "version": "1.1", + "settings": {}, + "theme": "dark", + "import": [ + { + "name": "alexa-layouts", + "version": "1.0.0" + } + ], + "resources": [ + { + "description": "Stock color for the light theme", + "colors": { + "colorTextPrimary": "#151920" + } + }, + { + "description": "Stock color for the dark theme", + "when": "${viewport.theme == 'dark'}", + "colors": { + "colorTextPrimary": "#f0f1ef" + } + }, + { + "description": "Standard font sizes", + "dimensions": { + "textSizeBody": 48, + "textSizePrimary": 27, + "textSizeSecondary": 23, + "textSizeDetails": 20, + "textSizeSecondaryHint": 25 + } + }, + { + "description": "Common spacing values", + "dimensions": { + "spacingThin": 6, + "spacingSmall": 12, + "spacingMedium": 24, + "spacingLarge": 48, + "spacingExtraLarge": 72 + } + }, + { + "description": "Common margins and padding", + "dimensions": { + "marginTop": 40, + "marginLeft": 60, + "marginRight": 60, + "marginBottom": 40 + } + } + ], + "styles": { + "textStyleBase": { + "description": "Base font description; set color", + "values": [ + { + "color": "@colorTextPrimary" + } + ] + }, + "textStyleBase0": { + "description": "Thin version of basic font", + "extend": "textStyleBase", + "values": { + "fontWeight": "100" + } + }, + "textStyleBase1": { + "description": "Light version of basic font", + "extend": "textStyleBase", + "values": { + "fontWeight": "300" + } + }, + "textStyleBase2": { + "description": "Regular version of basic font", + "extend": "textStyleBase", + "values": { + "fontWeight": "500" + } + }, + "mixinBody": { + "values": { + "fontSize": "@textSizeBody" + } + }, + "mixinPrimary": { + "values": { + "fontSize": "@textSizePrimary" + } + }, + "mixinDetails": { + "values": { + "fontSize": "@textSizeDetails" + } + }, + "mixinSecondary": { + "values": { + "fontSize": "@textSizeSecondary" + } + }, + "textStylePrimary": { + "extend": ["textStyleBase1", "mixinPrimary"] + }, + "textStyleSecondary": { + "extend": ["textStyleBase0", "mixinSecondary"] + }, + "textStyleBody": { + "extend": ["textStyleBase1", "mixinBody"] + }, + "textStyleSecondaryHint": { + "values": { + "fontFamily": "Bookerly", + "fontStyle": "italic", + "fontSize": "@textSizeSecondaryHint", + "color": "@colorTextPrimary" + } + }, + "textStyleDetails": { + "extend": ["textStyleBase2", "mixinDetails"] + } + }, + "onMount": [], + "graphics": {}, + "commands": {}, + "layouts": { + "ListTemplate1": { + "parameters": ["backgroundImage", "title", "logo", "hintText", "listData"], + "item": [ + { + "type": "Container", + "width": "100vw", + "height": "100vh", + "direction": "column", + "items": [ + { + "type": "Image", + "source": "${backgroundImage}", + "scale": "best-fill", + "width": "100vw", + "height": "100vh", + "position": "absolute" + }, + { + "type": "AlexaHeader", + "headerTitle": "${title}", + "headerAttributionImage": "${logo}" + }, + { + "type": "Sequence", + "grow": 1, + "height": "80vh", + "scrollDirection": "vertical", + "paddingLeft": "@marginLeft", + "paddingRight": "@marginRight", + "data": "${listData}", + "numbered": true, + "items": [ + { + "type": "VerticalListItem", + "image": "${data.image.sources[0].url}", + "primaryText": "${data.textContent.primaryText.text}", + "secondaryText": "${data.textContent.secondaryText.text}", + "tertiaryText": "${data.textContent.tertiaryText.text}" + } + ] + } + ] + } + ] + }, + "VerticalListItem": { + "parameters": ["primaryText", "secondaryText", "tertiaryText", "image"], + "item": [ + { + "when": "${viewport.shape == 'round'}", + "type": "Container", + "direction": "row", + "height": 200, + "width": 500, + "alignItems": "center", + "items": [ + { + "type": "Text", + "text": "${ordinal}", + "paddingBottom": "20dp", + "color": "white", + "spacing": "5dp" + }, + { + "type": "Image", + "when": "${image}", + "source": "${image}", + "height": 150, + "width": 150, + "spacing": 15, + "scale": "best-fit", + "align": "top" + }, + { + "type": "Container", + "direction": "column", + "spacing": 25, + "items": [ + { + "type": "Text", + "text": "${primaryText}", + "style": "textStyleDetail", + "grow": 1, + "shrink": 1, + "fontWeight": "300", + "maxLines": 1 + }, + { + "type": "Text", + "text": "${secondaryText}", + "style": "textStyleCaption", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + }, + { + "type": "Text", + "text": "${tertiaryText}", + "style": "textStyleDetails", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + } + ] + } + ] + }, + { + "type": "Container", + "direction": "row", + "height": 125, + "width": 800, + "alignItems": "center", + "items": [ + { + "type": "Text", + "text": "${ordinal}", + "paddingBottom": "20dp", + "color": "white", + "spacing": "5dp" + }, + { + "type": "Image", + "when": "${image}", + "source": "${image}", + "height": 100, + "width": 100, + "align": "top", + "spacing": 50, + "scale": "best-fit" + }, + { + "type": "Container", + "spacing": 30, + "direction": "column", + "items": [ + { + "type": "Text", + "text": "${primaryText}", + "style": "textStyleBody", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + }, + { + "type": "Text", + "text": "${secondaryText}", + "style": "textStyleDetails", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + } + ] + }, + { + "type": "Text", + "text": "${tertiaryText}", + "style": "textStyleBody", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "textAlign": "right", + "maxLines": 1 + } + ] + } + ] + } + }, + "mainTemplate": { + "parameters": ["payload"], + "item": [ + { + "type": "Container", + "id": "BookCabSimpleDialogAPL", + "items": [ + { + "type": "TouchWrapper", + "onPress": { + "type": "SendEvent", + "arguments": ["delegateToColtraneOld"] + }, + "item": { + "type": "Text", + "id": "BookCabSimpleDialogAPL", + "paddingTop": "100", + "paddingLeft": "100", + "color": "green", + "size": 50, + "text": "which date ?" + } + } + ] + } + ] + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/display/weather_success_apl_display/document.json b/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/display/weather_success_apl_display/document.json new file mode 100644 index 00000000..3bcc0e4a --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/display/weather_success_apl_display/document.json @@ -0,0 +1,379 @@ +{ + "type": "APL", + "version": "1.1", + "settings": {}, + "theme": "dark", + "import": [ + { + "name": "alexa-layouts", + "version": "1.0.0" + } + ], + "resources": [ + { + "description": "Stock color for the light theme", + "colors": { + "colorTextPrimary": "#151920" + } + }, + { + "description": "Stock color for the dark theme", + "when": "${viewport.theme == 'dark'}", + "colors": { + "colorTextPrimary": "#f0f1ef" + } + }, + { + "description": "Standard font sizes", + "dimensions": { + "textSizeBody": 48, + "textSizePrimary": 27, + "textSizeSecondary": 23, + "textSizeDetails": 20, + "textSizeSecondaryHint": 25 + } + }, + { + "description": "Common spacing values", + "dimensions": { + "spacingThin": 6, + "spacingSmall": 12, + "spacingMedium": 24, + "spacingLarge": 48, + "spacingExtraLarge": 72 + } + }, + { + "description": "Common margins and padding", + "dimensions": { + "marginTop": 40, + "marginLeft": 60, + "marginRight": 60, + "marginBottom": 40 + } + } + ], + "styles": { + "textStyleBase": { + "description": "Base font description; set color", + "values": [ + { + "color": "@colorTextPrimary" + } + ] + }, + "textStyleBase0": { + "description": "Thin version of basic font", + "extend": "textStyleBase", + "values": { + "fontWeight": "100" + } + }, + "textStyleBase1": { + "description": "Light version of basic font", + "extend": "textStyleBase", + "values": { + "fontWeight": "300" + } + }, + "textStyleBase2": { + "description": "Regular version of basic font", + "extend": "textStyleBase", + "values": { + "fontWeight": "500" + } + }, + "mixinBody": { + "values": { + "fontSize": "@textSizeBody" + } + }, + "mixinPrimary": { + "values": { + "fontSize": "@textSizePrimary" + } + }, + "mixinDetails": { + "values": { + "fontSize": "@textSizeDetails" + } + }, + "mixinSecondary": { + "values": { + "fontSize": "@textSizeSecondary" + } + }, + "textStylePrimary": { + "extend": ["textStyleBase1", "mixinPrimary"] + }, + "textStyleSecondary": { + "extend": ["textStyleBase0", "mixinSecondary"] + }, + "textStyleBody": { + "extend": ["textStyleBase1", "mixinBody"] + }, + "textStyleSecondaryHint": { + "values": { + "fontFamily": "Bookerly", + "fontStyle": "italic", + "fontSize": "@textSizeSecondaryHint", + "color": "@colorTextPrimary" + } + }, + "textStyleDetails": { + "extend": ["textStyleBase2", "mixinDetails"] + } + }, + "onMount": [], + "graphics": {}, + "commands": {}, + "layouts": { + "ListTemplate1": { + "parameters": ["backgroundImage", "title", "logo", "hintText", "listData"], + "item": [ + { + "type": "Container", + "width": "100vw", + "height": "100vh", + "direction": "column", + "items": [ + { + "type": "Image", + "source": "${backgroundImage}", + "scale": "best-fill", + "width": "100vw", + "height": "100vh", + "position": "absolute" + }, + { + "type": "AlexaHeader", + "headerTitle": "${title}", + "headerAttributionImage": "${logo}" + }, + { + "type": "Sequence", + "grow": 1, + "height": "80vh", + "scrollDirection": "vertical", + "paddingLeft": "@marginLeft", + "paddingRight": "@marginRight", + "data": "${listData}", + "numbered": true, + "items": [ + { + "type": "VerticalListItem", + "image": "${data.image.sources[0].url}", + "primaryText": "${data.textContent.primaryText.text}", + "secondaryText": "${data.textContent.secondaryText.text}", + "tertiaryText": "${data.textContent.tertiaryText.text}" + } + ] + } + ] + } + ] + }, + "VerticalListItem": { + "parameters": ["primaryText", "secondaryText", "tertiaryText", "image"], + "item": [ + { + "when": "${viewport.shape == 'round'}", + "type": "Container", + "direction": "row", + "height": 200, + "width": 500, + "alignItems": "center", + "items": [ + { + "type": "Text", + "text": "${ordinal}", + "paddingBottom": "20dp", + "color": "white", + "spacing": "5dp" + }, + { + "type": "Image", + "when": "${image}", + "source": "${image}", + "height": 150, + "width": 150, + "spacing": 15, + "scale": "best-fit", + "align": "top" + }, + { + "type": "Container", + "direction": "column", + "spacing": 25, + "items": [ + { + "type": "Text", + "text": "${primaryText}", + "style": "textStyleDetail", + "grow": 1, + "shrink": 1, + "fontWeight": "300", + "maxLines": 1 + }, + { + "type": "Text", + "text": "${secondaryText}", + "style": "textStyleCaption", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + }, + { + "type": "Text", + "text": "${tertiaryText}", + "style": "textStyleDetails", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + } + ] + } + ] + }, + { + "type": "Container", + "direction": "row", + "height": 125, + "width": 800, + "alignItems": "center", + "items": [ + { + "type": "Text", + "text": "${ordinal}", + "paddingBottom": "20dp", + "color": "white", + "spacing": "5dp" + }, + { + "type": "Image", + "when": "${image}", + "source": "${image}", + "height": 100, + "width": 100, + "align": "top", + "spacing": 50, + "scale": "best-fit" + }, + { + "type": "Container", + "spacing": 30, + "direction": "column", + "items": [ + { + "type": "Text", + "text": "${primaryText}", + "style": "textStyleBody", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + }, + { + "type": "Text", + "text": "${secondaryText}", + "style": "textStyleDetails", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + } + ] + }, + { + "type": "Text", + "text": "${tertiaryText}", + "style": "textStyleBody", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "textAlign": "right", + "maxLines": 1 + } + ] + } + ] + } + }, + "mainTemplate": { + "parameters": ["payload"], + "item": [ + { + "type": "Container", + "id": "BookCabSimpleDialogAPL", + "items": [ + { + "type": "TouchWrapper", + "onPress": { + "type": "SendEvent", + "arguments": ["delegateToSkillNew"] + }, + "item": { + "type": "Text", + "id": "BookCabSimpleDialogAPL", + "paddingTop": "100", + "paddingLeft": "100", + "color": "green", + "size": 50, + "text": "delegateToSkillNew" + } + }, + { + "type": "TouchWrapper", + "onPress": { + "type": "SendEvent", + "arguments": ["delegateToSkillOld"] + }, + "item": { + "type": "Text", + "id": "BookCabSimpleDialogAPL", + "paddingTop": "100", + "paddingLeft": "100", + "color": "green", + "size": 50, + "text": "delegateToSkillOld" + } + }, + { + "type": "TouchWrapper", + "onPress": { + "type": "SendEvent", + "arguments": ["delegateToColtraneNew"] + }, + "item": { + "type": "Text", + "id": "BookCabSimpleDialogAPL", + "paddingTop": "100", + "paddingLeft": "100", + "color": "green", + "size": 50, + "text": "delegateToColtraneNew" + } + }, + { + "type": "TouchWrapper", + "onPress": { + "type": "SendEvent", + "arguments": ["delegateToColtraneOld"] + }, + "item": { + "type": "Text", + "id": "BookCabSimpleDialogAPL", + "paddingTop": "100", + "paddingLeft": "100", + "color": "green", + "size": 50, + "text": "delegateToColtraneOld" + } + } + ] + } + ] + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/AlexaConversationsBye/document.json b/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/AlexaConversationsBye/document.json new file mode 100644 index 00000000..a0e2b3a8 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/AlexaConversationsBye/document.json @@ -0,0 +1,19 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": ["payload"], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "Bye.", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/AlexaConversationsNotifyFailure/document.json b/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/AlexaConversationsNotifyFailure/document.json new file mode 100644 index 00000000..61d75e08 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/AlexaConversationsNotifyFailure/document.json @@ -0,0 +1,19 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": ["payload"], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "Sorry, there was an error in the request.", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/AlexaConversationsOutOfDomain/document.json b/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/AlexaConversationsOutOfDomain/document.json new file mode 100644 index 00000000..e23d5986 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/AlexaConversationsOutOfDomain/document.json @@ -0,0 +1,19 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": ["payload"], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "Sorry, I don't understand.", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/AlexaConversationsProvideHelp/document.json b/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/AlexaConversationsProvideHelp/document.json new file mode 100644 index 00000000..612a6f6e --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/AlexaConversationsProvideHelp/document.json @@ -0,0 +1,19 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": ["payload"], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "I can give you the weather report. Just say \"what's the weather\" to start.", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/AlexaConversationsRequestMore/document.json b/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/AlexaConversationsRequestMore/document.json new file mode 100644 index 00000000..32a98507 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/AlexaConversationsRequestMore/document.json @@ -0,0 +1,19 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": ["payload"], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "What do you want to do.", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/AlexaConversationsThankYou/document.json b/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/AlexaConversationsThankYou/document.json new file mode 100644 index 00000000..4aeb6f4b --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/AlexaConversationsThankYou/document.json @@ -0,0 +1,19 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": ["payload"], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "Thank you.", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/AlexaConversationsWelcome/document.json b/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/AlexaConversationsWelcome/document.json new file mode 100644 index 00000000..b4ce85fe --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/AlexaConversationsWelcome/document.json @@ -0,0 +1,19 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": ["payload"], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "Welcome to the weather bot, I can give you the weather report. Just say \"what's the weather\" to start.", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/AlexaConversationsYouAreWelcome/document.json b/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/AlexaConversationsYouAreWelcome/document.json new file mode 100644 index 00000000..2cd1b9a8 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/AlexaConversationsYouAreWelcome/document.json @@ -0,0 +1,19 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": ["payload"], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "You are welcome.", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/alexa_prize_preconditions_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/alexa_prize_preconditions_apla/document.json new file mode 100644 index 00000000..60503182 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/alexa_prize_preconditions_apla/document.json @@ -0,0 +1,89 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": ["payload"], + "item": { + "type": "Selector", + "description": "Selects the speech response to render when device/locale is not supported", + "items": [ + { + "when": "${payload.result.isDeviceSupported == 0}", + "type": "Speech", + "contentType": "text", + "content": "Sorry, Alexa Prize is not available on this device.", + "description": "" + }, + { + "when": "${payload.result.isLocaleSupported == 0}", + "type": "Speech", + "contentType": "text", + "content": "Sorry, Alexa Prize is not available in your locale.", + "description": "" + }, + { + "when": "${payload.result.isSocialBotAvailable == 0}", + "type": "Speech", + "contentType": "text", + "content": "Right now the Alexa Prize socialbots are busy. Please try again soon and help the university students in their competition to advance conversational A I.", + "description": "" + }, + { + "when": "${payload.result.isAlexaPrizeEnabled == 0}", + "type": "Speech", + "contentType": "text", + "content": "Alexa Prize is currently disabled for this account. Please visit the skill store in the Alexa App to re-enable it.", + "description": "" + }, + { + "when": "${payload.result.isTopicBanned == 1}", + "type": "Speech", + "contentType": "text", + "content": "I’d rather not talk about that, but there’s lots of other things to chat about. Do you still wanna chat?", + "description": "The topic that user wants to talk about is banned, ask if they still want to chat about something else" + }, + { + "when": "${payload.result.isFalseWake == 1}", + "type": "Speech", + "contentType": "text", + "content": "Would you like to chat with an Alexa Prize socialbot?", + "description": "" + }, + { + "when": "${payload.result.handoffPromptOverride == 'HandOffConversationForFilming'}", + "type": "Speech", + "contentType": "text", + "content": "Welcome to the Finals of the Alexa Prize Socialbot Grand Challenge 3, a university competition to advance AI. I’ll get you a socialbot now.", + "description": "" + }, + { + "when": "${payload.result.handoffPromptOverride == 'HandOffConversationForFinals'}", + "type": "Speech", + "contentType": "text", + "content": "Welcome to the Alexa Prize Socialbot Grand Challenge 3: Grand Finale. Here’s one of the finalists.", + "description": "" + }, + { + "when": "${payload.result.handoffPromptOverride == 'HandOffConversationForRepeatUser'}", + "type": "Speech", + "contentType": "text", + "content": "Welcome to the Alexa Prize, a university competition to advance AI. It’s quarterfinals for these socialbots and your ratings help determine who makes it to the semifinals. I’ll get you a socialbot now. When you’re done, say stop, and I’ll ask you for your rating. Your conversation and feedback will be shared with the university to help the socialbots improve.", + "description": "" + }, + { + "when": "${payload.result.handoffPromptOverride == 'CancelHandoff'}", + "type": "Speech", + "contentType": "text", + "content": "Okay", + "description": "" + }, + { + "type": "Speech", + "contentType": "text", + "content": "Welcome to the Alexa Prize, a university competition to advance AI. It’s quarterfinals for these socialbots and your ratings help determine who makes it to the semifinals. I’ll get you a socialbot now. When you’re done, say stop, and I’ll ask you for your rating. Your conversation and feedback will be shared with the university to help the socialbots improve.", + "description": "This is the current default handoff prompt" + } + ] + } + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/confirm_color_for_fruit_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/confirm_color_for_fruit_apla/document.json new file mode 100644 index 00000000..62c9758b --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/confirm_color_for_fruit_apla/document.json @@ -0,0 +1,19 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": ["payload"], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "confirm color is ${payload.colorName} ? ", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/confirm_fruitName_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/confirm_fruitName_apla/document.json new file mode 100644 index 00000000..47433a49 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/confirm_fruitName_apla/document.json @@ -0,0 +1,19 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": ["payload"], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "confirm fruit ${payload.fruitName} ? ", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/getEmployeePosition_success_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/getEmployeePosition_success_apla/document.json new file mode 100644 index 00000000..d0a91481 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/getEmployeePosition_success_apla/document.json @@ -0,0 +1,19 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": ["payload"], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "${payload.result.name1} born on ${payload.result.a_dateOfBirth} with employee id ${payload.result.emplyee1id} , is an ${payload.result.position} ", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/no_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/no_apla/document.json new file mode 100644 index 00000000..96a3af82 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/no_apla/document.json @@ -0,0 +1,19 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": ["payload"], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "I'm sorry you didn't like it", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/nothing2_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/nothing2_apla/document.json new file mode 100644 index 00000000..af75a7a5 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/nothing2_apla/document.json @@ -0,0 +1,19 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": ["payload"], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "The number you gave us was not 3.", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/nothing_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/nothing_apla/document.json new file mode 100644 index 00000000..bca77c74 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/nothing_apla/document.json @@ -0,0 +1,19 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": ["payload"], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "The number you gave us was 3.", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/numericfeedback_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/numericfeedback_apla/document.json new file mode 100644 index 00000000..2219120c --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/numericfeedback_apla/document.json @@ -0,0 +1,19 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": ["payload"], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "Your random number was ${payload.num}. How did we do? Please give this interaction a rating between 1-5, where 5 is the highest rating", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/rating_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/rating_apla/document.json new file mode 100644 index 00000000..06b50d68 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/rating_apla/document.json @@ -0,0 +1,19 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": ["payload"], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "rating please?", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/requestArgs_request_fruitName_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/requestArgs_request_fruitName_apla/document.json new file mode 100644 index 00000000..5e5d608a --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/requestArgs_request_fruitName_apla/document.json @@ -0,0 +1,25 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": ["payload"], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "tell me the fruit name ?", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + }, + { + "type": "Speech", + "contentType": "text", + "content": "random slection tell me the fruit name ?", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/request_city_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/request_city_apla/document.json new file mode 100644 index 00000000..64297b5e --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/request_city_apla/document.json @@ -0,0 +1,19 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": ["payload"], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "Which city?", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/request_city_date_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/request_city_date_apla/document.json new file mode 100644 index 00000000..a55ea5e1 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/request_city_date_apla/document.json @@ -0,0 +1,19 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": ["payload"], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "Which city and for which date?", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/request_colorName_multiple_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/request_colorName_multiple_apla/document.json new file mode 100644 index 00000000..5e5891e1 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/request_colorName_multiple_apla/document.json @@ -0,0 +1,19 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": ["payload"], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "which color?", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/request_date_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/request_date_apla/document.json new file mode 100644 index 00000000..af3a3f7d --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/request_date_apla/document.json @@ -0,0 +1,19 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": ["payload"], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "Which date?", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/request_dob_getDate_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/request_dob_getDate_apla/document.json new file mode 100644 index 00000000..b70a2ac6 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/request_dob_getDate_apla/document.json @@ -0,0 +1,19 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": ["payload"], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "SSML", + "content": "provide date?", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/request_getEmploeeID_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/request_getEmploeeID_apla/document.json new file mode 100644 index 00000000..32c39133 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/request_getEmploeeID_apla/document.json @@ -0,0 +1,19 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": ["payload"], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "SSML", + "content": "provide employee id?", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/request_name_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/request_name_apla/document.json new file mode 100644 index 00000000..db05dfee --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/request_name_apla/document.json @@ -0,0 +1,19 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": ["payload"], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "SSML", + "content": "what is your cool name?", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/success_colorFruitAPI_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/success_colorFruitAPI_apla/document.json new file mode 100644 index 00000000..b566e3fb --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/success_colorFruitAPI_apla/document.json @@ -0,0 +1,19 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": ["payload"], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "price of an ${payload.result.fruitName} is free bucks ", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/success_fruitPriceAPI_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/success_fruitPriceAPI_apla/document.json new file mode 100644 index 00000000..0db81389 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/success_fruitPriceAPI_apla/document.json @@ -0,0 +1,19 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": ["payload"], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "price of an ${payload.result.fruitName} is ${payload.result.price} bucks ", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/weather_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/weather_apla/document.json new file mode 100644 index 00000000..b2f5f3d9 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/weather_apla/document.json @@ -0,0 +1,27 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": ["payload"], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "when": "${payload.weatherResult != null && payload.weatherResult.cityName != null && payload.weatherResult.highTemp != null && payload.weatherResult.lowTemp != null}", + "type": "Speech", + "contentType": "text", + "content": "In ${payload.weatherResult.cityName}, it's a high of ${payload.weatherResult.highTemp} degrees and a low of ${payload.weatherResult.lowTemp} degrees.", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + }, + { + "when": "${payload.weatherResult != null && payload.weatherResult.cityNameChanged != null && payload.weatherResult.highTemp != null && payload.weatherResult.lowTemp != null}", + "type": "Speech", + "contentType": "text", + "content": "In ${payload.weatherResult.cityName}, it's a high of ${payload.weatherResult.highTemp} degrees and a low of ${payload.weatherResult.lowTemp} degrees.", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/yes_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/yes_apla/document.json new file mode 100644 index 00000000..a443c91e --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/yes_apla/document.json @@ -0,0 +1,19 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": ["payload"], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "Nice! Glad you like it", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/yesnofeedback_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/yesnofeedback_apla/document.json new file mode 100644 index 00000000..fd08347e --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/yesnofeedback_apla/document.json @@ -0,0 +1,19 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": ["payload"], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "Your number was ${payload.num}. Is this a good number, yes or no?", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/skill.json b/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/skill.json new file mode 100644 index 00000000..5e99d129 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/skill.json @@ -0,0 +1,92 @@ +{ + "manifest": { + "apis": { + "custom": { + "dialogManagement": { + "dialogManagers": [ + { + "type": "AMAZON.Conversations" + } + ], + "sessionStartDelegationStrategy": { + "target": "AMAZON.Conversations" + } + }, + "endpoint": { + "uri": "arn:aws:lambda:us-east-1:658396899051:function:47172cde-7bb8-4e42-8fdb-dc5138bdf323:Release_0" + }, + "interfaces": [ + { + "supportedViewports": [ + { + "maxHeight": 480, + "maxWidth": 480, + "minHeight": 480, + "minWidth": 480, + "mode": "HUB", + "shape": "ROUND" + }, + { + "maxHeight": 600, + "maxWidth": 1024, + "minHeight": 600, + "minWidth": 1024, + "mode": "HUB", + "shape": "RECTANGLE" + }, + { + "maxHeight": 800, + "maxWidth": 1280, + "minHeight": 800, + "minWidth": 1280, + "mode": "HUB", + "shape": "RECTANGLE" + }, + { + "maxHeight": 540, + "maxWidth": 960, + "minHeight": 540, + "minWidth": 960, + "mode": "TV", + "shape": "RECTANGLE" + } + ], + "type": "ALEXA_PRESENTATION_APL" + } + ], + "regions": { + "EU": { + "endpoint": { + "uri": "arn:aws:lambda:eu-west-1:658396899051:function:47172cde-7bb8-4e42-8fdb-dc5138bdf323:Release_0" + } + }, + "NA": { + "endpoint": { + "uri": "arn:aws:lambda:us-east-1:658396899051:function:47172cde-7bb8-4e42-8fdb-dc5138bdf323:Release_0" + } + }, + "FE": { + "endpoint": { + "uri": "arn:aws:lambda:us-west-2:658396899051:function:47172cde-7bb8-4e42-8fdb-dc5138bdf323:Release_0" + } + } + } + } + }, + "manifestVersion": "1.0", + "publishingInformation": { + "category": "KNOWLEDGE_AND_TRIVIA", + "distributionCountries": [], + "isAvailableWorldwide": true, + "locales": { + "en-US": { + "description": "Sample Full Description", + "examplePhrases": ["Alexa open hello world", "hello", "help"], + "name": "engineering test skill one", + "summary": "Sample Short Description" + } + }, + "testingInstructions": "Sample Testing Instructions." + } + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/.ask/ask-states.json b/test/unit/fixture/dialog-evaluate/test-project-2/.ask/ask-states.json new file mode 100644 index 00000000..25e2965b --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-2/.ask/ask-states.json @@ -0,0 +1,8 @@ +{ + "askcliStatesVersion": "2020-03-31", + "profiles": { + "mft-test": { + "skillId": "amzn1.ask.skill.a3588a9b-d645-4a23-9e1a-90c984de0b83" + } + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/ask-resources.json b/test/unit/fixture/dialog-evaluate/test-project-2/ask-resources.json new file mode 100644 index 00000000..67851f3d --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-2/ask-resources.json @@ -0,0 +1,10 @@ +{ + "askcliResourcesVersion": "2020-03-31", + "profiles": { + "mft-test": { + "skillMetadata": { + "src": "./skill-package" + } + } + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/conversations/Samenamespace.acdl b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/conversations/Samenamespace.acdl new file mode 100644 index 00000000..b173cdf7 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/conversations/Samenamespace.acdl @@ -0,0 +1,7 @@ +namespace com.weatherbot.apis + +import com.amazon.ask.types.builtins.AMAZON.DATE +import com.weatherbot.types.WeatherResult +import slotTypes.customCity + +action WeatherResult getWeather(customCity cityName, DATE date) diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/conversations/apis.acdl b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/conversations/apis.acdl new file mode 100644 index 00000000..ca21531f --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/conversations/apis.acdl @@ -0,0 +1,51 @@ +namespace com.weatherbot.apis + +import com.amazon.alexa.schema.Nothing +import com.amazon.ask.types.builtins.AMAZON.Color +import com.amazon.ask.types.builtins.AMAZON.Food +import com.amazon.ask.types.builtins.AMAZON.NUMBER +import com.amazon.ask.types.builtins.AMAZON.US_CITY +import com.weatherbot.types.bookCabResult +import com.weatherbot.types.bookedFlightResult +import com.weatherbot.types.result +import com.weatherbot.types.result_one +import com.weatherbot.types.resultthree +import slotTypes.StringLiteral +import slotTypes.city_name_one +import slotTypes.city_name_two +import slotTypes.complexNames +import slotTypes.crust +import slotTypes.pickUpFrom +import slotTypes.signs +import slotTypes.size +import slotTypes.toppings + +action resultthree colorFruitNameAAA(Food fruitName = nothing) + +action resultthree colorFruitName(Color colorName, Food fruitName = nothing) + +action result fruitNameAPI(Food fruitName) + +action NUMBER numberOfVisits() + +action NUMBER getCooler() + +action NUMBER welcomeApi() + +action Nothing getHeater() + +action result_one favColorSign_Name(complexNames name) + +//action result_one favColorSign_Name(complexNames name, signs sign = nothing) + +action bookedFlightResult bookFlightAPI(city_name_one source, city_name_two destination) + +action bookCabResult bookCabAPI(pickUpFrom pickUpFrom, city_name_one dropTo = nothing) + +action Nothing secondEarthAPI() + +action StringLiteral OrderTwoToppingPizza(toppings second_topping, toppings first_topping, crust crust, size size = nothing) + +action Nothing satheesh(US_CITY citsy) + +action Nothing Satheesh(US_CITY citsy) diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/conversations/basicOfferDialog.acdl b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/conversations/basicOfferDialog.acdl new file mode 100644 index 00000000..0be5d696 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/conversations/basicOfferDialog.acdl @@ -0,0 +1,65 @@ +namespace offerDialogFile + +import com.amazon.alexa.ask.conversations.Affirm +import com.amazon.alexa.ask.conversations.CarryOverArgument +import com.amazon.alexa.ask.conversations.Inform +import com.amazon.alexa.ask.conversations.Invoke +import com.amazon.alexa.ask.conversations.Notify +import com.amazon.alexa.ask.conversations.Offer +import com.amazon.alexa.ask.conversations.Request +import com.amazon.alexa.ask.conversations.RequestArguments +import com.amazon.alexa.ask.conversations.ensure +import com.amazon.alexa.ask.conversations.expect +import com.amazon.alexa.ask.conversations.response +import com.amazon.alexa.schema.Nothing +import com.amazon.alexa.schema.Thing +import com.weatherbot.apis.bookCabAPI +import com.weatherbot.apis.bookFlightAPI +import com.weatherbot.types.bookCabResult +import com.weatherbot.types.bookedFlightResult +import com.weatherbot.utteracesets.affirmCabAPIEvent +import com.weatherbot.utteracesets.bookFlightEvent +import com.weatherbot.utteracesets.informFromBookFlight +import com.weatherbot.utteracesets.informPickUpFromBookCab +import com.weatherbot.utteracesets.informToBookFlight +import prompts.requestFromBookFlight_apla +import prompts.requestPickUpFromBookCab_apla +import prompts.requestToBookFlight_apla +import prompts.successBookCabAPI_apla +import prompts.successBookFlightAPI_apla +import slotTypes.* +import prompts.* +import displays.* +import com.weatherbot.utteracesets.* +import com.amazon.alexa.ask.conversations.* +import com.amazon.alexa.schema.* +import com.weatherbot.types.* + +type payloadBookFlightAPI { + bookedFlightResult resultTwo +} + +type payloadOfferResult { + bookCabResult result +} + +dialog Nothing complex_two() { + sample { + expect(act = Invoke,event = bookFlightEvent) + response(act = Request { arguments = [ bookFlightAPI.arguments.source ]},response = requestFromBookFlight_apla) + //response(act = Request { arguments = [ bookFlightAPI.arguments.source ]},response = requestFromBookFlight_apla) + // source is seattle + sourceFlightEvent = expect(act = Inform,event = informFromBookFlight) + response(act = Request { arguments = [ bookFlightAPI.arguments.destination ]},response = requestToBookFlight_apla) + // destination to portland + destinationFlightEvent = expect(act = Inform,event = informToBookFlight) + resultFlightApi = bookFlightAPI(source = sourceFlightEvent.source,destination = destinationFlightEvent.destination) + response(response = successBookFlightAPI_apla,act = Notify { actionName = bookFlightAPI, success = true},payload = payloadBookFlightAPI { resultTwo = resultFlightApi},nextAct = Offer { actionName = bookCabAPI, arguments = [ bookCabAPI.arguments.pickUpFrom ], carryOverArguments = [ CarryOverArgument { argument = bookCabAPI.arguments.dropTo, source = resultFlightApi.source } ]}) + ensure(requestArgs = [ RequestArguments { arguments = [ bookCabAPI.arguments.pickUpFrom ], response = requestPickUpFromBookCab_apla }]) + expect(act = Affirm,event = affirmCabAPIEvent) + response(response = requestPickUpFromBookCab_apla,act = Request { arguments = [ bookCabAPI.arguments.pickUpFrom ]}) + PickUpCabEvent = expect(act = Inform,event = informPickUpFromBookCab) + resultOne = bookCabAPI(pickUpFrom = PickUpCabEvent.pickUpFrom,dropTo = resultFlightApi.source) + response(response = successBookCabAPI_apla,act = Notify { actionName = bookCabAPI},payload = payloadOfferResult { result = resultOne}) + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/conversations/conditions b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/conversations/conditions new file mode 100644 index 00000000..5de831a6 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/conversations/conditions @@ -0,0 +1,71 @@ +namespace conditionsACDlFile + +import com.amazon.alexa.ask.conversations.Inform +import com.amazon.alexa.ask.conversations.Invoke +import com.amazon.alexa.ask.conversations.MultiModalResponse +import com.amazon.alexa.ask.conversations.Notify +import com.amazon.alexa.ask.conversations.Offer +import com.amazon.alexa.ask.conversations.ReqAlt +import com.amazon.alexa.ask.conversations.Request +import com.amazon.alexa.ask.conversations.RequestArguments +import com.amazon.alexa.ask.conversations.ensure +import com.amazon.alexa.ask.conversations.expect +import com.amazon.alexa.ask.conversations.response +import com.amazon.alexa.ask.conversations.size +import com.amazon.alexa.schema.Nothing +import com.amazon.alexa.schema.Thing +import com.weatherbot.apis.favColorSign_Name +import com.weatherbot.apis.getWeather +import com.weatherbot.types.WeatherResult +import com.weatherbot.types.result_one +import com.weatherbot.utteracesets.getWeatherEventNoArgs +import com.weatherbot.utteracesets.informCityEvent +import com.weatherbot.utteracesets.informComplexNameEvent +import com.weatherbot.utteracesets.informDateEvent +import displays.request_city_apl_display +import prompts.request_city_apla +import prompts.request_date_apla +import prompts.request_name_apla +import prompts.success_favColorSign_Name_apla +import prompts.weather_success_apla +import slotTypes.* +import prompts.* +import displays.* +import com.weatherbot.utteracesets.* +import com.amazon.alexa.ask.conversations.* +import com.amazon.alexa.schema.* +import com.weatherbot.types.* + +type payload_one { + result_one result +} + +type payload_one_two { + WeatherResult weatherResult +} + +dialog Nothing conditionComplex() { + sample { + expect(act = Invoke,event = getWeatherEventNoArgs) + request_city_multimodal = MultiModalResponse {apla = request_city_apla,apl = request_city_apl_display + } + request_date_multimodal = MultiModalResponse {apla = request_date_apla,apl = request_city_apl_display + } + response(response = request_city_multimodal,act = Request { arguments = [ getWeather.arguments.cityName ]}) + cityEvent = expect(act = Inform,event = informCityEvent) + response(response = request_date_multimodal,act = Request { arguments = [ getWeather.arguments.date ]}) + dateEvent = expect(act = Inform,event = informDateEvent) + weatherResult = getWeather(cityName = cityEvent.cityName,date = dateEvent.date) + if (((weatherResult.highTemp < 3 && weatherResult.lowTemp > 0) && com.amazon.alexa.ask.conversations.size(list = weatherResult.itemsToUse) > 1)) + {response( response = weather_success_apla, act = Notify {actionName = getWeather }, + nextAct = Offer { actionName = favColorSign_Name, arguments = [ favColorSign_Name.arguments.name ] }) + ensure( requestArgs = [ RequestArguments { arguments = [ favColorSign_Name.arguments.name ], response = request_name_apla } ]) + ComplexNameEvent = expect( act = Inform, event = informComplexNameEvent) + resultOne_one = favColorSign_Name( name = ComplexNameEvent.name) + response( response = success_favColorSign_Name_apla, act = Notify { actionName = favColorSign_Name }, + payload = payload_one { result = resultOne_one }) + } else { + response( response = weather_success_apla, act = Notify { actionName = getWeather,success = false }, nextAct = ReqAlt { arguments = [ getWeather.arguments.cityName ] }, payload = payload_one_two { weatherResult = weatherResult })cityEvent_new = expect( act = Inform, event = informCityEvent)weatherResult_two = getWeather( cityName = cityEvent_new.cityName, date = dateEvent.date)successAPLWithAPLsa_nw = MultiModalResponse { apla = weather_success_apla}response( response = successAPLWithAPLsa_nw, act = Notify { actionName = getWeather }, payload = payload_one_two { weatherResult = weatherResult_two }) + } + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/conversations/conversation_empty b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/conversations/conversation_empty new file mode 100644 index 00000000..2fa96708 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/conversations/conversation_empty @@ -0,0 +1,147 @@ +namespace com.numberbot + +import com.amazon.alexa.ask.conversations.APLA +import com.amazon.alexa.ask.conversations.Action +import com.amazon.alexa.ask.conversations.Bye +import com.amazon.alexa.ask.conversations.InvocationName +import com.amazon.alexa.ask.conversations.Invoke +import com.amazon.alexa.ask.conversations.Locale +import com.amazon.alexa.ask.conversations.Notify +import com.amazon.alexa.ask.conversations.Offer +import com.amazon.alexa.ask.conversations.RequestArguments +import com.amazon.alexa.ask.conversations.SkillLevelResponses +import com.amazon.alexa.ask.conversations.ensure +import com.amazon.alexa.ask.conversations.expect +import com.amazon.alexa.ask.conversations.response +import com.amazon.alexa.ask.conversations.skill +import com.amazon.alexa.ask.conversations.utterances +import com.amazon.alexa.schema.Nothing +import com.amazon.alexa.schema.Number +import com.amazon.alexa.schema.Thing +import com.amazon.ask.types.builtins.AMAZON.NUMBER +import prompts.AlexaConversationsBye +import prompts.AlexaConversationsOutOfDomain +import prompts.AlexaConversationsProvideHelp +import prompts.AlexaConversationsRequestMore +import prompts.AlexaConversationsWelcome +import prompts.numericfeedback_apla +import prompts.rating_apla +import slotTypes.* +import prompts.* +import displays.* +import com.weatherbot.utteracesets.* +import com.amazon.alexa.ask.conversations.* +import com.amazon.alexa.schema.* +import com.weatherbot.types.* +/* +mySkill = skill( + locales = [ + Locale.en_US + ], + dialogs = [ + MainDialog + ], + skillLevelResponses = SkillLevelResponses { + welcome = AlexaConversationsWelcome, + out_of_domain = AlexaConversationsOutOfDomain, + bye = AlexaConversationsBye, + reqmore = AlexaConversationsRequestMore, + provide_help = AlexaConversationsProvideHelp + }, + invocationNames = [ + InvocationName { + locale = Locale.en_US, + invocationName = "acdl number feedback bot" + } + ] +) + +*/ + +type NumPayload { + Number num +} + +type RatingRequest { + NUMBER rating +} + +InformRatingEvent = utterances( + samples = [ + "my score is {rating}", + "that was a {rating} conversation", + "i rate you a {rating}", + "{rating}" + ] +) + +getStart = utterances( + samples = [ + "give me a number please" + ] +) + +action Nothing saveRating(Number rating) + +action Number getNumber() + +dialog Nothing GetFeedback(APLA feedback_prompt, Thing payload, Action notifyAction) { + sample { + response( + response = feedback_prompt, + act = Notify { + actionName = notifyAction, + success = true + }, + nextAct = Offer { + actionName = saveRating, + arguments = [ + saveRating.arguments.rating + ] + }, + payload = payload + ) + myRating = expect( + act = Invoke, + event = InformRatingEvent + ) + ensure( + requestArgs = [ + RequestArguments { + arguments = [ + saveRating.arguments.rating + ], + response = rating_apla + } + ] + ) + saveRating( + rating = myRating.rating + ) + } +} + +dialog Nothing MainDialog() { + sample { + expect( + act = Invoke, + event = getStart + ) + num = getNumber() + GetFeedback( + feedback_prompt = numericfeedback_apla, + payload = NumPayload { + num = num + }, + notifyAction = getNumber + ) + response( + response = AlexaConversationsBye, + act = Notify { + actionName = saveRating, + success = true + }, + nextAct = Bye {} + ) + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/conversations/delegateToSkill.acdl b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/conversations/delegateToSkill.acdl new file mode 100644 index 00000000..b9c572d6 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/conversations/delegateToSkill.acdl @@ -0,0 +1,33 @@ +namespace delegateToSkill + +import com.amazon.alexa.ask.conversations.Invoke +import com.amazon.alexa.ask.conversations.Notify +import com.amazon.alexa.ask.conversations.expect +import com.amazon.alexa.ask.conversations.response +import com.amazon.alexa.schema.Nothing +import com.weatherbot.apis.secondEarthAPI +import com.weatherbot.utteracesets.delegateToSkill +import prompts.secondEarthAPI_apla +import slotTypes.* +import prompts.* +import displays.* +import com.weatherbot.utteracesets.* +import com.amazon.alexa.ask.conversations.* +import com.amazon.alexa.schema.* +import com.weatherbot.types.* +dialog Nothing testTwo() { + sample { + expect( + act = Invoke, + event = delegateToSkill + ) + secondEarthAPI() + response( + response = secondEarthAPI_apla, + act = Notify { + actionName = secondEarthAPI + }, + nextAct = nothing + ) + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/conversations/dialogWeather.acdl b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/conversations/dialogWeather.acdl new file mode 100644 index 00000000..60962dc9 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/conversations/dialogWeather.acdl @@ -0,0 +1,9 @@ +namespace dialogWeather + +import com.amazon.ask.types.builtins.AMAZON.DATE +import slotTypes.customCity + +type payloadConfirmArgsDialogWeather { + optional customCity cityName + optional DATE date +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/conversations/listDialogWithConditions.acdl b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/conversations/listDialogWithConditions.acdl new file mode 100644 index 00000000..a421edfa --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/conversations/listDialogWithConditions.acdl @@ -0,0 +1,243 @@ +namespace listDialog + +import com.amazon.alexa.ask.conversations.Affirm +import com.amazon.alexa.ask.conversations.ConfirmAction +import com.amazon.alexa.ask.conversations.ConfirmArgs +import com.amazon.alexa.ask.conversations.Inform +import com.amazon.alexa.ask.conversations.Invoke +import com.amazon.alexa.ask.conversations.Notify +import com.amazon.alexa.ask.conversations.Request +import com.amazon.alexa.ask.conversations.received +import com.amazon.alexa.ask.conversations.confirmAction + +import com.amazon.alexa.ask.conversations.expect +import com.amazon.alexa.ask.conversations.response +import com.amazon.alexa.ask.conversations.size +import com.amazon.alexa.ask.conversations.utterances +import com.amazon.alexa.schema.List +import com.amazon.alexa.schema.String +import com.amazon.alexa.schema.Nothing +import com.amazon.ask.types.builtins.AMAZON.Food +import com.amazon.ask.types.builtins.AMAZON.NUMBER +import com.weatherbot.apis.* +import com.weatherbot.apis.fruitNameAPI +import com.weatherbot.apis.numberOfVisits +import com.weatherbot.types.result +import com.weatherbot.utteracesets.GiveMeTodaySpecialsEvent +import com.weatherbot.utteracesets.affirmCookAPIEvent +import com.weatherbot.utteracesets.affirmFruitAPIEvent +import com.weatherbot.utteracesets.cookWithTwoIngredientsEvent +import com.weatherbot.utteracesets.getFruitPriceEvent +import com.weatherbot.utteracesets.informFoodNameEvent +import com.weatherbot.utteracesets.informfruitNameEvent +import prompts.SuccessGiveMeTodaySpecialsEvent_apla +import prompts.confirm_fruitName_apla +import prompts.confirm_main_addon_list_apla +import prompts.requestArgs_request_fruitName_apla +import prompts.request_listAddOns_apla +import prompts.request_mainFoodName_apla +import prompts.success_cookingAPI_apla +import prompts.success_fruitPriceAPI_apla +import slotTypes.orderStatus +import slotTypes.* +import prompts.* +import displays.* +import com.weatherbot.utteracesets.* +import com.amazon.alexa.ask.conversations.* +import com.amazon.alexa.schema.* +import com.weatherbot.types.* +type addOnShell { + List addOn +} + +action orderStatus cookingAPI(Food foodName, List addOn) + +action List todaySpecials() + +informlistAddOnsEvent = utterances( + samples = [ + "{addOn}", + "add {addOn}", + "mix {addOn}" + ] +) + +type payloadStatuscookWithTwoIngredients { + orderStatus status +} + +type payloadGiveMeTodaySpecials { + List result +} + +type payloadgetFruitPriceEvent { + result result +} + +type payloadConfirmActionComplex { + optional Food foodName + List addOn +} + +type paylaodCompleFruit { + Food fruitName +} + +type WrongpayloadGiveMeTodaySpecialsNew { + List ListOfMix1 + Mix Mix1 +} + +type payloadGiveMeTodaySpecialsNew { + List ListOfMix1 +} + + +type InteractionFoodName { + Food foodName +} + + +interaction { + received(Invoke,"let us cook") + response(response = request_listAddOns_apla,act = Request { arguments = [ cookingAPI.arguments.addOn ]}) + actual { + listAddOnsEventOneName = received(Inform, "{bread|ListOfMix1} and {jam|Mix1}") + } expected { + listAddOnsEventOne = received(Inform, "{bread|ListOfMix1} and {jam|ListOfMix1}") + } + response(response = request_mainFoodName_apla,act = Request { arguments = [ cookingAPI.arguments.foodName ]}) + FoodNameEventInte = received(Inform,"{cake|foodName}") + response(response = confirm_main_addon_list_apla,act = ConfirmAction { actionName = cookingAPI}, + payload = payloadConfirmActionComplex { foodName = FoodNameEventInte.foodName, addOn = listAddOnsEventOne.ListOfMix1}) + received(Affirm,"ok for sure") + resultOneInteList = cookingAPI(foodName = FoodNameEventInte.foodName,addOn = listAddOnsEventOne.ListOfMix1) + response(response = success_cookingAPI_apla,act = Notify { actionName = cookingAPI}, + payload = payloadStatuscookWithTwoIngredients { status = resultOneInteList}) +} + + +dialog Nothing complex() { + sample { + expect(act = Invoke,event = cookWithTwoIngredientsEvent) + response(response = request_listAddOns_apla,act = Request { arguments = [ cookingAPI.arguments.addOn ]}) + + listAddOnsEvent = expect(act = Inform,event = informlistAddOnsEvent) + response(response = request_mainFoodName_apla,act = Request { arguments = [ cookingAPI.arguments.foodName ]}) + + FoodNameEvent = expect(act = Inform,event = informFoodNameEvent) + + + response(response = confirm_main_addon_list_apla,act = ConfirmAction { actionName = cookingAPI},payload = payloadConfirmActionComplex { foodName = FoodNameEvent.foodName, addOn = listAddOnsEvent.addOn}) + // ok for sure + expect(act = Affirm,event = affirmCookAPIEvent) + + resultOne = cookingAPI(foodName = FoodNameEvent.foodName,addOn = listAddOnsEvent.addOn) + + response(response = success_cookingAPI_apla,act = Notify { actionName = cookingAPI}, + payload = payloadStatuscookWithTwoIngredients { status = resultOne}) + } + + + + + + + + sample { + expect(act = Invoke,event = GiveMeTodaySpecialsEvent) + numberOfVisits() + resultOne = todaySpecials() + if (com.amazon.alexa.ask.conversations.size(list = resultOne) == 1) { + response(response = SuccessGiveMeTodaySpecialsEvent_apla, act = Notify { actionName = todaySpecials }, payload = payloadGiveMeTodaySpecials { result = resultOne }) + } + } + + + + + + sample { + // "content": "what is the price of the fruit" + expect(act = Invoke,event = getFruitPriceEvent) + response(response = requestArgs_request_fruitName_apla,act = Request { arguments = [ fruitNameAPI.arguments.fruitName ]}) + // "content": "fruit name is apple" + fruitNameEvent = expect(act = Inform,event = informfruitNameEvent) + //response(response = confirm_fruitName_apla, act = ConfirmArgs { arguments = [fruitNameAPI.arguments.fruitName]},payload = paylaodCompleFruit { fruitName = fruitNameEvent.fruitName}) + + // expect(act = Affirm,event = affirmFruitAPIEvent) + resultOne = fruitNameAPI(fruitName = fruitNameEvent.fruitName) + // resposne1() + response(response = success_fruitPriceAPI_apla,act = Notify { actionName = fruitNameAPI},payload = payloadgetFruitPriceEvent { result = resultOne}) + + } +} + + + + + /* +type fruitEvent0 { + Food fruitName +} + +interaction { + actual { + fruitNameEvent1 = received(Inform, "fruit name is {apple|fruitName}") + resultOneTwo = fruitNameAPI(fruitName = fruitNameEvent1.fruitName) + response(response = success_fruitPriceAPI_apla,act = Notify { actionName = fruitNameAPI},payload = payloadgetFruitPriceEvent { result = resultOneTwo}) + } expected { + fruitNameEvent1 = received(Inform, "fruit name is {apple|fruitName}") + resultOne = todaySpecials() + if (com.amazon.alexa.ask.conversations.size(list = resultOne) == 1) { + response(response = SuccessGiveMeTodaySpecialsEvent_apla, act = Notify { actionName = todaySpecials }, payload = payloadGiveMeTodaySpecials { result = resultOne }) + } + } + } + +interaction { + + actual { + + + fruitNameEvent1 = received(Inform, "fruit name is {apple|fruitName}") + resultOneTwo = fruitNameAPI(fruitName = fruitNameEvent1.fruitName) + response(response = success_fruitPriceAPI_apla,act = Notify { actionName = fruitNameAPI},payload = payloadgetFruitPriceEvent { result = resultOneTwo}) + } expected { + fruitNameEvent1 = received(Inform, "fruit name is {apple|fruitName}") + } + + } + + + + + + + + + + + +interaction { + +actual { + + + fruitNameEvent1 = received(Inform, "fruit name is {apple|fruitName}") + response(response = confirm_fruitName_apla,act = ConfirmArgs { arguments = [ fruitNameAPI.arguments.fruitName ]}, + payload = paylaodCompleFruit { fruitName = fruitNameEvent1.fruitName}) + + } expected { + fruitNameEvent1 = received(Inform, "fruit name is {apple|fruitName}") + response(response = request_mainFoodName_apla, act = ConfirmAction { actionName = fruitNameAPI} , + payload = paylaodCompleFruit { fruitName = fruitNameEvent1.fruitName}) + } + +} +*/ + + + + + \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/conversations/optionalDelegate.acdl b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/conversations/optionalDelegate.acdl new file mode 100644 index 00000000..d69ecd3d --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/conversations/optionalDelegate.acdl @@ -0,0 +1,118 @@ +namespace optionalArgACDL + +import com.amazon.alexa.ask.conversations.Affirm +import com.amazon.alexa.ask.conversations.ConfirmArgs +import com.amazon.alexa.ask.conversations.Inform +import com.amazon.alexa.ask.conversations.Invoke +import com.amazon.alexa.ask.conversations.MultiModalResponse +import com.amazon.alexa.ask.conversations.Notify +import com.amazon.alexa.ask.conversations.Request +import com.amazon.alexa.ask.conversations.expect +import com.amazon.alexa.ask.conversations.response +import com.amazon.alexa.schema.Nothing +import com.amazon.alexa.schema.Thing +import com.weatherbot.apis.favColorSign_Name +import com.weatherbot.types.payloadConfirmActionConditionComplex +import com.weatherbot.types.result_one +import com.weatherbot.utteracesets.affirmFavColorEvent + +import com.weatherbot.utteracesets.informComplexNameEvent +import prompts.request_name_apla +import prompts.success_favColorSign_Name_apla +import slotTypes.complexNames +import slotTypes.* +import prompts.* +import displays.* +import com.weatherbot.utteracesets.* +import com.amazon.alexa.ask.conversations.* +import com.amazon.alexa.schema.* +import com.weatherbot.types.* +type payloadResult_optional { + result_one result +} + +type payloadResult_optional_name { + complexNames name +} + + + +// 1. New Prompt we cant map (Not used within any samples)) +// 2. New DialogACtType alone we cant map , should be done with apla prompts +// 3. WE can make use of an exisitng apla prompt and change type -> Shoudl be . +// 4. Payload Can be changed + + +getFavColorEvent = utterances( + samples = [ + "what is my favourite color", + "tell my favourite color" + ] +) + + +getFavColorEventTwo = utterances( + samples = [ + "guess the color" + ] +) + + +dialog Nothing optiOnal() { + sample { + expect(act = Invoke,event = getFavColorEvent) + response(act = Request { arguments = [ favColorSign_Name.arguments.name ]},response = MultiModalResponse { apla = request_name_apla}) + + ComplexNameEvent = expect(act = Inform,event = informComplexNameEvent) + response(response = confirmArgs_complexNames_apla, act = ConfirmArgs { arguments = [ favColorSign_Name.arguments.name ]}, + payload = payloadConfirmActionConditionComplex { name = ComplexNameEvent.name}) + + expect(act = Affirm,event = affirmFavColorEvent) + resultOne = favColorSign_Name(name = ComplexNameEvent.name) + response(response = success_favColorSign_Name_apla,act = Notify { actionName = favColorSign_Name}, + payload = payloadResult_optional { result = resultOne}) + } +} + +type PAYLOAD_TYPE01 { complexNames name} + +dialog Nothing optiOnalTwo() { + sample { + expect(act = Invoke,event = getFavColorEventTwo) + response(act = Request { arguments = [ favColorSign_Name.arguments.name ]},response = MultiModalResponse { apla = request_name_apla}) + + ComplexNameEvent = expect(act = Inform,event = informComplexNameEvent) + response(response = confirmAction_complexNames_apla, act = ConfirmAction {actionName = favColorSign_Name}, payload = payloadConfirmActionConditionComplex { name = ComplexNameEvent.name}) + + expect(act = Affirm,event = affirmFavColorEvent) + result1 = favColorSign_Name(name = ComplexNameEvent.name) + response(response = success_favColorSign_Name_apla,act = Notify { actionName = favColorSign_Name}, payload = payloadResult_optional { result = result1}) + } +} + + + +//com.amazon.alexa.ask.conversations.response( response = confirmArgs_complexNames_apla, act = com.amazon.alexa.ask.conversations.ConfirmArgs {arguments = [com.weatherbot.apis.favColorSign_Name.arguments.name ]}, surfaceForm = "confirm Action your cool name satheesh and ?", payload = PAYLOAD_TYPE1{name = Var1.complexNames1}) + +/* +com.amazon.alexa.ask.conversations.response( response = confirmArgs_complexNames_apla, act = com.amazon.alexa.ask.conversations.ConfirmArgs { arguments = [com.weatherbot.apis.favColorSign_Name.arguments.name ]}, surfaceForm = "", payload = PAYLOAD_TYPE0{complexNames = Var0.complexNames1}) + +com.amazon.alexa.ask.conversations.response( response = confirmArgs_complexNames_apla, act = com.amazon.alexa.ask.conversations.ConfirmArgs { arguments = [ favColorSign_Name.arguments.name ]}, surfaceForm = "", payload = Type0( complexNames = Var0.complexNames1 )) + +type nameShellInteract { + complexNames name +} +interaction { + actual { + ComplexNameEvent1 = received(Inform, "name is {satheesh|name}") + response(response = confirmAction_complexNames_apla, act = ConfirmAction {actionName = favColorSign_Name}, + payload = payloadConfirmActionConditionComplex { name = ComplexNameEvent1.name}) + } expected { + ComplexNameEvent1 = received(Inform, "name is {satheesh|name}") + response(response = confirmArgs_complexNames_apla, act = ConfirmArgs { arguments = [ favColorSign_Name.arguments.name ]}, + payload = payloadConfirmActionConditionComplex { name = ComplexNameEvent1.name}) + } + } + +*/ + \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/conversations/pizza.acdl b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/conversations/pizza.acdl new file mode 100644 index 00000000..d00a6c87 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/conversations/pizza.acdl @@ -0,0 +1,189 @@ +namespace pizzaAcdl + +import com.amazon.alexa.ask.conversations.Affirm +import com.amazon.alexa.ask.conversations.ConfirmAction +import com.amazon.alexa.ask.conversations.ConfirmArgs +import com.amazon.alexa.ask.conversations.Inform +import com.amazon.alexa.ask.conversations.Invoke +import com.amazon.alexa.ask.conversations.MultiModalResponse +import com.amazon.alexa.ask.conversations.Notify +import com.amazon.alexa.ask.conversations.Request +import com.amazon.alexa.ask.conversations.RequestArguments +import com.amazon.alexa.ask.conversations.ensure +import com.amazon.alexa.ask.conversations.expect +import com.amazon.alexa.ask.conversations.response +import com.amazon.alexa.schema.Nothing +import com.amazon.alexa.schema.Thing +import com.weatherbot.apis.OrderTwoToppingPizza +import com.weatherbot.types.PAYLOAD_TYPE6 +import com.weatherbot.types.PAYLOAD_TYPE7 +import com.weatherbot.types.PAYLOAD_TYPE88 +import com.weatherbot.types.PAYLOAD_TYPE9 +import com.weatherbot.utteracesets.Yes +import com.weatherbot.utteracesets.specifyCrust +import com.weatherbot.utteracesets.specifySize +import com.weatherbot.utteracesets.specifyTwoToppings +import com.weatherbot.utteracesets.startTwoToppingPizzaOrder +import prompts.askForCrustPrompts +import prompts.askForSizePrompts +import prompts.askForToppingOnePrompt +import prompts.askForToppingTwoPrompt +import prompts.askForTwoToppingsPrompts +import prompts.confirmSizePrompt +import prompts.confirmTwoToppingOrderPromptcopy +import prompts.confirmTwoToppingsPrompt +import prompts.twoToppingOrderSuccessPrompt +import slotTypes.* +import prompts.* +import displays.* +import com.weatherbot.utteracesets.* +import com.amazon.alexa.ask.conversations.* +import com.amazon.alexa.schema.* +import com.weatherbot.types.* +dialog Nothing orderTwoToppingPizza() { + sample { + expect( + act = Invoke, + event = startTwoToppingPizzaOrder + ) + ensure( + requestArgs = [ + RequestArguments { + arguments = [ + OrderTwoToppingPizza.arguments.first_topping + ], + response = MultiModalResponse { + apla = askForToppingOnePrompt + } + } + ] + ) + ensure( + requestArgs = [ + RequestArguments { + arguments = [ + OrderTwoToppingPizza.arguments.second_topping + ], + response = MultiModalResponse { + apla = askForToppingTwoPrompt + } + } + ] + ) + response( + act = Request { + arguments = [ + OrderTwoToppingPizza.arguments.size + ] + }, + response = MultiModalResponse { + apla = askForSizePrompts + } + ) + specifySizeRequest = expect( + act = Inform, + event = specifySize + ) + response( + act = ConfirmArgs { + arguments = [ + OrderTwoToppingPizza.arguments.size + ] + }, + payload = PAYLOAD_TYPE6 { + size = specifySizeRequest.size + }, + response = MultiModalResponse { + apla = confirmSizePrompt + } + ) + expect( + act = Affirm, + event = Yes + ) + response( + act = Request { + arguments = [ + OrderTwoToppingPizza.arguments.crust + ] + }, + response = MultiModalResponse { + apla = askForCrustPrompts + } + ) + specifyCrustRequest = expect( + act = Inform, + event = specifyCrust + ) + response( + act = Request { + arguments = [ + OrderTwoToppingPizza.arguments.first_topping, + OrderTwoToppingPizza.arguments.second_topping + ] + }, + response = MultiModalResponse { + apla = askForTwoToppingsPrompts + } + ) + specifyTwoToppingsRequest = expect( + act = Inform, + event = specifyTwoToppings + ) + response( + act = ConfirmArgs { + arguments = [ + OrderTwoToppingPizza.arguments.first_topping, + OrderTwoToppingPizza.arguments.second_topping + ] + }, + payload = PAYLOAD_TYPE7 { + second_topping = specifyTwoToppingsRequest.second_topping, + first_topping = specifyTwoToppingsRequest.first_topping + }, + response = MultiModalResponse { + apla = confirmTwoToppingsPrompt + } + ) + expect( + act = Affirm, + event = Yes + ) + response( + act = ConfirmAction { + actionName = OrderTwoToppingPizza + }, + payload = PAYLOAD_TYPE88 { + size = specifySizeRequest.size, + second_topping = specifyTwoToppingsRequest.second_topping, + first_topping = specifyTwoToppingsRequest.first_topping, + crust = specifyCrustRequest.crust + }, + response = MultiModalResponse { + apla = confirmTwoToppingOrderPromptcopy + } + ) + expect( + act = Affirm, + event = Yes + ) + stringLiteral1 = OrderTwoToppingPizza( + size = specifySizeRequest.size, + second_topping = specifyTwoToppingsRequest.second_topping, + first_topping = specifyTwoToppingsRequest.first_topping, + crust = specifyCrustRequest.crust + ) + response( + act = Notify { + success = true, + actionName = OrderTwoToppingPizza + }, + payload = PAYLOAD_TYPE9 { + speech = stringLiteral1 + }, + response = MultiModalResponse { + apla = twoToppingOrderSuccessPrompt + } + ) + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/conversations/soaDialog.acdl b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/conversations/soaDialog.acdl new file mode 100644 index 00000000..a09e5124 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/conversations/soaDialog.acdl @@ -0,0 +1,50 @@ +namespace soaACDl + +import com.amazon.alexa.ask.conversations.Affirm +import com.amazon.alexa.ask.conversations.ConfirmArgs +import com.amazon.alexa.ask.conversations.Inform +import com.amazon.alexa.ask.conversations.Invoke +import com.amazon.alexa.ask.conversations.Notify +import com.amazon.alexa.ask.conversations.Request +import com.amazon.alexa.ask.conversations.expect +import com.amazon.alexa.ask.conversations.response +import com.amazon.alexa.schema.Nothing +import com.amazon.ask.types.builtins.AMAZON.Color +import com.weatherbot.apis.colorFruitName +import com.weatherbot.apis.fruitNameAPI +import com.weatherbot.types.result +import com.weatherbot.utteracesets.MultipleDialogEvent +import com.weatherbot.utteracesets.affirmMultipleColorEvent +import com.weatherbot.utteracesets.informColorMultipleEvent +import prompts.confirm_color_for_fruit_apla +import prompts.request_colorName_multiple_apla +import prompts.success_fruitPriceAPI_apla +import slotTypes.* +import prompts.* +import displays.* +import com.weatherbot.utteracesets.* +import com.amazon.alexa.ask.conversations.* +import com.amazon.alexa.schema.* +import com.weatherbot.types.* + +type payloadMultipleDialogEvent { + result result +} + +type payloadsOAConfirmArgs { + Color colorName +} + +dialog Nothing sOA() { + sample { + // "i want to buy a fruit" + expect(act = Invoke,event = MultipleDialogEvent) + response(response = request_colorName_multiple_apla,act = Request { arguments = [ colorFruitName.arguments.colorName ]}) + colorEvent = expect(act = Inform,event = informColorMultipleEvent) + response(response = confirm_color_for_fruit_apla,act = ConfirmArgs { arguments = [ colorFruitName.arguments.colorName ]},payload = payloadsOAConfirmArgs { colorName = colorEvent.colorName}) + expect(act = Affirm,event = affirmMultipleColorEvent) + resultEvent = colorFruitName(colorName = colorEvent.colorName) + resultOne = fruitNameAPI(fruitName = resultEvent.fruitName) + response(response = success_fruitPriceAPI_apla,act = Notify { actionName = fruitNameAPI},payload = payloadMultipleDialogEvent { result = resultOne}) + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/conversations/types.acdl b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/conversations/types.acdl new file mode 100644 index 00000000..057115d1 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/conversations/types.acdl @@ -0,0 +1,248 @@ +namespace com.weatherbot.types + +import com.amazon.alexa.schema.List +import com.amazon.ask.types.builtins.AMAZON.Color +import com.amazon.ask.types.builtins.AMAZON.DATE +import com.amazon.ask.types.builtins.AMAZON.Food +import com.amazon.ask.types.builtins.AMAZON.NUMBER +import slotTypes.Mix +import slotTypes.StringLiteral +import slotTypes.cheese +import slotTypes.city_name_one +import slotTypes.city_name_two +import slotTypes.complexNames +import slotTypes.crust +import slotTypes.customCity +import slotTypes.option +import slotTypes.orderStatus +import slotTypes.pickUpFrom +import slotTypes.signs +import slotTypes.size +import slotTypes.specialPizzaName +import slotTypes.toppings + +type customCityShell { + customCity cityName +} + +type signShell { + signs sign +} + +type dateValue { + DATE date +} + +type WeatherResult { + customCity cityName + NUMBER highTemp + NUMBER lowTemp + optional List itemsToUse +} + +type resultthree { + Food fruitName + Color colorName +} + +type result { + Food fruitName + NUMBER price +} + +type fruitNameShell { + Food fruitName +} + +type foodNameShell { + Food foodName +} + +type CityDateShell { + optional customCity cityName + optional DATE date +} + +type nameShell { + complexNames name +} + +type colorNameShell { + Color colorName +} + +type result_one { + Color colorName + complexNames name + signs sign +} + +type sourceShell { + city_name_one source +} + +type destinationShell { + city_name_two destination +} + +type pickUpFromShell { + pickUpFrom pickUpFrom +} + +type dropToShell { + city_name_one dropTo +} + +type bookedFlightResult { + city_name_two destination + city_name_one source + orderStatus orderStatus +} + +type bookCabResult { + pickUpFrom pickUpFrom + city_name_one dropTo + orderStatus orderStatus +} + +type ResponsePayload { + WeatherResult weatherResult +} + +type payloadConfirmActionConditionComplex { + optional complexNames name + optional signs sign +} + +type Response_Payload_one { + optional customCity cityName + optional DATE date +} + +type inform_menu_optionRequestType { + option option +} + +type specifySpecialNameRequestType { + specialPizzaName name +} + +type askMenuQuestionRequestType { + option option +} + +type specifySizeAndToppingsRequestType { + size size + List toppings +} + +type orderSpecificSizePizzaRequestType { + size size +} + +type specifyQtyRequestType { + NUMBER qty +} + +type customizePizzaReferenceSpecialRequestType { + specialPizzaName name +} + +type specifyTwoToppingsRequestType { + toppings second_topping + toppings first_topping +} + +type inquireAboutFeedingSizeRequestType { + size size +} + +type specifyToppingsRequestType { + List toppingsList +} + +type specifySizeRequestType { + size size +} + +type specifyCrustRequestType { + crust crust +} + +type specifyCheeseRequestType { + cheese cheese +} + +type pizza { + size size + List toppingsList + crust crust + cheese cheese +} + +type special { + pizza pizza + NUMBER cost + NUMBER qty + specialPizzaName name +} + +type PAYLOAD_TYPE0 { + size size + StringLiteral prompt +} + +type PAYLOAD_TYPE1 { + size size + List toppingsList + crust crust + cheese cheese +} + +type PAYLOAD_TYPE2 { + pizza pizza +} + +type PAYLOAD_TYPE3 { + size size + List toppingsList + crust crust + cheese cheese +} + +type PAYLOAD_TYPE4 { + pizza pizza +} + +type PAYLOAD_TYPE5 { + size size + StringLiteral prompt +} + +type PAYLOAD_TYPE6 { + size size +} + +type PAYLOAD_TYPE7 { + toppings second_topping + toppings first_topping +} + +type PAYLOAD_TYPE88 { + toppings second_topping + toppings first_topping + crust crust + optional size size +} + +type PAYLOAD_TYPE9 { + StringLiteral speech +} + +type PAYLOAD_TYPE10 { + StringLiteral optionResponse +} + +type PAYLOAD_TYPE11 { + StringLiteral optionResponse +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/conversations/utteracesets.acdl b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/conversations/utteracesets.acdl new file mode 100644 index 00000000..db46e06f --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/conversations/utteracesets.acdl @@ -0,0 +1,435 @@ +namespace com.weatherbot.utteracesets + +import com.amazon.alexa.ask.conversations.utterances +import com.weatherbot.types.CityDateShell +import com.weatherbot.types.askMenuQuestionRequestType +import com.weatherbot.types.colorNameShell +import com.weatherbot.types.customCityShell +import com.weatherbot.types.customizePizzaReferenceSpecialRequestType +import com.weatherbot.types.dateValue +import com.weatherbot.types.destinationShell +import com.weatherbot.types.dropToShell +import com.weatherbot.types.foodNameShell +import com.weatherbot.types.fruitNameShell +import com.weatherbot.types.inform_menu_optionRequestType +import com.weatherbot.types.inquireAboutFeedingSizeRequestType +import com.weatherbot.types.nameShell +import com.weatherbot.types.orderSpecificSizePizzaRequestType +import com.weatherbot.types.pickUpFromShell +import com.weatherbot.types.signShell +import com.weatherbot.types.sourceShell +import com.weatherbot.types.specifyCheeseRequestType +import com.weatherbot.types.specifyCrustRequestType +import com.weatherbot.types.specifyQtyRequestType +import com.weatherbot.types.specifySizeAndToppingsRequestType +import com.weatherbot.types.specifySizeRequestType +import com.weatherbot.types.specifySpecialNameRequestType +import com.weatherbot.types.specifyToppingsRequestType +import com.weatherbot.types.specifyTwoToppingsRequestType + +values = [ + "what is the weather", + "what's the weather", + "tell me the weather" +] + +getWeatherEventNoArgs = utterances( + samples = values +) + +getWeatherEventArgs = utterances( + samples = [ + "tell me the weather in {cityName} {date}", + "how is the weather in {cityName} {date}" + ] +) + +getWeatherEvent = utterances( + samples = [ + "What's the weather {date} in {cityName}", + "what is the weather {date}", + "How is the weather {date}", + "How is weather in {cityName} {date}", + "how is weather", + "can you please give me weather report for {date}" + ] +) + +informCityEvent = utterances( + samples = [ + "{cityName}", + "city is {cityName}", + "city name is {cityName}" + ] +) + +informDateEvent = utterances( + samples = [ + "date is {date}", + "for {date}", + "{date}" + ] +) + +affirmWeatherEvent = utterances( + samples = [ + "yes", + "yeah" + ] +) + +delegateToSkill = utterances( + samples = [ + "get me to paradise", + "take me to paradise" + ] +) + +cookWithTwoIngredientsEvent = utterances( + samples = [ + "let us cook", + "start cooking", + "cook with two ingredients", + "cook two ingredients", + "switch to coltrane", + "hit coltrane", + "make coltrane DM" + ] +) + +welcome = utterances( + samples = [ + "get me car" + ] +) + +affirmMultipleColorEvent = utterances( + samples = [ + "do it" + ] +) + +informfruitNameEvent = utterances( + samples = [ + "{fruitName}", + "fruit name is {fruitName}", + "fruit is {fruitName}" + ] +) + +MultipleDialogEvent = utterances( + samples = [ + "i want to buy a fruit" + ] +) + +informColorMultipleEvent = utterances( + samples = [ + "{colorName}", + "color is {colorName}", + "color {colorName}" + ] +) + +informFoodNameEvent = utterances( + samples = [ + "{foodName}", + "food is {foodName}", + "let us make {foodName}" + ] +) + +affirmFruitAPIEvent = utterances( + samples = [ + "uh huh", + "yup" + ] +) + +affirmCookAPIEvent = utterances( + samples = [ + "ok", + "that is ok", + "ok for sure" + ] +) + +GiveMeTodaySpecialsEvent = utterances( + samples = [ + "give me today specials", + "what is special today" + ] +) + +getFruitPriceEvent = utterances( + samples = [ + "what is the price of the fruit", + "what is the price of fruit" + ] +) + + + +informsignEvent = utterances( + samples = [ + "{sign}", + "sign is {sign}", + "sun sign is {sign}" + ] +) + +informComplexNameEvent = utterances( + samples = [ + "{name}", + "name is {name}", + "i am {name}" + ] +) + +affirmFavColorEvent = utterances( + samples = [ + "correct" + ] +) + +bookFlightEvent = utterances( + samples = [ + "book a flight", + "book flight" + ] +) + +informFromBookFlight = utterances( + samples = [ + "from {source}", + "travel from {source}", + "source is {source}" + ] +) + +informToBookFlight = utterances( + samples = [ + "to {destination}", + "trave to {destination}", + "go to {destination}", + "destination to {destination}" + ] +) + +affirmCabAPIEvent = utterances( + samples = [ + "sure do", + "sure please do", + "roger", + "indeed" + ] +) + +informPickUpFromBookCab = utterances( + samples = [ + "{pickUpFrom}" + ] +) + +informdropToBookCab = utterances( + samples = [ + "{dropTo}" + ] +) + +inform_menu_option = utterances( + samples = [ + "{option}" + ] +) + +menuOptionsQuestion = utterances( + samples = [ + "what options can I change?", + "what kinds of options are there?" + ] +) + +inquireAboutFeedingSizeNoArgs = utterances( + samples = [ + "how many people does that feed", + "Is that enough for two adults and two kids" + ] +) + +specifySpecialName = utterances( + samples = [ + "{name}" + ] +) + +askMenuQuestion = utterances( + samples = [ + "what are your {option}", + "what {option} can i get", + "what types of {option} do you have", + "What kind of {option} do you have" + ] +) + +specifySizeAndToppings = utterances( + samples = [ + "add a {size} {toppings} pizza to my order", + "order a {size} {toppings} pizza", + "I want a {size} {toppings} pizza" + ] +) + +orderSpecificSizePizza = utterances( + samples = [ + "order a {size} pizza", + "I want a {size} pizza" + ] +) + +DummyInvokeOrderCustomizedPizzaReferenceSpecial = utterances( + samples = [ + "dummy invoke needed when offer API is used in NotifySuccess request template + OfferAPI for OrderCustomizedPizzaReferenceSpecial" + ] +) + +startCustomizeFlow = utterances( + samples = [ + "I want to customize a special" + ] +) + +confirmCustomizedSpecial = utterances( + samples = [ + "sounds good", + "perfect", + "go ahead", + "sure", + "yeah", + "ok", + "yep" + ] +) + +specifyQty = utterances( + samples = [ + "{qty} please", + "{qty}", + "give me {qty}", + "I will take {qty}", + "I want {qty}" + ] +) + +customizePizzaReferenceSpecial = utterances( + samples = [ + "let's customize the {name}", + "I want to customize the {name}" + ] +) + +specifyTwoToppings = utterances( + samples = [ + "no, make it {first_topping} and {second_topping}", + "no, {first_topping} and {second_topping}", + "actually make that {first_topping} and {second_topping}", + "change that to {first_topping} and {second_topping}", + "{first_topping} and {second_topping}", + "add {first_topping} and {second_topping}", + "I want {first_topping} and {second_topping}" + ] +) + +Yes = utterances( + samples = [ + "Correct", + "Uh huh", + "Right", + "Yep", + "Yes" + ] +) + +inquireAboutFeedingSize = utterances( + samples = [ + "is a {size} enough for four adults", + "how many people can a {size} feed", + "how many people can {size} pizza feed?" + ] +) + +tested = utterances( + samples = [ + "launch skill" + ] +) + +startTwoToppingPizzaOrder = utterances( + samples = [ + "order a two topping pizza", + "I want a two topping pizza" + ] +) + +specifyToppings = utterances( + samples = [ + "{toppingsList}", + "I'd like {toppingsList}", + "give me {toppingsList}", + "we like {toppingsList}", + "The kids want {toppingsList}" + ] +) + +startPizzaOrder = utterances( + samples = [ + "build my own pizza", + "I need my own custom pizza", + "Add one more order", + "I want another pizza", + "build another pizza", + "create another pizza", + "build a pizza", + "place an order for a pizza", + "add another pizza to my order", + "add another custom pizza to my order", + "create a custom pizza", + "start my pizza order", + "order me a custom pizza", + "order a pizza" + ] +) + +specifySize = utterances( + samples = [ + "change it to {size}", + "make that a {size}", + "change that to a {size} pizza", + "{size}", + "I need a {size} pizza" + ] +) + +specifyCrust = utterances( + samples = [ + "{crust}", + "I need {crust}" + ] +) + +specifyCheese = utterances( + samples = [ + "{cheese}", + "I need {cheese}", + "Please add {cheese}" + ] +) + +confirmPizzaOrder = utterances( + samples = [ + "yes", + "yup", + "go ahead", + "perfect" + ] +) diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/conversations/welcomeAPI.acdl b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/conversations/welcomeAPI.acdl new file mode 100644 index 00000000..26b5fc36 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/conversations/welcomeAPI.acdl @@ -0,0 +1,38 @@ +namespace welcomeAPi + +import com.amazon.alexa.ask.conversations.Invoke +import com.amazon.alexa.ask.conversations.Notify +import com.amazon.alexa.ask.conversations.expect +import com.amazon.alexa.ask.conversations.response +import com.amazon.alexa.schema.Nothing +import com.amazon.ask.types.builtins.AMAZON.NUMBER +import com.weatherbot.apis.welcomeApi +import com.weatherbot.utteracesets.welcome +import prompts.welcome_apla_custom +import slotTypes.* +import prompts.* +import displays.* +import com.weatherbot.utteracesets.* +import com.amazon.alexa.ask.conversations.* +import com.amazon.alexa.schema.* +import com.weatherbot.types.* + +type welcomeApiPayloads { + NUMBER result +} + +dialog Nothing complex() { + sample { + expect( + act = Invoke, + event = com.weatherbot.utteracesets.welcome + ) + resultDam = welcomeApi() + response( + response = welcome_apla_custom, + act = Notify { + actionName = welcomeApi + } + ) + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/interactionModels/custom/en-US.json b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/interactionModels/custom/en-US.json new file mode 100644 index 00000000..91c60c47 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/interactionModels/custom/en-US.json @@ -0,0 +1,527 @@ +{ + "interactionModel": { + "languageModel": { + "invocationName": "serious master test skill", + "intents": [ + { + "name": "AMAZON.CancelIntent", + "samples": [] + }, + { + "name": "AMAZON.HelpIntent", + "samples": [] + }, + { + "name": "AMAZON.StopIntent", + "samples": [] + }, + { + "name": "NoDialog", + "samples": ["show me the wonders"] + }, + { + "name": "test", + "samples": ["nanum rowdy dhann"] + }, + { + "name": "SkillToColtrane", + "samples": ["switch to coltrane", "hit coltrane", "make coltrane DM"] + }, + { + "name": "AMAZON.NavigateHomeIntent", + "samples": [] + }, + { + "name": "AMAZON.FallbackIntent", + "samples": [] + } + ], + "types": [ + { + "values": [ + { + "name": { + "value": "satheesh" + } + }, + { + "name": { + "value": "raman" + } + } + ], + "name": "request_city_apl_displaya" + }, + { + "values": [ + { + "name": { + "value": "satheesh" + } + }, + { + "name": { + "value": "raman" + } + } + ], + "name": "complexNames" + }, + { + "values": [ + { + "name": { + "value": "scorpion" + } + }, + { + "name": { + "value": "aeries" + } + }, + { + "name": { + "value": "virgo" + } + }, + { + "name": { + "value": "cancer" + } + } + ], + "name": "signs" + }, + { + "values": [ + { + "name": { + "value": "almonds" + } + }, + { + "name": { + "value": "bread" + } + }, + { + "name": { + "value": "egg" + } + }, + { + "name": { + "value": "sauce" + } + }, + { + "name": { + "value": "jam" + } + }, + { + "name": { + "value": "cheese" + } + } + ], + "name": "Mix" + }, + { + "values": [ + { + "name": { + "value": "small" + } + }, + { + "name": { + "value": "medium" + } + }, + { + "name": { + "value": "large" + } + }, + { + "name": { + "value": "extra large" + } + } + ], + "name": "size" + }, + { + "values": [ + { + "name": { + "value": "guindy" + } + }, + { + "name": { + "value": "paris" + } + }, + { + "name": { + "value": "anna nagar" + } + }, + { + "name": { + "value": "ramapuram" + } + } + ], + "name": "pickUpFrom" + }, + { + "values": [ + { + "name": { + "value": "dummy value for api response literal property" + } + } + ], + "name": "StringLiteral" + }, + { + "values": [ + { + "name": { + "value": "deep dish" + } + }, + { + "name": { + "value": "regular" + } + }, + { + "name": { + "value": "hand made" + } + }, + { + "name": { + "value": "gluten free" + } + }, + { + "name": { + "value": "thin crust" + } + }, + { + "name": { + "value": "brooklyn style" + } + } + ], + "name": "crust" + }, + { + "values": [ + { + "name": { + "value": "none", + "synonyms": ["no cheese", "dont add cheese", "nope", "no"] + } + }, + { + "name": { + "value": "light", + "synonyms": ["light cheese"] + } + }, + { + "name": { + "value": "normal", + "synonyms": ["Normal cheese"] + } + }, + { + "name": { + "value": "extra", + "synonyms": ["Extra cheese"] + } + }, + { + "name": { + "value": "double", + "synonyms": ["Double cheese"] + } + } + ], + "name": "cheese" + }, + { + "values": [ + { + "name": { + "value": "cheese", + "synonyms": ["cheeses"] + } + }, + { + "name": { + "value": "crust", + "synonyms": ["crusts"] + } + }, + { + "name": { + "value": "size", + "synonyms": ["sizes"] + } + } + ], + "name": "option" + }, + { + "values": [ + { + "name": { + "value": "two medium, two topping" + } + }, + { + "name": { + "value": "three cheese delight" + } + }, + { + "name": { + "value": "pepperoni party" + } + }, + { + "name": { + "value": "meat lovers" + } + }, + { + "name": { + "value": "veggie supreme" + } + }, + { + "name": { + "value": "kitchen sink" + } + } + ], + "name": "specialPizzaName" + }, + { + "values": [ + { + "name": { + "value": "onion", + "synonyms": ["onions"] + } + }, + { + "name": { + "value": "banana peppers", + "synonyms": ["banana pepper"] + } + }, + { + "name": { + "value": "olives", + "synonyms": ["black olives"] + } + }, + { + "name": { + "value": "mushrooms", + "synonyms": ["mushroom"] + } + }, + { + "name": { + "value": "pineapple" + } + }, + { + "name": { + "value": "spinach", + "synonyms": ["spinach"] + } + } + ], + "name": "toppings" + }, + { + "values": [ + { + "name": { + "value": "failure" + } + }, + { + "name": { + "value": "failed" + } + }, + { + "name": { + "value": "success" + } + } + ], + "name": "orderStatus" + }, + { + "values": [ + { + "name": { + "value": "san diego" + } + }, + { + "name": { + "value": "los angeles" + } + }, + { + "name": { + "value": "denver" + } + }, + { + "name": { + "value": "paris" + } + }, + { + "name": { + "value": "seattle" + } + }, + { + "name": { + "value": "portland" + } + }, + { + "name": { + "value": "ramapuram" + } + }, + { + "name": { + "value": "chennai" + } + } + ], + "name": "city_name_one" + }, + { + "values": [ + { + "name": { + "value": "denver" + } + }, + { + "name": { + "value": "sydney" + } + }, + { + "name": { + "value": "portland" + } + }, + { + "name": { + "value": "new york" + } + }, + { + "name": { + "value": "visakhapatnam" + } + }, + { + "name": { + "value": "bangalore" + } + }, + { + "name": { + "value": "mumbai" + } + }, + { + "name": { + "value": "seattle" + } + }, + { + "name": { + "value": "chennai" + } + } + ], + "name": "customCity" + }, + { + "values": [ + { + "name": { + "value": "denver" + } + }, + { + "name": { + "value": "sydney" + } + }, + { + "name": { + "value": "portland" + } + }, + { + "name": { + "value": "new york" + } + }, + { + "name": { + "value": "visakhapatnam" + } + }, + { + "name": { + "value": "bangalore" + } + }, + { + "name": { + "value": "mumbai" + } + }, + { + "name": { + "value": "seattle" + } + }, + { + "name": { + "value": "chennai" + } + } + ], + "name": "city_name_two" + } + ] + } + }, + "version": "12" +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/display/confirm_city_apl_display/document.json b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/display/confirm_city_apl_display/document.json new file mode 100644 index 00000000..6fea1ff7 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/display/confirm_city_apl_display/document.json @@ -0,0 +1,331 @@ +{ + "type": "APL", + "version": "1.1", + "settings": {}, + "theme": "dark", + "import": [ + { + "name": "alexa-layouts", + "version": "1.0.0" + } + ], + "resources": [ + { + "description": "Stock color for the light theme", + "colors": { + "colorTextPrimary": "#151920" + } + }, + { + "description": "Stock color for the dark theme", + "when": "${viewport.theme == 'dark'}", + "colors": { + "colorTextPrimary": "#f0f1ef" + } + }, + { + "description": "Standard font sizes", + "dimensions": { + "textSizeBody": 48, + "textSizePrimary": 27, + "textSizeSecondary": 23, + "textSizeDetails": 20, + "textSizeSecondaryHint": 25 + } + }, + { + "description": "Common spacing values", + "dimensions": { + "spacingThin": 6, + "spacingSmall": 12, + "spacingMedium": 24, + "spacingLarge": 48, + "spacingExtraLarge": 72 + } + }, + { + "description": "Common margins and padding", + "dimensions": { + "marginTop": 40, + "marginLeft": 60, + "marginRight": 60, + "marginBottom": 40 + } + } + ], + "styles": { + "textStyleBase": { + "description": "Base font description; set color", + "values": [ + { + "color": "@colorTextPrimary" + } + ] + }, + "textStyleBase0": { + "description": "Thin version of basic font", + "extend": "textStyleBase", + "values": { + "fontWeight": "100" + } + }, + "textStyleBase1": { + "description": "Light version of basic font", + "extend": "textStyleBase", + "values": { + "fontWeight": "300" + } + }, + "textStyleBase2": { + "description": "Regular version of basic font", + "extend": "textStyleBase", + "values": { + "fontWeight": "500" + } + }, + "mixinBody": { + "values": { + "fontSize": "@textSizeBody" + } + }, + "mixinPrimary": { + "values": { + "fontSize": "@textSizePrimary" + } + }, + "mixinDetails": { + "values": { + "fontSize": "@textSizeDetails" + } + }, + "mixinSecondary": { + "values": { + "fontSize": "@textSizeSecondary" + } + }, + "textStylePrimary": { + "extend": ["textStyleBase1", "mixinPrimary"] + }, + "textStyleSecondary": { + "extend": ["textStyleBase0", "mixinSecondary"] + }, + "textStyleBody": { + "extend": ["textStyleBase1", "mixinBody"] + }, + "textStyleSecondaryHint": { + "values": { + "fontFamily": "Bookerly", + "fontStyle": "italic", + "fontSize": "@textSizeSecondaryHint", + "color": "@colorTextPrimary" + } + }, + "textStyleDetails": { + "extend": ["textStyleBase2", "mixinDetails"] + } + }, + "onMount": [], + "graphics": {}, + "commands": {}, + "layouts": { + "ListTemplate1": { + "parameters": ["backgroundImage", "title", "logo", "hintText", "listData"], + "item": [ + { + "type": "Container", + "width": "100vw", + "height": "100vh", + "direction": "column", + "items": [ + { + "type": "Image", + "source": "${backgroundImage}", + "scale": "best-fill", + "width": "100vw", + "height": "100vh", + "position": "absolute" + }, + { + "type": "AlexaHeader", + "headerTitle": "${title}", + "headerAttributionImage": "${logo}" + }, + { + "type": "Sequence", + "grow": 1, + "height": "80vh", + "scrollDirection": "vertical", + "paddingLeft": "@marginLeft", + "paddingRight": "@marginRight", + "data": "${listData}", + "numbered": true, + "items": [ + { + "type": "VerticalListItem", + "image": "${data.image.sources[0].url}", + "primaryText": "${data.textContent.primaryText.text}", + "secondaryText": "${data.textContent.secondaryText.text}", + "tertiaryText": "${data.textContent.tertiaryText.text}" + } + ] + } + ] + } + ] + }, + "VerticalListItem": { + "parameters": ["primaryText", "secondaryText", "tertiaryText", "image"], + "item": [ + { + "when": "${viewport.shape == 'round'}", + "type": "Container", + "direction": "row", + "height": 200, + "width": 500, + "alignItems": "center", + "items": [ + { + "type": "Text", + "text": "${ordinal}", + "paddingBottom": "20dp", + "color": "white", + "spacing": "5dp" + }, + { + "type": "Image", + "when": "${image}", + "source": "${image}", + "height": 150, + "width": 150, + "spacing": 15, + "scale": "best-fit", + "align": "top" + }, + { + "type": "Container", + "direction": "column", + "spacing": 25, + "items": [ + { + "type": "Text", + "text": "${primaryText}", + "style": "textStyleDetail", + "grow": 1, + "shrink": 1, + "fontWeight": "300", + "maxLines": 1 + }, + { + "type": "Text", + "text": "${secondaryText}", + "style": "textStyleCaption", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + }, + { + "type": "Text", + "text": "${tertiaryText}", + "style": "textStyleDetails", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + } + ] + } + ] + }, + { + "type": "Container", + "direction": "row", + "height": 125, + "width": 800, + "alignItems": "center", + "items": [ + { + "type": "Text", + "text": "${ordinal}", + "paddingBottom": "20dp", + "color": "white", + "spacing": "5dp" + }, + { + "type": "Image", + "when": "${image}", + "source": "${image}", + "height": 100, + "width": 100, + "align": "top", + "spacing": 50, + "scale": "best-fit" + }, + { + "type": "Container", + "spacing": 30, + "direction": "column", + "items": [ + { + "type": "Text", + "text": "${primaryText}", + "style": "textStyleBody", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + }, + { + "type": "Text", + "text": "${secondaryText}", + "style": "textStyleDetails", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + } + ] + }, + { + "type": "Text", + "text": "${tertiaryText}", + "style": "textStyleBody", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "textAlign": "right", + "maxLines": 1 + } + ] + } + ] + } + }, + "mainTemplate": { + "parameters": ["payload"], + "item": [ + { + "type": "Container", + "id": "BookCabSimpleDialogAPL", + "items": [ + { + "type": "TouchWrapper", + "onPress": { + "type": "SendEvent", + "arguments": ["delegateToColtraneOld"] + }, + "item": { + "type": "Text", + "id": "BookCabSimpleDialogAPL", + "paddingTop": "100", + "paddingLeft": "100", + "color": "green", + "size": 50, + "text": "which city ?" + } + } + ] + } + ] + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/display/confirm_date_apl_display/document.json b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/display/confirm_date_apl_display/document.json new file mode 100644 index 00000000..d41ea236 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/display/confirm_date_apl_display/document.json @@ -0,0 +1,331 @@ +{ + "type": "APL", + "version": "1.1", + "settings": {}, + "theme": "dark", + "import": [ + { + "name": "alexa-layouts", + "version": "1.0.0" + } + ], + "resources": [ + { + "description": "Stock color for the light theme", + "colors": { + "colorTextPrimary": "#151920" + } + }, + { + "description": "Stock color for the dark theme", + "when": "${viewport.theme == 'dark'}", + "colors": { + "colorTextPrimary": "#f0f1ef" + } + }, + { + "description": "Standard font sizes", + "dimensions": { + "textSizeBody": 48, + "textSizePrimary": 27, + "textSizeSecondary": 23, + "textSizeDetails": 20, + "textSizeSecondaryHint": 25 + } + }, + { + "description": "Common spacing values", + "dimensions": { + "spacingThin": 6, + "spacingSmall": 12, + "spacingMedium": 24, + "spacingLarge": 48, + "spacingExtraLarge": 72 + } + }, + { + "description": "Common margins and padding", + "dimensions": { + "marginTop": 40, + "marginLeft": 60, + "marginRight": 60, + "marginBottom": 40 + } + } + ], + "styles": { + "textStyleBase": { + "description": "Base font description; set color", + "values": [ + { + "color": "@colorTextPrimary" + } + ] + }, + "textStyleBase0": { + "description": "Thin version of basic font", + "extend": "textStyleBase", + "values": { + "fontWeight": "100" + } + }, + "textStyleBase1": { + "description": "Light version of basic font", + "extend": "textStyleBase", + "values": { + "fontWeight": "300" + } + }, + "textStyleBase2": { + "description": "Regular version of basic font", + "extend": "textStyleBase", + "values": { + "fontWeight": "500" + } + }, + "mixinBody": { + "values": { + "fontSize": "@textSizeBody" + } + }, + "mixinPrimary": { + "values": { + "fontSize": "@textSizePrimary" + } + }, + "mixinDetails": { + "values": { + "fontSize": "@textSizeDetails" + } + }, + "mixinSecondary": { + "values": { + "fontSize": "@textSizeSecondary" + } + }, + "textStylePrimary": { + "extend": ["textStyleBase1", "mixinPrimary"] + }, + "textStyleSecondary": { + "extend": ["textStyleBase0", "mixinSecondary"] + }, + "textStyleBody": { + "extend": ["textStyleBase1", "mixinBody"] + }, + "textStyleSecondaryHint": { + "values": { + "fontFamily": "Bookerly", + "fontStyle": "italic", + "fontSize": "@textSizeSecondaryHint", + "color": "@colorTextPrimary" + } + }, + "textStyleDetails": { + "extend": ["textStyleBase2", "mixinDetails"] + } + }, + "onMount": [], + "graphics": {}, + "commands": {}, + "layouts": { + "ListTemplate1": { + "parameters": ["backgroundImage", "title", "logo", "hintText", "listData"], + "item": [ + { + "type": "Container", + "width": "100vw", + "height": "100vh", + "direction": "column", + "items": [ + { + "type": "Image", + "source": "${backgroundImage}", + "scale": "best-fill", + "width": "100vw", + "height": "100vh", + "position": "absolute" + }, + { + "type": "AlexaHeader", + "headerTitle": "${title}", + "headerAttributionImage": "${logo}" + }, + { + "type": "Sequence", + "grow": 1, + "height": "80vh", + "scrollDirection": "vertical", + "paddingLeft": "@marginLeft", + "paddingRight": "@marginRight", + "data": "${listData}", + "numbered": true, + "items": [ + { + "type": "VerticalListItem", + "image": "${data.image.sources[0].url}", + "primaryText": "${data.textContent.primaryText.text}", + "secondaryText": "${data.textContent.secondaryText.text}", + "tertiaryText": "${data.textContent.tertiaryText.text}" + } + ] + } + ] + } + ] + }, + "VerticalListItem": { + "parameters": ["primaryText", "secondaryText", "tertiaryText", "image"], + "item": [ + { + "when": "${viewport.shape == 'round'}", + "type": "Container", + "direction": "row", + "height": 200, + "width": 500, + "alignItems": "center", + "items": [ + { + "type": "Text", + "text": "${ordinal}", + "paddingBottom": "20dp", + "color": "white", + "spacing": "5dp" + }, + { + "type": "Image", + "when": "${image}", + "source": "${image}", + "height": 150, + "width": 150, + "spacing": 15, + "scale": "best-fit", + "align": "top" + }, + { + "type": "Container", + "direction": "column", + "spacing": 25, + "items": [ + { + "type": "Text", + "text": "${primaryText}", + "style": "textStyleDetail", + "grow": 1, + "shrink": 1, + "fontWeight": "300", + "maxLines": 1 + }, + { + "type": "Text", + "text": "${secondaryText}", + "style": "textStyleCaption", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + }, + { + "type": "Text", + "text": "${tertiaryText}", + "style": "textStyleDetails", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + } + ] + } + ] + }, + { + "type": "Container", + "direction": "row", + "height": 125, + "width": 800, + "alignItems": "center", + "items": [ + { + "type": "Text", + "text": "${ordinal}", + "paddingBottom": "20dp", + "color": "white", + "spacing": "5dp" + }, + { + "type": "Image", + "when": "${image}", + "source": "${image}", + "height": 100, + "width": 100, + "align": "top", + "spacing": 50, + "scale": "best-fit" + }, + { + "type": "Container", + "spacing": 30, + "direction": "column", + "items": [ + { + "type": "Text", + "text": "${primaryText}", + "style": "textStyleBody", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + }, + { + "type": "Text", + "text": "${secondaryText}", + "style": "textStyleDetails", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + } + ] + }, + { + "type": "Text", + "text": "${tertiaryText}", + "style": "textStyleBody", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "textAlign": "right", + "maxLines": 1 + } + ] + } + ] + } + }, + "mainTemplate": { + "parameters": ["payload"], + "item": [ + { + "type": "Container", + "id": "BookCabSimpleDialogAPL", + "items": [ + { + "type": "TouchWrapper", + "onPress": { + "type": "SendEvent", + "arguments": ["delegateToColtraneOld"] + }, + "item": { + "type": "Text", + "id": "BookCabSimpleDialogAPL", + "paddingTop": "100", + "paddingLeft": "100", + "color": "green", + "size": 50, + "text": "which date ?" + } + } + ] + } + ] + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/display/confirm_weather_apla_display/document.json b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/display/confirm_weather_apla_display/document.json new file mode 100644 index 00000000..3bcc0e4a --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/display/confirm_weather_apla_display/document.json @@ -0,0 +1,379 @@ +{ + "type": "APL", + "version": "1.1", + "settings": {}, + "theme": "dark", + "import": [ + { + "name": "alexa-layouts", + "version": "1.0.0" + } + ], + "resources": [ + { + "description": "Stock color for the light theme", + "colors": { + "colorTextPrimary": "#151920" + } + }, + { + "description": "Stock color for the dark theme", + "when": "${viewport.theme == 'dark'}", + "colors": { + "colorTextPrimary": "#f0f1ef" + } + }, + { + "description": "Standard font sizes", + "dimensions": { + "textSizeBody": 48, + "textSizePrimary": 27, + "textSizeSecondary": 23, + "textSizeDetails": 20, + "textSizeSecondaryHint": 25 + } + }, + { + "description": "Common spacing values", + "dimensions": { + "spacingThin": 6, + "spacingSmall": 12, + "spacingMedium": 24, + "spacingLarge": 48, + "spacingExtraLarge": 72 + } + }, + { + "description": "Common margins and padding", + "dimensions": { + "marginTop": 40, + "marginLeft": 60, + "marginRight": 60, + "marginBottom": 40 + } + } + ], + "styles": { + "textStyleBase": { + "description": "Base font description; set color", + "values": [ + { + "color": "@colorTextPrimary" + } + ] + }, + "textStyleBase0": { + "description": "Thin version of basic font", + "extend": "textStyleBase", + "values": { + "fontWeight": "100" + } + }, + "textStyleBase1": { + "description": "Light version of basic font", + "extend": "textStyleBase", + "values": { + "fontWeight": "300" + } + }, + "textStyleBase2": { + "description": "Regular version of basic font", + "extend": "textStyleBase", + "values": { + "fontWeight": "500" + } + }, + "mixinBody": { + "values": { + "fontSize": "@textSizeBody" + } + }, + "mixinPrimary": { + "values": { + "fontSize": "@textSizePrimary" + } + }, + "mixinDetails": { + "values": { + "fontSize": "@textSizeDetails" + } + }, + "mixinSecondary": { + "values": { + "fontSize": "@textSizeSecondary" + } + }, + "textStylePrimary": { + "extend": ["textStyleBase1", "mixinPrimary"] + }, + "textStyleSecondary": { + "extend": ["textStyleBase0", "mixinSecondary"] + }, + "textStyleBody": { + "extend": ["textStyleBase1", "mixinBody"] + }, + "textStyleSecondaryHint": { + "values": { + "fontFamily": "Bookerly", + "fontStyle": "italic", + "fontSize": "@textSizeSecondaryHint", + "color": "@colorTextPrimary" + } + }, + "textStyleDetails": { + "extend": ["textStyleBase2", "mixinDetails"] + } + }, + "onMount": [], + "graphics": {}, + "commands": {}, + "layouts": { + "ListTemplate1": { + "parameters": ["backgroundImage", "title", "logo", "hintText", "listData"], + "item": [ + { + "type": "Container", + "width": "100vw", + "height": "100vh", + "direction": "column", + "items": [ + { + "type": "Image", + "source": "${backgroundImage}", + "scale": "best-fill", + "width": "100vw", + "height": "100vh", + "position": "absolute" + }, + { + "type": "AlexaHeader", + "headerTitle": "${title}", + "headerAttributionImage": "${logo}" + }, + { + "type": "Sequence", + "grow": 1, + "height": "80vh", + "scrollDirection": "vertical", + "paddingLeft": "@marginLeft", + "paddingRight": "@marginRight", + "data": "${listData}", + "numbered": true, + "items": [ + { + "type": "VerticalListItem", + "image": "${data.image.sources[0].url}", + "primaryText": "${data.textContent.primaryText.text}", + "secondaryText": "${data.textContent.secondaryText.text}", + "tertiaryText": "${data.textContent.tertiaryText.text}" + } + ] + } + ] + } + ] + }, + "VerticalListItem": { + "parameters": ["primaryText", "secondaryText", "tertiaryText", "image"], + "item": [ + { + "when": "${viewport.shape == 'round'}", + "type": "Container", + "direction": "row", + "height": 200, + "width": 500, + "alignItems": "center", + "items": [ + { + "type": "Text", + "text": "${ordinal}", + "paddingBottom": "20dp", + "color": "white", + "spacing": "5dp" + }, + { + "type": "Image", + "when": "${image}", + "source": "${image}", + "height": 150, + "width": 150, + "spacing": 15, + "scale": "best-fit", + "align": "top" + }, + { + "type": "Container", + "direction": "column", + "spacing": 25, + "items": [ + { + "type": "Text", + "text": "${primaryText}", + "style": "textStyleDetail", + "grow": 1, + "shrink": 1, + "fontWeight": "300", + "maxLines": 1 + }, + { + "type": "Text", + "text": "${secondaryText}", + "style": "textStyleCaption", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + }, + { + "type": "Text", + "text": "${tertiaryText}", + "style": "textStyleDetails", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + } + ] + } + ] + }, + { + "type": "Container", + "direction": "row", + "height": 125, + "width": 800, + "alignItems": "center", + "items": [ + { + "type": "Text", + "text": "${ordinal}", + "paddingBottom": "20dp", + "color": "white", + "spacing": "5dp" + }, + { + "type": "Image", + "when": "${image}", + "source": "${image}", + "height": 100, + "width": 100, + "align": "top", + "spacing": 50, + "scale": "best-fit" + }, + { + "type": "Container", + "spacing": 30, + "direction": "column", + "items": [ + { + "type": "Text", + "text": "${primaryText}", + "style": "textStyleBody", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + }, + { + "type": "Text", + "text": "${secondaryText}", + "style": "textStyleDetails", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + } + ] + }, + { + "type": "Text", + "text": "${tertiaryText}", + "style": "textStyleBody", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "textAlign": "right", + "maxLines": 1 + } + ] + } + ] + } + }, + "mainTemplate": { + "parameters": ["payload"], + "item": [ + { + "type": "Container", + "id": "BookCabSimpleDialogAPL", + "items": [ + { + "type": "TouchWrapper", + "onPress": { + "type": "SendEvent", + "arguments": ["delegateToSkillNew"] + }, + "item": { + "type": "Text", + "id": "BookCabSimpleDialogAPL", + "paddingTop": "100", + "paddingLeft": "100", + "color": "green", + "size": 50, + "text": "delegateToSkillNew" + } + }, + { + "type": "TouchWrapper", + "onPress": { + "type": "SendEvent", + "arguments": ["delegateToSkillOld"] + }, + "item": { + "type": "Text", + "id": "BookCabSimpleDialogAPL", + "paddingTop": "100", + "paddingLeft": "100", + "color": "green", + "size": 50, + "text": "delegateToSkillOld" + } + }, + { + "type": "TouchWrapper", + "onPress": { + "type": "SendEvent", + "arguments": ["delegateToColtraneNew"] + }, + "item": { + "type": "Text", + "id": "BookCabSimpleDialogAPL", + "paddingTop": "100", + "paddingLeft": "100", + "color": "green", + "size": 50, + "text": "delegateToColtraneNew" + } + }, + { + "type": "TouchWrapper", + "onPress": { + "type": "SendEvent", + "arguments": ["delegateToColtraneOld"] + }, + "item": { + "type": "Text", + "id": "BookCabSimpleDialogAPL", + "paddingTop": "100", + "paddingLeft": "100", + "color": "green", + "size": 50, + "text": "delegateToColtraneOld" + } + } + ] + } + ] + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/display/request_city_apl_display/document.json b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/display/request_city_apl_display/document.json new file mode 100644 index 00000000..6fea1ff7 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/display/request_city_apl_display/document.json @@ -0,0 +1,331 @@ +{ + "type": "APL", + "version": "1.1", + "settings": {}, + "theme": "dark", + "import": [ + { + "name": "alexa-layouts", + "version": "1.0.0" + } + ], + "resources": [ + { + "description": "Stock color for the light theme", + "colors": { + "colorTextPrimary": "#151920" + } + }, + { + "description": "Stock color for the dark theme", + "when": "${viewport.theme == 'dark'}", + "colors": { + "colorTextPrimary": "#f0f1ef" + } + }, + { + "description": "Standard font sizes", + "dimensions": { + "textSizeBody": 48, + "textSizePrimary": 27, + "textSizeSecondary": 23, + "textSizeDetails": 20, + "textSizeSecondaryHint": 25 + } + }, + { + "description": "Common spacing values", + "dimensions": { + "spacingThin": 6, + "spacingSmall": 12, + "spacingMedium": 24, + "spacingLarge": 48, + "spacingExtraLarge": 72 + } + }, + { + "description": "Common margins and padding", + "dimensions": { + "marginTop": 40, + "marginLeft": 60, + "marginRight": 60, + "marginBottom": 40 + } + } + ], + "styles": { + "textStyleBase": { + "description": "Base font description; set color", + "values": [ + { + "color": "@colorTextPrimary" + } + ] + }, + "textStyleBase0": { + "description": "Thin version of basic font", + "extend": "textStyleBase", + "values": { + "fontWeight": "100" + } + }, + "textStyleBase1": { + "description": "Light version of basic font", + "extend": "textStyleBase", + "values": { + "fontWeight": "300" + } + }, + "textStyleBase2": { + "description": "Regular version of basic font", + "extend": "textStyleBase", + "values": { + "fontWeight": "500" + } + }, + "mixinBody": { + "values": { + "fontSize": "@textSizeBody" + } + }, + "mixinPrimary": { + "values": { + "fontSize": "@textSizePrimary" + } + }, + "mixinDetails": { + "values": { + "fontSize": "@textSizeDetails" + } + }, + "mixinSecondary": { + "values": { + "fontSize": "@textSizeSecondary" + } + }, + "textStylePrimary": { + "extend": ["textStyleBase1", "mixinPrimary"] + }, + "textStyleSecondary": { + "extend": ["textStyleBase0", "mixinSecondary"] + }, + "textStyleBody": { + "extend": ["textStyleBase1", "mixinBody"] + }, + "textStyleSecondaryHint": { + "values": { + "fontFamily": "Bookerly", + "fontStyle": "italic", + "fontSize": "@textSizeSecondaryHint", + "color": "@colorTextPrimary" + } + }, + "textStyleDetails": { + "extend": ["textStyleBase2", "mixinDetails"] + } + }, + "onMount": [], + "graphics": {}, + "commands": {}, + "layouts": { + "ListTemplate1": { + "parameters": ["backgroundImage", "title", "logo", "hintText", "listData"], + "item": [ + { + "type": "Container", + "width": "100vw", + "height": "100vh", + "direction": "column", + "items": [ + { + "type": "Image", + "source": "${backgroundImage}", + "scale": "best-fill", + "width": "100vw", + "height": "100vh", + "position": "absolute" + }, + { + "type": "AlexaHeader", + "headerTitle": "${title}", + "headerAttributionImage": "${logo}" + }, + { + "type": "Sequence", + "grow": 1, + "height": "80vh", + "scrollDirection": "vertical", + "paddingLeft": "@marginLeft", + "paddingRight": "@marginRight", + "data": "${listData}", + "numbered": true, + "items": [ + { + "type": "VerticalListItem", + "image": "${data.image.sources[0].url}", + "primaryText": "${data.textContent.primaryText.text}", + "secondaryText": "${data.textContent.secondaryText.text}", + "tertiaryText": "${data.textContent.tertiaryText.text}" + } + ] + } + ] + } + ] + }, + "VerticalListItem": { + "parameters": ["primaryText", "secondaryText", "tertiaryText", "image"], + "item": [ + { + "when": "${viewport.shape == 'round'}", + "type": "Container", + "direction": "row", + "height": 200, + "width": 500, + "alignItems": "center", + "items": [ + { + "type": "Text", + "text": "${ordinal}", + "paddingBottom": "20dp", + "color": "white", + "spacing": "5dp" + }, + { + "type": "Image", + "when": "${image}", + "source": "${image}", + "height": 150, + "width": 150, + "spacing": 15, + "scale": "best-fit", + "align": "top" + }, + { + "type": "Container", + "direction": "column", + "spacing": 25, + "items": [ + { + "type": "Text", + "text": "${primaryText}", + "style": "textStyleDetail", + "grow": 1, + "shrink": 1, + "fontWeight": "300", + "maxLines": 1 + }, + { + "type": "Text", + "text": "${secondaryText}", + "style": "textStyleCaption", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + }, + { + "type": "Text", + "text": "${tertiaryText}", + "style": "textStyleDetails", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + } + ] + } + ] + }, + { + "type": "Container", + "direction": "row", + "height": 125, + "width": 800, + "alignItems": "center", + "items": [ + { + "type": "Text", + "text": "${ordinal}", + "paddingBottom": "20dp", + "color": "white", + "spacing": "5dp" + }, + { + "type": "Image", + "when": "${image}", + "source": "${image}", + "height": 100, + "width": 100, + "align": "top", + "spacing": 50, + "scale": "best-fit" + }, + { + "type": "Container", + "spacing": 30, + "direction": "column", + "items": [ + { + "type": "Text", + "text": "${primaryText}", + "style": "textStyleBody", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + }, + { + "type": "Text", + "text": "${secondaryText}", + "style": "textStyleDetails", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + } + ] + }, + { + "type": "Text", + "text": "${tertiaryText}", + "style": "textStyleBody", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "textAlign": "right", + "maxLines": 1 + } + ] + } + ] + } + }, + "mainTemplate": { + "parameters": ["payload"], + "item": [ + { + "type": "Container", + "id": "BookCabSimpleDialogAPL", + "items": [ + { + "type": "TouchWrapper", + "onPress": { + "type": "SendEvent", + "arguments": ["delegateToColtraneOld"] + }, + "item": { + "type": "Text", + "id": "BookCabSimpleDialogAPL", + "paddingTop": "100", + "paddingLeft": "100", + "color": "green", + "size": 50, + "text": "which city ?" + } + } + ] + } + ] + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/display/request_date_apl_display/document.json b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/display/request_date_apl_display/document.json new file mode 100644 index 00000000..d41ea236 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/display/request_date_apl_display/document.json @@ -0,0 +1,331 @@ +{ + "type": "APL", + "version": "1.1", + "settings": {}, + "theme": "dark", + "import": [ + { + "name": "alexa-layouts", + "version": "1.0.0" + } + ], + "resources": [ + { + "description": "Stock color for the light theme", + "colors": { + "colorTextPrimary": "#151920" + } + }, + { + "description": "Stock color for the dark theme", + "when": "${viewport.theme == 'dark'}", + "colors": { + "colorTextPrimary": "#f0f1ef" + } + }, + { + "description": "Standard font sizes", + "dimensions": { + "textSizeBody": 48, + "textSizePrimary": 27, + "textSizeSecondary": 23, + "textSizeDetails": 20, + "textSizeSecondaryHint": 25 + } + }, + { + "description": "Common spacing values", + "dimensions": { + "spacingThin": 6, + "spacingSmall": 12, + "spacingMedium": 24, + "spacingLarge": 48, + "spacingExtraLarge": 72 + } + }, + { + "description": "Common margins and padding", + "dimensions": { + "marginTop": 40, + "marginLeft": 60, + "marginRight": 60, + "marginBottom": 40 + } + } + ], + "styles": { + "textStyleBase": { + "description": "Base font description; set color", + "values": [ + { + "color": "@colorTextPrimary" + } + ] + }, + "textStyleBase0": { + "description": "Thin version of basic font", + "extend": "textStyleBase", + "values": { + "fontWeight": "100" + } + }, + "textStyleBase1": { + "description": "Light version of basic font", + "extend": "textStyleBase", + "values": { + "fontWeight": "300" + } + }, + "textStyleBase2": { + "description": "Regular version of basic font", + "extend": "textStyleBase", + "values": { + "fontWeight": "500" + } + }, + "mixinBody": { + "values": { + "fontSize": "@textSizeBody" + } + }, + "mixinPrimary": { + "values": { + "fontSize": "@textSizePrimary" + } + }, + "mixinDetails": { + "values": { + "fontSize": "@textSizeDetails" + } + }, + "mixinSecondary": { + "values": { + "fontSize": "@textSizeSecondary" + } + }, + "textStylePrimary": { + "extend": ["textStyleBase1", "mixinPrimary"] + }, + "textStyleSecondary": { + "extend": ["textStyleBase0", "mixinSecondary"] + }, + "textStyleBody": { + "extend": ["textStyleBase1", "mixinBody"] + }, + "textStyleSecondaryHint": { + "values": { + "fontFamily": "Bookerly", + "fontStyle": "italic", + "fontSize": "@textSizeSecondaryHint", + "color": "@colorTextPrimary" + } + }, + "textStyleDetails": { + "extend": ["textStyleBase2", "mixinDetails"] + } + }, + "onMount": [], + "graphics": {}, + "commands": {}, + "layouts": { + "ListTemplate1": { + "parameters": ["backgroundImage", "title", "logo", "hintText", "listData"], + "item": [ + { + "type": "Container", + "width": "100vw", + "height": "100vh", + "direction": "column", + "items": [ + { + "type": "Image", + "source": "${backgroundImage}", + "scale": "best-fill", + "width": "100vw", + "height": "100vh", + "position": "absolute" + }, + { + "type": "AlexaHeader", + "headerTitle": "${title}", + "headerAttributionImage": "${logo}" + }, + { + "type": "Sequence", + "grow": 1, + "height": "80vh", + "scrollDirection": "vertical", + "paddingLeft": "@marginLeft", + "paddingRight": "@marginRight", + "data": "${listData}", + "numbered": true, + "items": [ + { + "type": "VerticalListItem", + "image": "${data.image.sources[0].url}", + "primaryText": "${data.textContent.primaryText.text}", + "secondaryText": "${data.textContent.secondaryText.text}", + "tertiaryText": "${data.textContent.tertiaryText.text}" + } + ] + } + ] + } + ] + }, + "VerticalListItem": { + "parameters": ["primaryText", "secondaryText", "tertiaryText", "image"], + "item": [ + { + "when": "${viewport.shape == 'round'}", + "type": "Container", + "direction": "row", + "height": 200, + "width": 500, + "alignItems": "center", + "items": [ + { + "type": "Text", + "text": "${ordinal}", + "paddingBottom": "20dp", + "color": "white", + "spacing": "5dp" + }, + { + "type": "Image", + "when": "${image}", + "source": "${image}", + "height": 150, + "width": 150, + "spacing": 15, + "scale": "best-fit", + "align": "top" + }, + { + "type": "Container", + "direction": "column", + "spacing": 25, + "items": [ + { + "type": "Text", + "text": "${primaryText}", + "style": "textStyleDetail", + "grow": 1, + "shrink": 1, + "fontWeight": "300", + "maxLines": 1 + }, + { + "type": "Text", + "text": "${secondaryText}", + "style": "textStyleCaption", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + }, + { + "type": "Text", + "text": "${tertiaryText}", + "style": "textStyleDetails", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + } + ] + } + ] + }, + { + "type": "Container", + "direction": "row", + "height": 125, + "width": 800, + "alignItems": "center", + "items": [ + { + "type": "Text", + "text": "${ordinal}", + "paddingBottom": "20dp", + "color": "white", + "spacing": "5dp" + }, + { + "type": "Image", + "when": "${image}", + "source": "${image}", + "height": 100, + "width": 100, + "align": "top", + "spacing": 50, + "scale": "best-fit" + }, + { + "type": "Container", + "spacing": 30, + "direction": "column", + "items": [ + { + "type": "Text", + "text": "${primaryText}", + "style": "textStyleBody", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + }, + { + "type": "Text", + "text": "${secondaryText}", + "style": "textStyleDetails", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + } + ] + }, + { + "type": "Text", + "text": "${tertiaryText}", + "style": "textStyleBody", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "textAlign": "right", + "maxLines": 1 + } + ] + } + ] + } + }, + "mainTemplate": { + "parameters": ["payload"], + "item": [ + { + "type": "Container", + "id": "BookCabSimpleDialogAPL", + "items": [ + { + "type": "TouchWrapper", + "onPress": { + "type": "SendEvent", + "arguments": ["delegateToColtraneOld"] + }, + "item": { + "type": "Text", + "id": "BookCabSimpleDialogAPL", + "paddingTop": "100", + "paddingLeft": "100", + "color": "green", + "size": 50, + "text": "which date ?" + } + } + ] + } + ] + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/display/weather_success_apl_display/document.json b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/display/weather_success_apl_display/document.json new file mode 100644 index 00000000..3bcc0e4a --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/display/weather_success_apl_display/document.json @@ -0,0 +1,379 @@ +{ + "type": "APL", + "version": "1.1", + "settings": {}, + "theme": "dark", + "import": [ + { + "name": "alexa-layouts", + "version": "1.0.0" + } + ], + "resources": [ + { + "description": "Stock color for the light theme", + "colors": { + "colorTextPrimary": "#151920" + } + }, + { + "description": "Stock color for the dark theme", + "when": "${viewport.theme == 'dark'}", + "colors": { + "colorTextPrimary": "#f0f1ef" + } + }, + { + "description": "Standard font sizes", + "dimensions": { + "textSizeBody": 48, + "textSizePrimary": 27, + "textSizeSecondary": 23, + "textSizeDetails": 20, + "textSizeSecondaryHint": 25 + } + }, + { + "description": "Common spacing values", + "dimensions": { + "spacingThin": 6, + "spacingSmall": 12, + "spacingMedium": 24, + "spacingLarge": 48, + "spacingExtraLarge": 72 + } + }, + { + "description": "Common margins and padding", + "dimensions": { + "marginTop": 40, + "marginLeft": 60, + "marginRight": 60, + "marginBottom": 40 + } + } + ], + "styles": { + "textStyleBase": { + "description": "Base font description; set color", + "values": [ + { + "color": "@colorTextPrimary" + } + ] + }, + "textStyleBase0": { + "description": "Thin version of basic font", + "extend": "textStyleBase", + "values": { + "fontWeight": "100" + } + }, + "textStyleBase1": { + "description": "Light version of basic font", + "extend": "textStyleBase", + "values": { + "fontWeight": "300" + } + }, + "textStyleBase2": { + "description": "Regular version of basic font", + "extend": "textStyleBase", + "values": { + "fontWeight": "500" + } + }, + "mixinBody": { + "values": { + "fontSize": "@textSizeBody" + } + }, + "mixinPrimary": { + "values": { + "fontSize": "@textSizePrimary" + } + }, + "mixinDetails": { + "values": { + "fontSize": "@textSizeDetails" + } + }, + "mixinSecondary": { + "values": { + "fontSize": "@textSizeSecondary" + } + }, + "textStylePrimary": { + "extend": ["textStyleBase1", "mixinPrimary"] + }, + "textStyleSecondary": { + "extend": ["textStyleBase0", "mixinSecondary"] + }, + "textStyleBody": { + "extend": ["textStyleBase1", "mixinBody"] + }, + "textStyleSecondaryHint": { + "values": { + "fontFamily": "Bookerly", + "fontStyle": "italic", + "fontSize": "@textSizeSecondaryHint", + "color": "@colorTextPrimary" + } + }, + "textStyleDetails": { + "extend": ["textStyleBase2", "mixinDetails"] + } + }, + "onMount": [], + "graphics": {}, + "commands": {}, + "layouts": { + "ListTemplate1": { + "parameters": ["backgroundImage", "title", "logo", "hintText", "listData"], + "item": [ + { + "type": "Container", + "width": "100vw", + "height": "100vh", + "direction": "column", + "items": [ + { + "type": "Image", + "source": "${backgroundImage}", + "scale": "best-fill", + "width": "100vw", + "height": "100vh", + "position": "absolute" + }, + { + "type": "AlexaHeader", + "headerTitle": "${title}", + "headerAttributionImage": "${logo}" + }, + { + "type": "Sequence", + "grow": 1, + "height": "80vh", + "scrollDirection": "vertical", + "paddingLeft": "@marginLeft", + "paddingRight": "@marginRight", + "data": "${listData}", + "numbered": true, + "items": [ + { + "type": "VerticalListItem", + "image": "${data.image.sources[0].url}", + "primaryText": "${data.textContent.primaryText.text}", + "secondaryText": "${data.textContent.secondaryText.text}", + "tertiaryText": "${data.textContent.tertiaryText.text}" + } + ] + } + ] + } + ] + }, + "VerticalListItem": { + "parameters": ["primaryText", "secondaryText", "tertiaryText", "image"], + "item": [ + { + "when": "${viewport.shape == 'round'}", + "type": "Container", + "direction": "row", + "height": 200, + "width": 500, + "alignItems": "center", + "items": [ + { + "type": "Text", + "text": "${ordinal}", + "paddingBottom": "20dp", + "color": "white", + "spacing": "5dp" + }, + { + "type": "Image", + "when": "${image}", + "source": "${image}", + "height": 150, + "width": 150, + "spacing": 15, + "scale": "best-fit", + "align": "top" + }, + { + "type": "Container", + "direction": "column", + "spacing": 25, + "items": [ + { + "type": "Text", + "text": "${primaryText}", + "style": "textStyleDetail", + "grow": 1, + "shrink": 1, + "fontWeight": "300", + "maxLines": 1 + }, + { + "type": "Text", + "text": "${secondaryText}", + "style": "textStyleCaption", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + }, + { + "type": "Text", + "text": "${tertiaryText}", + "style": "textStyleDetails", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + } + ] + } + ] + }, + { + "type": "Container", + "direction": "row", + "height": 125, + "width": 800, + "alignItems": "center", + "items": [ + { + "type": "Text", + "text": "${ordinal}", + "paddingBottom": "20dp", + "color": "white", + "spacing": "5dp" + }, + { + "type": "Image", + "when": "${image}", + "source": "${image}", + "height": 100, + "width": 100, + "align": "top", + "spacing": 50, + "scale": "best-fit" + }, + { + "type": "Container", + "spacing": 30, + "direction": "column", + "items": [ + { + "type": "Text", + "text": "${primaryText}", + "style": "textStyleBody", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + }, + { + "type": "Text", + "text": "${secondaryText}", + "style": "textStyleDetails", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + } + ] + }, + { + "type": "Text", + "text": "${tertiaryText}", + "style": "textStyleBody", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "textAlign": "right", + "maxLines": 1 + } + ] + } + ] + } + }, + "mainTemplate": { + "parameters": ["payload"], + "item": [ + { + "type": "Container", + "id": "BookCabSimpleDialogAPL", + "items": [ + { + "type": "TouchWrapper", + "onPress": { + "type": "SendEvent", + "arguments": ["delegateToSkillNew"] + }, + "item": { + "type": "Text", + "id": "BookCabSimpleDialogAPL", + "paddingTop": "100", + "paddingLeft": "100", + "color": "green", + "size": 50, + "text": "delegateToSkillNew" + } + }, + { + "type": "TouchWrapper", + "onPress": { + "type": "SendEvent", + "arguments": ["delegateToSkillOld"] + }, + "item": { + "type": "Text", + "id": "BookCabSimpleDialogAPL", + "paddingTop": "100", + "paddingLeft": "100", + "color": "green", + "size": 50, + "text": "delegateToSkillOld" + } + }, + { + "type": "TouchWrapper", + "onPress": { + "type": "SendEvent", + "arguments": ["delegateToColtraneNew"] + }, + "item": { + "type": "Text", + "id": "BookCabSimpleDialogAPL", + "paddingTop": "100", + "paddingLeft": "100", + "color": "green", + "size": 50, + "text": "delegateToColtraneNew" + } + }, + { + "type": "TouchWrapper", + "onPress": { + "type": "SendEvent", + "arguments": ["delegateToColtraneOld"] + }, + "item": { + "type": "Text", + "id": "BookCabSimpleDialogAPL", + "paddingTop": "100", + "paddingLeft": "100", + "color": "green", + "size": 50, + "text": "delegateToColtraneOld" + } + } + ] + } + ] + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/AlexaConversationsBye/document.json b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/AlexaConversationsBye/document.json new file mode 100644 index 00000000..a0e2b3a8 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/AlexaConversationsBye/document.json @@ -0,0 +1,19 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": ["payload"], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "Bye.", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/AlexaConversationsNotifyFailure/document.json b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/AlexaConversationsNotifyFailure/document.json new file mode 100644 index 00000000..61d75e08 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/AlexaConversationsNotifyFailure/document.json @@ -0,0 +1,19 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": ["payload"], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "Sorry, there was an error in the request.", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/AlexaConversationsOutOfDomain/document.json b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/AlexaConversationsOutOfDomain/document.json new file mode 100644 index 00000000..e23d5986 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/AlexaConversationsOutOfDomain/document.json @@ -0,0 +1,19 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": ["payload"], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "Sorry, I don't understand.", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/AlexaConversationsProvideHelp/document.json b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/AlexaConversationsProvideHelp/document.json new file mode 100644 index 00000000..612a6f6e --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/AlexaConversationsProvideHelp/document.json @@ -0,0 +1,19 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": ["payload"], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "I can give you the weather report. Just say \"what's the weather\" to start.", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/AlexaConversationsRequestMore/document.json b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/AlexaConversationsRequestMore/document.json new file mode 100644 index 00000000..32a98507 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/AlexaConversationsRequestMore/document.json @@ -0,0 +1,19 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": ["payload"], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "What do you want to do.", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/AlexaConversationsThankYou/document.json b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/AlexaConversationsThankYou/document.json new file mode 100644 index 00000000..4aeb6f4b --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/AlexaConversationsThankYou/document.json @@ -0,0 +1,19 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": ["payload"], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "Thank you.", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/AlexaConversationsWelcome/document.json b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/AlexaConversationsWelcome/document.json new file mode 100644 index 00000000..2b43c89b --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/AlexaConversationsWelcome/document.json @@ -0,0 +1,19 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": ["payload"], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "Welcome to the weatherOct16", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/AlexaConversationsYouAreWelcome/document.json b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/AlexaConversationsYouAreWelcome/document.json new file mode 100644 index 00000000..2cd1b9a8 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/AlexaConversationsYouAreWelcome/document.json @@ -0,0 +1,19 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": ["payload"], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "You are welcome.", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/SuccessGiveMeTodaySpecialsEvent_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/SuccessGiveMeTodaySpecialsEvent_apla/document.json new file mode 100644 index 00000000..fe2a6876 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/SuccessGiveMeTodaySpecialsEvent_apla/document.json @@ -0,0 +1,20 @@ +{ + "type": "APLA", + "version": "0.8", + "mainTemplate": { + "parameters": ["payload"], + "item": { + "type": "Selector", + "strategy": "randomItem", + "description": "Change 'type' above to try different Selector Component Types like Sequencer", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "today's special are ${payload.result.length} items , all items are ${payload.result}, first item is ${payload.result[0]}", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/SuccessGiveMeTodaySpecialsEvent_apla_failure/document.json b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/SuccessGiveMeTodaySpecialsEvent_apla_failure/document.json new file mode 100644 index 00000000..43a45860 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/SuccessGiveMeTodaySpecialsEvent_apla_failure/document.json @@ -0,0 +1,20 @@ +{ + "type": "APLA", + "version": "0.8", + "mainTemplate": { + "parameters": ["payload"], + "item": { + "type": "Selector", + "strategy": "randomItem", + "description": "Change 'type' above to try different Selector Component Types like Sequencer", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "Failure : today's special are ${payload.result.length} items , all items are ${payload.result}, first item is ${payload.result[0]}", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/askForCrustPrompts/datasources/default.json b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/askForCrustPrompts/datasources/default.json new file mode 100644 index 00000000..0967ef42 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/askForCrustPrompts/datasources/default.json @@ -0,0 +1 @@ +{} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/askForCrustPrompts/document.json b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/askForCrustPrompts/document.json new file mode 100644 index 00000000..f18d4e17 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/askForCrustPrompts/document.json @@ -0,0 +1,26 @@ +{ + "type": "APLA", + "version": "0.8", + "mainTemplate": { + "parameters": ["payload"], + "item": { + "type": "Selector", + "strategy": "randomItem", + "description": "Change 'type' above to try different Selector Component Types like Sequencer", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "On what kind of crust, we have thin, deep dish, regular and brooklyn style", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + }, + { + "type": "Speech", + "contentType": "text", + "content": "Ok, we have thin, deep dish, regular and brooklyn style, what would you like", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/askForSizePrompts/datasources/default.json b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/askForSizePrompts/datasources/default.json new file mode 100644 index 00000000..0967ef42 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/askForSizePrompts/datasources/default.json @@ -0,0 +1 @@ +{} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/askForSizePrompts/document.json b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/askForSizePrompts/document.json new file mode 100644 index 00000000..601c788f --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/askForSizePrompts/document.json @@ -0,0 +1,26 @@ +{ + "type": "APLA", + "version": "0.8", + "mainTemplate": { + "parameters": ["payload"], + "item": { + "type": "Selector", + "strategy": "randomItem", + "description": "Change 'type' above to try different Selector Component Types like Sequencer", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "What size? We have small, medium, large and extra large", + "description": "Prompt for size" + }, + { + "type": "Speech", + "contentType": "text", + "content": "Ok. We have small to extra large pizzas. What size would you like? ", + "description": "Prompt for size" + } + ] + } + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/askForToppingOnePrompt/datasources/default.json b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/askForToppingOnePrompt/datasources/default.json new file mode 100644 index 00000000..0967ef42 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/askForToppingOnePrompt/datasources/default.json @@ -0,0 +1 @@ +{} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/askForToppingOnePrompt/document.json b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/askForToppingOnePrompt/document.json new file mode 100644 index 00000000..a0a43ab5 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/askForToppingOnePrompt/document.json @@ -0,0 +1,20 @@ +{ + "type": "APLA", + "version": "0.8", + "mainTemplate": { + "parameters": ["payload"], + "item": { + "type": "Selector", + "strategy": "randomItem", + "description": "Change 'type' above to try different Selector Component Types like Sequencer", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "What would you like for the 1st topping?", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/askForToppingTwoPrompt/datasources/default.json b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/askForToppingTwoPrompt/datasources/default.json new file mode 100644 index 00000000..0967ef42 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/askForToppingTwoPrompt/datasources/default.json @@ -0,0 +1 @@ +{} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/askForToppingTwoPrompt/document.json b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/askForToppingTwoPrompt/document.json new file mode 100644 index 00000000..a53aa22d --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/askForToppingTwoPrompt/document.json @@ -0,0 +1,20 @@ +{ + "type": "APLA", + "version": "0.8", + "mainTemplate": { + "parameters": ["payload"], + "item": { + "type": "Selector", + "strategy": "randomItem", + "description": "Change 'type' above to try different Selector Component Types like Sequencer", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "What about the 2nd topping?", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/askForToppingsPrompts/datasources/default.json b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/askForToppingsPrompts/datasources/default.json new file mode 100644 index 00000000..0967ef42 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/askForToppingsPrompts/datasources/default.json @@ -0,0 +1 @@ +{} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/askForToppingsPrompts/document.json b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/askForToppingsPrompts/document.json new file mode 100644 index 00000000..f1fea64d --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/askForToppingsPrompts/document.json @@ -0,0 +1,20 @@ +{ + "type": "APLA", + "version": "0.8", + "mainTemplate": { + "parameters": ["payload"], + "item": { + "type": "Selector", + "strategy": "randomItem", + "description": "Change 'type' above to try different Selector Component Types like Sequencer", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "What would you like on your pizza?", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/askForTwoToppingsPrompts/datasources/default.json b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/askForTwoToppingsPrompts/datasources/default.json new file mode 100644 index 00000000..0967ef42 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/askForTwoToppingsPrompts/datasources/default.json @@ -0,0 +1 @@ +{} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/askForTwoToppingsPrompts/document.json b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/askForTwoToppingsPrompts/document.json new file mode 100644 index 00000000..7f961daf --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/askForTwoToppingsPrompts/document.json @@ -0,0 +1,20 @@ +{ + "type": "APLA", + "version": "0.8", + "mainTemplate": { + "parameters": ["payload"], + "item": { + "type": "Selector", + "strategy": "randomItem", + "description": "Change 'type' above to try different Selector Component Types like Sequencer", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "Ok, what two toppings would you like?", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/askForTwoToppingsPrompts_copy/datasources/default.json b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/askForTwoToppingsPrompts_copy/datasources/default.json new file mode 100644 index 00000000..0967ef42 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/askForTwoToppingsPrompts_copy/datasources/default.json @@ -0,0 +1 @@ +{} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/askForTwoToppingsPrompts_copy/document.json b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/askForTwoToppingsPrompts_copy/document.json new file mode 100644 index 00000000..7f961daf --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/askForTwoToppingsPrompts_copy/document.json @@ -0,0 +1,20 @@ +{ + "type": "APLA", + "version": "0.8", + "mainTemplate": { + "parameters": ["payload"], + "item": { + "type": "Selector", + "strategy": "randomItem", + "description": "Change 'type' above to try different Selector Component Types like Sequencer", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "Ok, what two toppings would you like?", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/confirmAction_complexNames_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/confirmAction_complexNames_apla/document.json new file mode 100644 index 00000000..d2d72c41 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/confirmAction_complexNames_apla/document.json @@ -0,0 +1,19 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": ["payload"], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "confirm Action your cool name ${payload.name} and ${payload.sign}? ", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/confirmArgs_complexNames_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/confirmArgs_complexNames_apla/document.json new file mode 100644 index 00000000..4ada7688 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/confirmArgs_complexNames_apla/document.json @@ -0,0 +1,19 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": ["payload"], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "confirm args your cool name ${payload.name} and ${payload.sign}? ", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/confirmSizePrompt/datasources/default.json b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/confirmSizePrompt/datasources/default.json new file mode 100644 index 00000000..c9c6423f --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/confirmSizePrompt/datasources/default.json @@ -0,0 +1 @@ +{"size": "extra large"} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/confirmSizePrompt/document.json b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/confirmSizePrompt/document.json new file mode 100644 index 00000000..070f8dba --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/confirmSizePrompt/document.json @@ -0,0 +1,20 @@ +{ + "type": "APLA", + "version": "0.8", + "mainTemplate": { + "parameters": ["payload"], + "item": { + "type": "Sequencer", + "description": "Change 'type' above to try different Selector Component Types like Sequencer", + "items": [ + {"type": "Speech", "contentType": "text", "content": "You wanted "}, + { + "type": "Speech", + "when": "${payload.size == 'small' || payload.size == 'large' || payload.size == 'medium'}", + "content": "a ${payload.size} pizza, is that correct?" + }, + {"type": "Speech", "when": "${payload.size == 'extra large'}", "content": "an ${payload.size} pizza, is that correct?"} + ] + } + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/confirmTwoToppingOrderPrompt/datasources/default.json b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/confirmTwoToppingOrderPrompt/datasources/default.json new file mode 100644 index 00000000..0967ef42 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/confirmTwoToppingOrderPrompt/datasources/default.json @@ -0,0 +1 @@ +{} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/confirmTwoToppingOrderPrompt/document.json b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/confirmTwoToppingOrderPrompt/document.json new file mode 100644 index 00000000..25713921 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/confirmTwoToppingOrderPrompt/document.json @@ -0,0 +1,20 @@ +{ + "type": "APLA", + "version": "0.8", + "mainTemplate": { + "parameters": ["payload"], + "item": { + "type": "Selector", + "strategy": "randomItem", + "description": "Change 'type' above to try different Selector Component Types like Sequencer", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "Ok, that's a ${payload.first_topping} and ${payload.second_topping} on ${payload.crust} crust. Is that correct?", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/confirmTwoToppingOrderPromptcopy/datasources/default.json b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/confirmTwoToppingOrderPromptcopy/datasources/default.json new file mode 100644 index 00000000..0967ef42 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/confirmTwoToppingOrderPromptcopy/datasources/default.json @@ -0,0 +1 @@ +{} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/confirmTwoToppingOrderPromptcopy/document.json b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/confirmTwoToppingOrderPromptcopy/document.json new file mode 100644 index 00000000..25c0e27b --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/confirmTwoToppingOrderPromptcopy/document.json @@ -0,0 +1,20 @@ +{ + "type": "APLA", + "version": "0.8", + "mainTemplate": { + "parameters": ["payload"], + "item": { + "type": "Selector", + "strategy": "randomItem", + "description": "Change 'type' above to try different Selector Component Types like Sequencer", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "Ok, that's a ${payload.size} ${payload.first_topping} and ${payload.second_topping} on ${payload.crust} crust. Is that correct?", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/confirmTwoToppingsPrompt/datasources/default.json b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/confirmTwoToppingsPrompt/datasources/default.json new file mode 100644 index 00000000..0967ef42 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/confirmTwoToppingsPrompt/datasources/default.json @@ -0,0 +1 @@ +{} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/confirmTwoToppingsPrompt/document.json b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/confirmTwoToppingsPrompt/document.json new file mode 100644 index 00000000..00926d2b --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/confirmTwoToppingsPrompt/document.json @@ -0,0 +1,20 @@ +{ + "type": "APLA", + "version": "0.8", + "mainTemplate": { + "parameters": ["payload"], + "item": { + "type": "Selector", + "strategy": "randomItem", + "description": "Change 'type' above to try different Selector Component Types like Sequencer", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "Just to confirm, you want ${payload.first_topping} and ${payload.second_topping}", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/confirm_color_for_fruit_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/confirm_color_for_fruit_apla/document.json new file mode 100644 index 00000000..62c9758b --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/confirm_color_for_fruit_apla/document.json @@ -0,0 +1,19 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": ["payload"], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "confirm color is ${payload.colorName} ? ", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/confirm_fruitName_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/confirm_fruitName_apla/document.json new file mode 100644 index 00000000..47433a49 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/confirm_fruitName_apla/document.json @@ -0,0 +1,19 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": ["payload"], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "confirm fruit ${payload.fruitName} ? ", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/confirm_main_addon_list_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/confirm_main_addon_list_apla/document.json new file mode 100644 index 00000000..113da0d0 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/confirm_main_addon_list_apla/document.json @@ -0,0 +1,19 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": ["payload"], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "confirm ${payload.foodName} with ${payload.addOn} ? ", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/confirm_weather_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/confirm_weather_apla/document.json new file mode 100644 index 00000000..e63460da --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/confirm_weather_apla/document.json @@ -0,0 +1,19 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": ["payload"], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "Confirm weather forecast for ${payload.cityName} ${payload.date}?", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/confirm_weather_city_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/confirm_weather_city_apla/document.json new file mode 100644 index 00000000..498fa5f6 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/confirm_weather_city_apla/document.json @@ -0,0 +1,19 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": ["payload"], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "Confirm weather for ${payload.cityName}?", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/confirm_weather_date_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/confirm_weather_date_apla/document.json new file mode 100644 index 00000000..b9102336 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/confirm_weather_date_apla/document.json @@ -0,0 +1,19 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": ["payload"], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "Confirm weather for ${payload.date}?", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/no_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/no_apla/document.json new file mode 100644 index 00000000..96a3af82 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/no_apla/document.json @@ -0,0 +1,19 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": ["payload"], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "I'm sorry you didn't like it", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/nothing2_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/nothing2_apla/document.json new file mode 100644 index 00000000..af75a7a5 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/nothing2_apla/document.json @@ -0,0 +1,19 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": ["payload"], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "The number you gave us was not 3.", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/nothing_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/nothing_apla/document.json new file mode 100644 index 00000000..bca77c74 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/nothing_apla/document.json @@ -0,0 +1,19 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": ["payload"], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "The number you gave us was 3.", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/numericfeedback_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/numericfeedback_apla/document.json new file mode 100644 index 00000000..2219120c --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/numericfeedback_apla/document.json @@ -0,0 +1,19 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": ["payload"], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "Your random number was ${payload.num}. How did we do? Please give this interaction a rating between 1-5, where 5 is the highest rating", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/rating_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/rating_apla/document.json new file mode 100644 index 00000000..06b50d68 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/rating_apla/document.json @@ -0,0 +1,19 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": ["payload"], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "rating please?", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/requestArgs_request_fruitName_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/requestArgs_request_fruitName_apla/document.json new file mode 100644 index 00000000..5e5d608a --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/requestArgs_request_fruitName_apla/document.json @@ -0,0 +1,25 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": ["payload"], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "tell me the fruit name ?", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + }, + { + "type": "Speech", + "contentType": "text", + "content": "random slection tell me the fruit name ?", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/requestFromBookFlight_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/requestFromBookFlight_apla/document.json new file mode 100644 index 00000000..db1436d6 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/requestFromBookFlight_apla/document.json @@ -0,0 +1,20 @@ +{ + "type": "APLA", + "version": "0.8", + "mainTemplate": { + "parameters": ["payload"], + "item": { + "type": "Selector", + "strategy": "randomItem", + "description": "Change 'type' above to try different Selector Component Types like Sequencer", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "from where?", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/requestPickUpFromBookCab_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/requestPickUpFromBookCab_apla/document.json new file mode 100644 index 00000000..7e4c3ef7 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/requestPickUpFromBookCab_apla/document.json @@ -0,0 +1,20 @@ +{ + "type": "APLA", + "version": "0.8", + "mainTemplate": { + "parameters": ["payload"], + "item": { + "type": "Selector", + "strategy": "randomItem", + "description": "Change 'type' above to try different Selector Component Types like Sequencer", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "request PickUp From BookCab apla, from where ?", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/requestToBookFlight_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/requestToBookFlight_apla/document.json new file mode 100644 index 00000000..aa9e23b0 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/requestToBookFlight_apla/document.json @@ -0,0 +1,20 @@ +{ + "type": "APLA", + "version": "0.8", + "mainTemplate": { + "parameters": ["payload"], + "item": { + "type": "Selector", + "strategy": "randomItem", + "description": "Change 'type' above to try different Selector Component Types like Sequencer", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "to where ?", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/request_city_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/request_city_apla/document.json new file mode 100644 index 00000000..64297b5e --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/request_city_apla/document.json @@ -0,0 +1,19 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": ["payload"], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "Which city?", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/request_city_cityName_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/request_city_cityName_apla/document.json new file mode 100644 index 00000000..1bf948d1 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/request_city_cityName_apla/document.json @@ -0,0 +1,25 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": ["payload"], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "Which city?", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + }, + { + "type": "Speech", + "contentType": "text", + "content": "random selector Which city?", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/request_city_cityName_date_AMAZON_DATE_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/request_city_cityName_date_AMAZON_DATE_apla/document.json new file mode 100644 index 00000000..a55ea5e1 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/request_city_cityName_date_AMAZON_DATE_apla/document.json @@ -0,0 +1,19 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": ["payload"], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "Which city and for which date?", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/request_colorName_multiple_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/request_colorName_multiple_apla/document.json new file mode 100644 index 00000000..5e5891e1 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/request_colorName_multiple_apla/document.json @@ -0,0 +1,19 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": ["payload"], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "which color?", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/request_date_AMAZON_DATE_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/request_date_AMAZON_DATE_apla/document.json new file mode 100644 index 00000000..af3a3f7d --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/request_date_AMAZON_DATE_apla/document.json @@ -0,0 +1,19 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": ["payload"], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "Which date?", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/request_date_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/request_date_apla/document.json new file mode 100644 index 00000000..af3a3f7d --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/request_date_apla/document.json @@ -0,0 +1,19 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": ["payload"], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "Which date?", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/request_listAddOns_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/request_listAddOns_apla/document.json new file mode 100644 index 00000000..50faed8e --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/request_listAddOns_apla/document.json @@ -0,0 +1,19 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": ["payload"], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "what are the add ons?", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/request_mainFoodName_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/request_mainFoodName_apla/document.json new file mode 100644 index 00000000..316161b3 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/request_mainFoodName_apla/document.json @@ -0,0 +1,19 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": ["payload"], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "What is the main food name?", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/request_name_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/request_name_apla/document.json new file mode 100644 index 00000000..db05dfee --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/request_name_apla/document.json @@ -0,0 +1,19 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": ["payload"], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "SSML", + "content": "what is your cool name?", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/request_sign_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/request_sign_apla/document.json new file mode 100644 index 00000000..b96b84ce --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/request_sign_apla/document.json @@ -0,0 +1,19 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": ["payload"], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "SSML", + "content": "which sign", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/requestdropToBookCab_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/requestdropToBookCab_apla/document.json new file mode 100644 index 00000000..aa9e23b0 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/requestdropToBookCab_apla/document.json @@ -0,0 +1,20 @@ +{ + "type": "APLA", + "version": "0.8", + "mainTemplate": { + "parameters": ["payload"], + "item": { + "type": "Selector", + "strategy": "randomItem", + "description": "Change 'type' above to try different Selector Component Types like Sequencer", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "to where ?", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/secondEarthAPI_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/secondEarthAPI_apla/document.json new file mode 100644 index 00000000..263c095a --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/secondEarthAPI_apla/document.json @@ -0,0 +1,19 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": ["payload"], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "success delegating", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/seq_offer_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/seq_offer_apla/document.json new file mode 100644 index 00000000..09c06d67 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/seq_offer_apla/document.json @@ -0,0 +1,19 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": ["payload"], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "sequence offer , lets find fav color by sign and name?", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/successBookCabAPI_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/successBookCabAPI_apla/document.json new file mode 100644 index 00000000..830fcf43 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/successBookCabAPI_apla/document.json @@ -0,0 +1,20 @@ +{ + "type": "APLA", + "version": "0.8", + "mainTemplate": { + "parameters": ["payload"], + "item": { + "type": "Selector", + "strategy": "randomItem", + "description": "Change 'type' above to try different Selector Component Types like Sequencer", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "Booked cab is ${payload.result.orderStatus}", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/successBookFlightAPI_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/successBookFlightAPI_apla/document.json new file mode 100644 index 00000000..46c6daf3 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/successBookFlightAPI_apla/document.json @@ -0,0 +1,20 @@ +{ + "type": "APLA", + "version": "0.8", + "mainTemplate": { + "parameters": ["payload"], + "item": { + "type": "Selector", + "strategy": "randomItem", + "description": "Change 'type' above to try different Selector Component Types like Sequencer", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "booked flight is ${payload.resultTwo.orderStatus} from ${payload.resultTwo.source} to ${payload.resultTwo.destination}, do you need cab to airport ?", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/success_cookingAPI_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/success_cookingAPI_apla/document.json new file mode 100644 index 00000000..2b920b3d --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/success_cookingAPI_apla/document.json @@ -0,0 +1,19 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": ["payload"], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "we have ${payload.status.orderStatus}", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/success_favColorSign_Name_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/success_favColorSign_Name_apla/document.json new file mode 100644 index 00000000..65211056 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/success_favColorSign_Name_apla/document.json @@ -0,0 +1,19 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": ["payload"], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "Fav color of ${payload.result.name}, is ${payload.result.color}", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/success_fruitPriceAPI_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/success_fruitPriceAPI_apla/document.json new file mode 100644 index 00000000..0db81389 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/success_fruitPriceAPI_apla/document.json @@ -0,0 +1,19 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": ["payload"], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "price of an ${payload.result.fruitName} is ${payload.result.price} bucks ", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/twoToppingOrderSuccessPrompt/datasources/default.json b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/twoToppingOrderSuccessPrompt/datasources/default.json new file mode 100644 index 00000000..0967ef42 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/twoToppingOrderSuccessPrompt/datasources/default.json @@ -0,0 +1 @@ +{} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/twoToppingOrderSuccessPrompt/document.json b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/twoToppingOrderSuccessPrompt/document.json new file mode 100644 index 00000000..24236a39 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/twoToppingOrderSuccessPrompt/document.json @@ -0,0 +1,20 @@ +{ + "type": "APLA", + "version": "0.8", + "mainTemplate": { + "parameters": ["payload"], + "item": { + "type": "Selector", + "strategy": "randomItem", + "description": "Change 'type' above to try different Selector Component Types like Sequencer", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "${payload.speech}", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/weather_success_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/weather_success_apla/document.json new file mode 100644 index 00000000..21441101 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/weather_success_apla/document.json @@ -0,0 +1,27 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": ["payload"], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "when": "${payload.weatherResult.cityName != null && payload.weatherResult.highTemp < 3 && payload.weatherResult.lowTemp > 0}", + "type": "Speech", + "contentType": "text", + "content": "Offer In ${payload.weatherResult.cityName}, it's a high of ${payload.weatherResult.highTemp} degrees and a low of ${payload.weatherResult.lowTemp} degrees.", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + }, + { + "when": "${payload.weatherResult.cityName != null && payload.weatherResult.highTemp == null && payload.weatherResult.lowTemp == null}", + "type": "Speech", + "contentType": "text", + "content": "Alternate In ${payload.weatherResult.cityName}, it's a high of ${payload.weatherResult.highTemp} degrees and a low of ${payload.weatherResult.lowTemp} degrees.", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/welcome_apla_custom/document.json b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/welcome_apla_custom/document.json new file mode 100644 index 00000000..20c5a48c --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/welcome_apla_custom/document.json @@ -0,0 +1,19 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": ["payload"], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "Hi Satheesh , you have visited ${payload.result}", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/skill.json b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/skill.json new file mode 100644 index 00000000..1cc857f9 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/skill.json @@ -0,0 +1,93 @@ +{ + "manifest": { + "apis": { + "custom": { + "dialogManagement": { + "dialogManagers": [ + { + "type": "AMAZON.Conversations" + } + ], + "sessionStartDelegationStrategy": { + "target": "AMAZON.Conversations" + } + }, + "endpoint": { + "uri": "arn:aws:lambda:us-east-1:658396899051:function:a3588a9b-d645-4a23-9e1a-90c984de0b83:Release_0" + }, + "interfaces": [ + { + "supportedViewports": [ + { + "maxHeight": 480, + "maxWidth": 480, + "minHeight": 480, + "minWidth": 480, + "mode": "HUB", + "shape": "ROUND" + }, + { + "maxHeight": 600, + "maxWidth": 1024, + "minHeight": 600, + "minWidth": 1024, + "mode": "HUB", + "shape": "RECTANGLE" + }, + { + "maxHeight": 800, + "maxWidth": 1280, + "minHeight": 800, + "minWidth": 1280, + "mode": "HUB", + "shape": "RECTANGLE" + }, + { + "maxHeight": 540, + "maxWidth": 960, + "minHeight": 540, + "minWidth": 960, + "mode": "TV", + "shape": "RECTANGLE" + } + ], + "type": "ALEXA_PRESENTATION_APL" + } + ], + "regions": { + "EU": { + "endpoint": { + "uri": "arn:aws:lambda:eu-west-1:658396899051:function:a3588a9b-d645-4a23-9e1a-90c984de0b83:Release_0" + } + }, + "NA": { + "endpoint": { + "uri": "arn:aws:lambda:us-east-1:658396899051:function:a3588a9b-d645-4a23-9e1a-90c984de0b83:Release_0" + } + }, + "FE": { + "endpoint": { + "uri": "arn:aws:lambda:us-west-2:658396899051:function:a3588a9b-d645-4a23-9e1a-90c984de0b83:Release_0" + } + } + } + } + }, + "manifestVersion": "1.0", + "publishingInformation": { + "category": "KNOWLEDGE_AND_TRIVIA", + "distributionCountries": [], + "isAvailableWorldwide": true, + "locales": { + "en-US": { + "description": "Sample Full Description", + "examplePhrases": ["Alexa open hello world", "hello", "help"], + "keywords": [], + "name": "engineering test skill two", + "summary": "Sample Short Description" + } + }, + "testingInstructions": "Sample Testing Instructions." + } + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-3/.ask/ask-states.json b/test/unit/fixture/dialog-evaluate/test-project-3/.ask/ask-states.json new file mode 100644 index 00000000..18048d0e --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-3/.ask/ask-states.json @@ -0,0 +1,8 @@ +{ + "askcliStatesVersion": "2020-03-31", + "profiles": { + "TEST_PROFILE": { + "skillId": "TEST_SKILL_ID" + } + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-3/ask-resources.json b/test/unit/fixture/dialog-evaluate/test-project-3/ask-resources.json new file mode 100644 index 00000000..649c901b --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-3/ask-resources.json @@ -0,0 +1,10 @@ +{ + "askcliResourcesVersion": "2020-03-31", + "profiles": { + "TEST_PROFILE": { + "skillMetadata": { + "src": "./skill-package" + } + } + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/TestDataACDLi18n/deBye/document.json b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/TestDataACDLi18n/deBye/document.json new file mode 100644 index 00000000..5927b675 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/TestDataACDLi18n/deBye/document.json @@ -0,0 +1,18 @@ +{ + "type": "APLA", + "version": "0.8", + "mainTemplate": { + "parameters": ["payload"], + "item": { + "type": "Selector", + "strategy": "randomItem", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "Tschüss satheesh" + } + ] + } + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/TestDataACDLi18n/deHelp/document.json b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/TestDataACDLi18n/deHelp/document.json new file mode 100644 index 00000000..777cc487 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/TestDataACDLi18n/deHelp/document.json @@ -0,0 +1,19 @@ +{ + "type": "APLA", + "version": "0.8", + "mainTemplate": { + "parameters": ["payload"], + "item": { + "type": "Selector", + "strategy": "randomItem", + "description": "Change \u0027type\u0027 above to try different Selector Component Types like Sequencer", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "Hilfe leisten satheesh" + } + ] + } + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/TestDataACDLi18n/deOutOfDomain/datasources/default.json b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/TestDataACDLi18n/deOutOfDomain/datasources/default.json new file mode 100644 index 00000000..0967ef42 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/TestDataACDLi18n/deOutOfDomain/datasources/default.json @@ -0,0 +1 @@ +{} diff --git a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/TestDataACDLi18n/deOutOfDomain/document.json b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/TestDataACDLi18n/deOutOfDomain/document.json new file mode 100644 index 00000000..e00dc420 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/TestDataACDLi18n/deOutOfDomain/document.json @@ -0,0 +1,18 @@ +{ + "type": "APLA", + "version": "0.8", + "mainTemplate": { + "parameters": ["payload"], + "item": { + "type": "Selector", + "strategy": "randomItem", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "Entschuldigung, ich verstehe Satheesh nicht" + } + ] + } + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/TestDataACDLi18n/deRequireMore/document.json b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/TestDataACDLi18n/deRequireMore/document.json new file mode 100644 index 00000000..3d7c5e01 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/TestDataACDLi18n/deRequireMore/document.json @@ -0,0 +1,19 @@ +{ + "type": "APLA", + "version": "0.8", + "mainTemplate": { + "parameters": ["payload"], + "item": { + "type": "Selector", + "strategy": "randomItem", + "items": [ + { + "description": "This template is emitted after we deny an API. Since we only have one, this is functionally equivalent to needing to request the city again.", + "type": "Speech", + "contentType": "text", + "content": "mehr benötigen satheesh" + } + ] + } + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/TestDataACDLi18n/deWelcome/document.json b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/TestDataACDLi18n/deWelcome/document.json new file mode 100644 index 00000000..9ba7f62f --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/TestDataACDLi18n/deWelcome/document.json @@ -0,0 +1,18 @@ +{ + "type": "APLA", + "version": "0.8", + "mainTemplate": { + "parameters": ["payload"], + "item": { + "type": "Selector", + "strategy": "randomItem", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "Willkommen meinen König Satheesh" + } + ] + } + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/conversations/ALexaPrize.acdl b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/conversations/ALexaPrize.acdl new file mode 100644 index 00000000..086efb02 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/conversations/ALexaPrize.acdl @@ -0,0 +1,203 @@ +namespace com.alexaprize + +import com.amazon.alexa.ask.conversations.Affirm +import com.amazon.alexa.ask.conversations.Deny +import com.amazon.alexa.ask.conversations.Invoke +import com.amazon.alexa.ask.conversations.Notify +import com.amazon.alexa.ask.conversations.Offer +import com.amazon.alexa.ask.conversations.expect +import com.amazon.alexa.ask.conversations.response +import com.amazon.alexa.ask.conversations.utterances +import com.amazon.alexa.schema.Boolean +import com.amazon.alexa.schema.Nothing +import com.amazon.alexa.schema.String +import com.amazon.ask.types.builtins.AMAZON.NUMBER +import prompts.alexa_prize_preconditions_apla +import slotTypes.TopicType + +type ConversationDetails { + optional TopicType Topic +} + +letsChatEvent = utterances( + samples = [ + "let's chat", + "i want to chat", + "chat", + "talk", + "let's chat about {Topic}", + "i want to talk about {Topic}", + "can we talk about {Topic}" + ] +) + +affirmEvent = utterances( + samples = [ + "yes", + "yup", + "yeah", + "sure", + "alright" + ] +) + +denyEvent = utterances( + samples = [ + "no", + "nope", + "not really", + "not", + "naah" + ] +) + +type AlexaPrizePreconditions { + NUMBER isLocaleSupported + NUMBER isDeviceSupported + NUMBER isFalseWake + NUMBER isSocialBotAvailable + NUMBER isAlexaPrizeEnabled + NUMBER isTopicBanned + String handoffPromptOverride +} + +type AlexaPrizePreconditionsPayload { + AlexaPrizePreconditions result +} + +type HandoffResults { + String handoffPromptOverride +} + +type HandoffResultsPayload { + HandoffResults result +} + +action AlexaPrizePreconditions checkPreconditionsAndHandoff(TopicType Topic = nothing) + +action HandoffResults intentConfirmedHandoff() + +action HandoffResults intentDeniedHandoff() + +dialog Nothing AlexaPrizeDialog() { + sample { + preconditionsResult = checkPrecondition() + isHandoffPossible = (((preconditionsResult.isDeviceSupported == 1 && preconditionsResult.isLocaleSupported == 1) && preconditionsResult.isSocialBotAvailable == 1) && preconditionsResult.isAlexaPrizeEnabled == 1) + if (isHandoffPossible) { + isConfirmationNeeded = (preconditionsResult.isFalseWake == 1 || preconditionsResult.isTopicBanned == 1) + responses( + isConfirmationNeeded = isConfirmationNeeded, + preconditionsResult = preconditionsResult + ) + } else { + response( + response = alexa_prize_preconditions_apla, + act = Notify { + actionName = checkPreconditionsAndHandoff, + success = false + }, + payload = AlexaPrizePreconditionsPayload { + result = preconditionsResult + } + ) + } + } +} + +dialog AlexaPrizePreconditions checkPrecondition() { + sample { + chatRequest = expect( + act = Invoke, + event = letsChatEvent + ) + checkPreconditionsAndHandoff( + Topic = chatRequest.Topic + ) + } + sample { + expect( + act = Invoke, + event = letsChatEvent + ) + preconditionsResult = checkPreconditionsAndHandoff() + } +} + +dialog Nothing responses(Boolean isConfirmationNeeded, AlexaPrizePreconditions preconditionsResult) { + sample { + if (isConfirmationNeeded) { + handoffResult( + preconditionsResult = preconditionsResult + ) + } else { + response( + response = alexa_prize_preconditions_apla, + act = Notify { + actionName = checkPreconditionsAndHandoff + }, + payload = AlexaPrizePreconditionsPayload { + result = preconditionsResult + } + ) + } + } +} + +dialog Nothing handoffResult(AlexaPrizePreconditions preconditionsResult) { + sample { + response( + response = alexa_prize_preconditions_apla, + act = Notify { + actionName = checkPreconditionsAndHandoff + }, + nextAct = Offer { + actionName = intentConfirmedHandoff + }, + payload = AlexaPrizePreconditionsPayload { + result = preconditionsResult + } + ) + expect( + act = Affirm, + event = affirmEvent + ) + handoffResults = intentConfirmedHandoff() + response( + response = alexa_prize_preconditions_apla, + act = Notify { + actionName = intentConfirmedHandoff + }, + payload = HandoffResultsPayload { + result = handoffResults + } + ) + } + sample { + response( + response = alexa_prize_preconditions_apla, + act = Notify { + actionName = checkPreconditionsAndHandoff + }, + nextAct = Offer { + actionName = intentDeniedHandoff + }, + payload = AlexaPrizePreconditionsPayload { + result = preconditionsResult + } + ) + expect( + act = Deny, + event = denyEvent + ) + handoffResults = intentDeniedHandoff() + response( + response = alexa_prize_preconditions_apla, + act = Notify { + actionName = intentDeniedHandoff + }, + payload = HandoffResultsPayload { + result = handoffResults + } + ) + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/conversations/Dialog_NonDeployable.acdl b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/conversations/Dialog_NonDeployable.acdl new file mode 100644 index 00000000..275632d7 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/conversations/Dialog_NonDeployable.acdl @@ -0,0 +1,81 @@ +namespace dialogs_non_deployable + +import apis.getEmployeeDetails +import com.amazon.alexa.ask.conversations.Inform +import com.amazon.alexa.ask.conversations.Request +import com.amazon.alexa.ask.conversations.expect +import com.amazon.alexa.ask.conversations.response +import com.amazon.ask.types.builtins.AMAZON.DATE +import com.amazon.ask.types.builtins.AMAZON.NUMBER +import prompts.request_dob_getDate_apla +import prompts.request_getEmploeeID_apla +import prompts.request_name_apla +import slotTypes.complexNames +import types.complexResult +import utteracesets.informComplexNameEvent +import utteracesets.informDOBEvent +import utteracesets.informEmployeeIDEvent + +dialog complexNames getName() { + sample { + response( + response = request_name_apla, + act = Request { + arguments = [ + getEmployeeDetails.arguments.name1 + ] + } + ) + complexNamesReturn = expect( + act = Inform, + event = informComplexNameEvent + ) + complexNamesReturn.name + } +} + +dialog NUMBER getEmploeeID() { + sample { + response( + response = request_getEmploeeID_apla, + act = Request { + arguments = [ + getEmployeeDetails.arguments.emplyee1id + ] + } + ) + empID = expect( + act = Inform, + event = informEmployeeIDEvent + ) + empID.emplyee1id + } +} + +dialog DATE getDate() { + sample { + response( + response = request_dob_getDate_apla, + act = Request { + arguments = [ + getEmployeeDetails.arguments.a_dateOfBirth + ] + } + ) + dobEvent = expect( + act = Inform, + event = informDOBEvent + ) + dobEvent.a_dateOfBirth + } +} + +dialog complexResult a_getEmployeeDetails(complexNames name1, NUMBER emplyee1id, DATE a_dateOfBirth) { + sample { + complexResultEvent = getEmployeeDetails( + name1 = name1, + emplyee1id = emplyee1id, + a_dateOfBirth = a_dateOfBirth + ) + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/conversations/Dialogs_reusableDialogsUsage_NonDeployableDialogs.acdl b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/conversations/Dialogs_reusableDialogsUsage_NonDeployableDialogs.acdl new file mode 100644 index 00000000..3132c271 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/conversations/Dialogs_reusableDialogsUsage_NonDeployableDialogs.acdl @@ -0,0 +1,50 @@ +namespace reusableDialogs.NonDeployableDialogs + +import apis.getEmployeeDetails +import com.amazon.alexa.ask.conversations.Invoke +import com.amazon.alexa.ask.conversations.Notify +import com.amazon.alexa.ask.conversations.expect +import com.amazon.alexa.ask.conversations.response +import com.amazon.alexa.schema.Nothing +import dialogs_non_deployable.a_getEmployeeDetails +import dialogs_non_deployable.getDate +import dialogs_non_deployable.getEmploeeID +import dialogs_non_deployable.getName +import prompts.getEmployeePosition_success_apla +import types.complexResult +import utteracesets.who_are_you +import slotTypes.* +import prompts.* +import displays.* +import com.amazon.ask.types.builtins.AMAZON.* +import com.amazon.alexa.schema.* +import com.amazon.alexa.ask.conversations.* +type PayLoadresult { + complexResult result +} + +dialog Nothing dilaog_getEmployeePosition() { + sample { + expect( + act = Invoke, + event = who_are_you + ) + complexNamesEvent = getName() + NUMBEREvent = getEmploeeID() + DATEEvent = getDate() + resultOne = a_getEmployeeDetails( + name1 = complexNamesEvent, + emplyee1id = NUMBEREvent, + a_dateOfBirth = DATEEvent + ) + response( + response = getEmployeePosition_success_apla, + act = Notify { + actionName = getEmployeeDetails + }, + payload = PayLoadresult { + result = resultOne + } + ) + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/conversations/Weather.acdl b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/conversations/Weather.acdl new file mode 100644 index 00000000..dea04349 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/conversations/Weather.acdl @@ -0,0 +1,152 @@ +namespace com.weatherbot + +import com.amazon.alexa.ask.conversations.Invoke +import com.amazon.alexa.ask.conversations.Notify +import com.amazon.alexa.ask.conversations.RequestArguments +import com.amazon.alexa.ask.conversations.ensure +import com.amazon.alexa.ask.conversations.expect +import com.amazon.alexa.ask.conversations.response +import com.amazon.alexa.ask.conversations.utterances +import com.amazon.alexa.schema.Nothing +import com.amazon.alexa.schema.Thing +import com.amazon.ask.types.builtins.AMAZON.DATE +import com.amazon.ask.types.builtins.AMAZON.NUMBER +import com.amazon.ask.types.builtins.AMAZON.US_CITY +import prompts.request_city_apla +import prompts.request_date_apla + +import slotTypes.* +import prompts.* +import displays.* +import com.amazon.ask.types.builtins.AMAZON.* +import com.amazon.alexa.schema.* +import com.amazon.alexa.ask.conversations.* + +type CityAndDate { + optional myCustomCities cityNameChanged + optional US_CITY cityName + optional DATE date +} + + +@locale(Locale.en_US) +getWeatherEvent_enUS = utterances( + samples = [ + "What's the weather {date} in {cityNameChanged}", + "What's the weather {date} in {cityName}", + "What is the weather {date} in {cityName}", + "what is the weather {date}", + "how is weather" + ] +) + + +@locale(Locale.de_DE) +getWeatherEvent_deDE = utterances( + samples = [ + "Wie ist das wetter {date} in {cityNameChanged}", + "wie ist das wetter {date} in {cityName}", + "wie ist das wetter {date}", + "wie ist das wetter" + ] +) + +getWeatherEvent = variations(getWeatherEvent_enUS,getWeatherEvent_deDE) + +@locale(Locale.en_US) +weather_apla_en = apla("../../skill-package/response/prompts/weather_apla") + +@locale(Locale.de_DE) +weather_apla_de = apla("../../skill-package/response/prompts/weather_apla_de_apla") + +weather_apla_apla_apla = variations(weather_apla_en,weather_apla_de) + + +type cityNameshell{ + US_CITY cityName +} + +@locale(Locale.en_US) +weather_apl_visual_en = apl("../../skill-package/response/display/confirm_weather_apla_display") + +@locale(Locale.de_DE) +weather_apl_visual_de = apl ("../../skill-package/response/display/display_de_apl") + +weather_apl_visual = variations(weather_apl_visual_en, weather_apl_visual_de) + +weather_apla_var = MultiModalResponse (apla = weather_apla_apla_apla, apl = weather_apl_visual) + +/* +what's the weather today in seattle +what is the weather today in madurai +what's the weather today in chennai +what's the weather today in speaker + +*/ + + + +type WeatherResult { + optional myCustomCities cityNameChanged + optional US_CITY cityName + NUMBER highTemp + NUMBER lowTemp +} + +type ResponsePayload { + WeatherResult weatherResult +} + +action WeatherResult getWeather(DATE date, US_CITY cityName = nothing, myCustomCities cityNameChanged = nothing) + +dialog Nothing Weather() { + sample { + weatherRequest = expect(act = Invoke,event = getWeatherEvent) + ensure( +requestArgs = [ + RequestArguments {arguments = [ getWeather.arguments.cityNameChanged],response = request_city_apla}, + RequestArguments {arguments = [ getWeather.arguments.cityName],response = request_city_apla}, + RequestArguments { arguments = [getWeather.arguments.date],response = request_date_apla} + ] + ) + weatherResult = getWeather(date = weatherRequest.date, cityName = weatherRequest.cityName) + response( + response = weather_apla_var, + act = Notify {actionName = getWeather}, + payload = ResponsePayload { weatherResult = weatherResult} + ) + } + + sample { + weatherRequest = expect(act = Invoke,event = getWeatherEvent) + ensure( +requestArgs = [ + RequestArguments {arguments = [ getWeather.arguments.cityNameChanged],response = request_city_apla}, + RequestArguments {arguments = [ getWeather.arguments.cityName],response = request_city_apla}, + RequestArguments { arguments = [getWeather.arguments.date],response = request_date_apla} + ] + ) + weatherResult = getWeather(date = weatherRequest.date, cityNameChanged = weatherRequest.cityNameChanged) + response( + response = weather_apla_var, + act = Notify {actionName = getWeather}, + payload = ResponsePayload { weatherResult = weatherResult} + ) + } +} + +dialog Nothing ComplexTest() { + sample { + Weather() + } +} + + + +type weatherRequestEvent0 { + optional myCustomCities cityNameChanged + optional US_CITY cityName + DATE date +} + + diff --git a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/conversations/apis.acdl b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/conversations/apis.acdl new file mode 100644 index 00000000..22e0beb9 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/conversations/apis.acdl @@ -0,0 +1,17 @@ +namespace apis + +import com.amazon.alexa.schema.Nothing +import com.amazon.ask.types.builtins.AMAZON.DATE +import com.amazon.ask.types.builtins.AMAZON.NUMBER +import slotTypes.complexNames +import slotTypes.signs +import types.complexResult +import types.result_one +import com.amazon.alexa.ask.conversations.* + +action Nothing secondEarthAPI() + +action result_one favColorSign_Name(complexNames name, signs sign = nothing) + + +action complexResult getEmployeeDetails(complexNames name1, NUMBER emplyee1id, DATE a_dateOfBirth = nothing) diff --git a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/conversations/apisNamepaceLambda.acdl b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/conversations/apisNamepaceLambda.acdl new file mode 100644 index 00000000..5fcdf369 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/conversations/apisNamepaceLambda.acdl @@ -0,0 +1,23 @@ +namespace com.weatherbot.apis + +import com.amazon.ask.types.builtins.AMAZON.Color +import com.amazon.ask.types.builtins.AMAZON.Food +import com.amazon.ask.types.builtins.AMAZON.NUMBER +import slotTypes.* + +type result { + Food fruitName + NUMBER price +} + +type payloadgetFruitPriceEvent { + result result +} + +action result fruitNameAPI(Food fruitName) + +action resultthree colorFruitName(myColors colorName) + +type resultthree { + Food fruitName +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/conversations/conversation_empty.acdl b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/conversations/conversation_empty.acdl new file mode 100644 index 00000000..4189bdda --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/conversations/conversation_empty.acdl @@ -0,0 +1,114 @@ +namespace com.numberbot + +import com.amazon.alexa.ask.conversations.APLA +import com.amazon.alexa.ask.conversations.Action +import com.amazon.alexa.ask.conversations.Bye +import com.amazon.alexa.ask.conversations.Invoke +import com.amazon.alexa.ask.conversations.Notify +import com.amazon.alexa.ask.conversations.Offer +import com.amazon.alexa.ask.conversations.RequestArguments +import com.amazon.alexa.ask.conversations.ensure +import com.amazon.alexa.ask.conversations.expect +import com.amazon.alexa.ask.conversations.response +import com.amazon.alexa.ask.conversations.utterances +import com.amazon.alexa.schema.Nothing +import com.amazon.alexa.schema.Number +import com.amazon.alexa.schema.Thing +import com.amazon.ask.types.builtins.AMAZON.NUMBER +import prompts.AlexaConversationsBye +import prompts.numericfeedback_apla +import prompts.rating_apla + +type NumPayload { + Number num +} + +type RatingRequest { + NUMBER rating +} + +InformRatingEvent = utterances( + samples = [ + "my score is {rating}", + "that was a {rating} conversation", + "i rate you a {rating}", + "{rating}" + ] +) + +getStart = utterances( + samples = [ + "give me a number please" + ] +) + +action Nothing saveRating(Number rating) + +action Number getNumber() + +dialog Nothing GetFeedback(APLA feedback_prompt, Number num, Action notifyAction) { + sample { + response( + response = feedback_prompt, + act = Notify { + actionName = notifyAction, + success = true + }, + nextAct = Offer { + actionName = saveRating, + arguments = [ + saveRating.arguments.rating + ] + }, + payload = NumPayload { + num = num + } + ) + myRating = expect( + act = Invoke, + event = InformRatingEvent + ) + ensure( + requestArgs = [ + RequestArguments { + arguments = [ + saveRating.arguments.rating + ], + response = rating_apla + } + ] + ) + saveRating( + rating = myRating.rating + ) + } +} + +dialog Number levelOne() { + sample { + expect( + act = Invoke, + event = getStart + ) + num = getNumber() + } +} + +dialog Nothing MainDialog() { + sample { + num = levelOne() + GetFeedback( + feedback_prompt = numericfeedback_apla, + num = num, + notifyAction = getNumber + ) + response( + response = AlexaConversationsBye, + act = Notify { + actionName = saveRating, + success = true + }, + nextAct = Bye {} + ) + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/conversations/fruitNameApi.acdl b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/conversations/fruitNameApi.acdl new file mode 100644 index 00000000..4664f2f2 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/conversations/fruitNameApi.acdl @@ -0,0 +1,34 @@ +namespace test + +import com.amazon.alexa.ask.conversations.utterances +import com.amazon.ask.types.builtins.AMAZON.Food + +type fruitNameShell { + Food fruitName +} + +type paylaodCompleFruit { + Food fruitName +} + +getFruitPriceEvent = utterances( + samples = [ + "what is the price of the fruit", + "what is the price of fruit" + ] +) + +informfruitNameEvent = utterances( + samples = [ + "{fruitName}", + "fruit name is {fruitName}", + "fruit is {fruitName}" + ] +) + +affirmFruitAPIEvent = utterances( + samples = [ + "uh huh", + "yup" + ] +) diff --git a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/conversations/separateConfig.acdl b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/conversations/separateConfig.acdl new file mode 100644 index 00000000..be06ae17 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/conversations/separateConfig.acdl @@ -0,0 +1,98 @@ +namespace configSkill + +import com.amazon.alexa.ask.conversations.skill +import com.amazon.alexa.ask.conversations.variations + +import com.amazon.alexa.ask.conversations.apla +import com.amazon.alexa.ask.conversations.apl +import com.amazon.alexa.ask.conversations.MultiModalResponse +import com.amazon.alexa.ask.conversations.Locale +import com.amazon.alexa.ask.conversations.locale +import com.amazon.alexa.ask.conversations.SkillLevelResponses +import com.amazon.alexa.ask.conversations.InvocationName + +import com.weatherbot.Weather +import soaACDl.sOA + +@locale(Locale.de_DE) +welcome_de = apla("../../skill-package/TestDataACDLi18n/deWelcome") + +@locale(Locale.en_US, Locale.de_DE) +welcome_en_apl_tap = apl("../../skill-package/response/display/confirm_city_apl_display") + +welcome_apl = variations(welcome_en_apl_tap) + +@locale(Locale.en_US) +welcome_en = apla("../../skill-package/response/prompts/AlexaConversationsWelcome") +combo_apla_welcome = variations( welcome_en , welcome_de) + + +@locale(Locale.en_US) +out_of_domain_en = apla("../../skill-package/response/prompts/AlexaConversationsOutOfDomain") +@locale(Locale.en_US) +bye_en = apla("../../skill-package/response/prompts/AlexaConversationsBye") +@locale(Locale.en_US) +reqmore_en = apla("../../skill-package/response/prompts/AlexaConversationsRequestMore") +@locale(Locale.en_US) +provide_help_en = apla("../../skill-package/response/prompts/AlexaConversationsProvideHelp") + + +@locale(Locale.es_US) +welcome_es_US = apla("../../skill-package/response/prompts/AlexaConversationsWelcome") +@locale(Locale.es_US) +out_of_domain_es_US = apla("../../skill-package/response/prompts/AlexaConversationsOutOfDomain") +@locale(Locale.es_US) +bye_es_US = apla("../../skill-package/response/prompts/AlexaConversationsBye") +@locale(Locale.es_US) +reqmore_es_US = apla("../../skill-package/response/prompts/AlexaConversationsRequestMore") +@locale(Locale.es_US) +provide_help_es_US = apla("../../skill-package/response/prompts/AlexaConversationsProvideHelp") + + + +@locale(Locale.de_DE) +out_of_domain_de = apla("../../skill-package/TestDataACDLi18n/deOutOfDomain") +out_of_domainResponse = variations(out_of_domain_en, out_of_domain_de, out_of_domain_es_US) + +@locale(Locale.de_DE) +bye_de = apla("../../skill-package/TestDataACDLi18n/deBye") +byeResponse = variations(bye_en, bye_de, bye_es_US) + +@locale(Locale.de_DE) +reqmore_de = apla("../../skill-package/TestDataACDLi18n/deRequireMore") +reqmoreResponse = variations(reqmore_en, reqmore_de, reqmore_es_US) + +@locale(Locale.de_DE) +provide_help_de = apla("../../skill-package/TestDataACDLi18n/deHelp") +provide_helpResponse = variations(provide_help_en, provide_help_de,provide_help_es_US ) + + +combo = MultiModalResponse {apla = combo_apla_welcome, apl = welcome_apl} + +a = skill( + locales = [Locale.es_US, Locale.de_DE], + dialogs = [Weather, sOA], + skillLevelResponses = SkillLevelResponses + { + welcome = combo + ,out_of_domain = out_of_domainResponse + ,bye = byeResponse + ,reqmore = reqmoreResponse + ,provide_help = provide_helpResponse + }, + invocationNames = [ InvocationName { + locale = Locale.en_US, + invocationName = "acdl weatherbot localized" + }, + InvocationName { + locale = Locale.en_GB, + invocationName = "acdl weatherbot localized" + }, + InvocationName { + locale = Locale.en_CA, + invocationName = "acdl weatherbot localized" + } + ] + +) + diff --git a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/conversations/soaDialog.acdl b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/conversations/soaDialog.acdl new file mode 100644 index 00000000..020b9f53 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/conversations/soaDialog.acdl @@ -0,0 +1,132 @@ +namespace soaACDl + +import com.amazon.alexa.ask.conversations.Affirm +import com.amazon.alexa.ask.conversations.ConfirmArgs +import com.amazon.alexa.ask.conversations.ConfirmAction +import com.weatherbot.apis.* +import com.amazon.alexa.ask.conversations.Invoke +import com.amazon.alexa.ask.conversations.Notify +import com.amazon.alexa.ask.conversations.Request +import com.amazon.alexa.ask.conversations.expect +//import com.amazon.alexa.ask.conversations.received +import com.amazon.alexa.ask.conversations.response +import com.amazon.alexa.ask.conversations.utterances +import types.* +import com.amazon.alexa.schema.String + +import com.weatherbot.apis.colorFruitName +import com.weatherbot.apis.fruitNameAPI +import com.weatherbot.apis.result +import prompts.confirm_color_for_fruit_apla +import prompts.request_colorName_multiple_apla +import prompts.success_fruitPriceAPI_apla +import prompts.request_city_apla +import slotTypes.* +import prompts.* +import displays.* +import com.amazon.ask.types.builtins.AMAZON.* +import com.amazon.alexa.schema.* +import com.amazon.alexa.ask.conversations.* + + + +type payloadMultipleDialogEvent { + resultthree result +} + +@locale(Locale.en_US) +MultipleDialogEvent_enUS = utterances( + samples = [ + "i want to buy a fruit" + ] +) +TRYTHI = MultipleDialogEvent_enUS + +@locale(Locale.de_DE, Locale.es_US) +MultipleDialogEvent_deDE = utterances( + samples = [ + "ich möchte eine frucht kaufen" + ] +) + +MultipleDialogEvent_temp = variations(TRYTHI) + +MultipleDialogEvent = variations(MultipleDialogEvent_temp, MultipleDialogEvent_deDE) + +@locale(Locale.en_US) +informColorMultipleEvent_enUS = utterances( + samples = [ + "{colorName}", + "color is {colorName}", + "color {colorName}" + ] +) +@locale(Locale.de_DE) +informColorMultipleEvent_deDE = utterances( + samples = [ + "{colorName}", + "farbe ist {colorName}", + "farbe {colorName}" + ] +) + + +informColorMultipleEvent = variations(informColorMultipleEvent_enUS, informColorMultipleEvent_deDE) + +affirmMultipleColorEvent = utterances( + samples = [ + "do it" + ] +) + + +type colorNameShell { + myColors colorName +} + + +type payloadsOAConfirmArgs { + myColors colorName +} + + + + +/* + +informColorMultipleEvent = utterances( + samples = [ + "{colorName}", + "color is {colorName}", + "color {colorName}" + ] +) + +dialog Nothing stagingAreaOne() { + sample { + expect(act = Invoke,event = MultipleDialogEvent) + response(response = request_colorName_multiple_apla,act = Request {arguments = [colorFruitName.arguments.colorName]}) + } +} + + +*/ + +//com.amazon.alexa.ask.conversations.response(response = request_colorName_multiple_apla, act = com.amazon.alexa.ask.conversations.Request {arguments = [colorFruitName.arguments.colorName]}) + +@locale(Locale.de_DE, Locale.en_US) +dialog Nothing sOA() { + //@locale(Locale.en_US) + sample { + expect(act = Invoke,event = MultipleDialogEvent) + response(response = request_colorName_multiple_apla,act = Request {arguments = [colorFruitName.arguments.colorName]}) + + colorEvent = expect(act = Inform,event = informColorMultipleEvent) + + resultEvent = colorFruitName(colorName = colorEvent.colorName) + response( response = success_colorFruitAPI_apla, act = Notify { actionName = colorFruitName}, + payload = payloadMultipleDialogEvent {result = resultEvent} + ) + } + +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/conversations/types.acdl b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/conversations/types.acdl new file mode 100644 index 00000000..439e8934 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/conversations/types.acdl @@ -0,0 +1,43 @@ +namespace types + +import com.amazon.ask.types.builtins.AMAZON.Color +import com.amazon.ask.types.builtins.AMAZON.DATE +import com.amazon.ask.types.builtins.AMAZON.Food +import com.amazon.ask.types.builtins.AMAZON.NUMBER +import slotTypes.complexNames +import slotTypes.position +import slotTypes.signs +import slotTypes.* + +type result_one { + Color colorName + complexNames name + signs sign +} + +type complexResult { + complexNames name1 + DATE a_dateOfBirth + NUMBER emplyee1id + position position +} + +type nameShell { + complexNames name +} + +type dobshell { + DATE a_dateOfBirth +} + +type employeeIDshell { + NUMBER emplyee1id +} + +type fruitNameShell { + Food fruitName +} +/ +type colorEvent0 { + myColors colorName +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/conversations/utteracesets.acdl b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/conversations/utteracesets.acdl new file mode 100644 index 00000000..5f8fe09b --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/conversations/utteracesets.acdl @@ -0,0 +1,82 @@ +namespace utteracesets + +import com.amazon.alexa.ask.conversations.utterances +import types.dobshell +import types.employeeIDshell +import types.fruitNameShell +import types.nameShell + +getFruitPriceEvent = utterances( + samples = [ + "what is the price of the fruit", + "what is the price of fruit" + ] +) + +affirmFruitAPIEvent = utterances( + samples = [ + "yeah" + ] +) + +informfruitNameEvent = utterances( + samples = [ + "{fruitName}", + "fruit name is {fruitName}", + "fruit is {fruitName}" + ] +) + +delegateToSkill = utterances( + samples = [ + "get me to paradise", + "take me to paradise" + ] +) + +getFavColorEvent = utterances( + samples = [ + "what is my favourite color", + "tell my favourite color" + ] +) + +affirmFavColorEvent = utterances( + samples = [ + "correct" + ] +) + +who_are_you = utterances( + samples = [ + "who are you", + "who is that", + "find his designation" + ] +) + +informComplexNameEvent = utterances( + samples = [ + "{name}", + "name is {name}", + "i am {name}" + ] +) + +informDOBEvent = utterances( + samples = [ + "date of birth is {a_dateOfBirth}", + "birth date is {a_dateOfBirth}" + ] +) + +informEmployeeIDEvent = utterances( + samples = [ + "employee i.d. is {emplyee1id}", + "employee identification is {emplyee1id}", + "identification is {emplyee1id}", + "employee id is {emplyee1id}", + "i.d. is {emplyee1id}", + "id is {emplyee1id}" + ] +) diff --git a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/interactionModels/custom/de-DE.json b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/interactionModels/custom/de-DE.json new file mode 100644 index 00000000..f9d930e7 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/interactionModels/custom/de-DE.json @@ -0,0 +1,919 @@ +{ + "interactionModel": { + "languageModel": { + "invocationName": "waka waka test skill", + "intents": [ + { + "name": "AMAZON.CancelIntent", + "samples": [] + }, + { + "name": "AMAZON.HelpIntent", + "samples": [] + }, + { + "name": "AMAZON.StopIntent", + "samples": [] + }, + { + "name": "GetWeatherIntent", + "samples": ["what is the weather", "how is the weather", "tell me the weather"] + }, + { + "name": "AMAZON.NavigateHomeIntent", + "samples": [] + }, + { + "name": "AMAZON.FallbackIntent", + "samples": [] + } + ], + "types": [ + { + "values": [ + { + "id": "movies", + "name": { + "value": "movies", + "synonyms": [] + } + }, + { + "id": "politics", + "name": { + "value": "politics", + "synonyms": [] + } + }, + { + "id": "sports", + "name": { + "value": "sports", + "synonyms": [] + } + }, + { + "id": "hobbies", + "name": { + "value": "hobbies", + "synonyms": [] + } + }, + { + "id": "astronomy", + "name": { + "value": "astronomy", + "synonyms": [] + } + }, + { + "id": "physics", + "name": { + "value": "physics", + "synonyms": [] + } + }, + { + "id": "los_angeles_dodgers", + "name": { + "value": "los angeles dodgers" + } + }, + { + "id": "president_emmanuel_macron", + "name": { + "value": "president emmanuel macron" + } + }, + { + "id": "emmanuel_macron", + "name": { + "value": "emmanuel macron" + } + }, + { + "id": "tax_cuts", + "name": { + "value": "tax cuts" + } + }, + { + "id": "middle_class", + "name": { + "value": "middle class" + } + }, + { + "id": "inequality_divide", + "name": { + "value": "inequality divide" + } + }, + { + "id": "wealth_inequality", + "name": { + "value": "wealth inequality" + } + }, + { + "id": "n._p._r.", + "name": { + "value": "n. p. r." + } + }, + { + "id": "president_trump", + "name": { + "value": "president trump" + } + }, + { + "id": "fox", + "name": { + "value": "fox" + } + }, + { + "id": "police_officers", + "name": { + "value": "police officers" + } + }, + { + "id": "jerome_hall", + "name": { + "value": "jerome hall" + } + }, + { + "id": "diversity_training_program", + "name": { + "value": "diversity training program" + } + }, + { + "id": "read_preble", + "name": { + "value": "read preble" + } + }, + { + "id": "christopher_preble", + "name": { + "value": "christopher preble" + } + }, + { + "id": "pacific_rim", + "name": { + "value": "pacific rim" + } + }, + { + "id": "washington_nationals", + "name": { + "value": "washington nationals" + } + }, + { + "id": "michael_cohen", + "name": { + "value": "michael cohen" + } + }, + { + "id": "john_wall", + "name": { + "value": "john wall" + } + }, + { + "id": "united_states", + "name": { + "value": "united states" + } + }, + { + "id": "washington_wizards", + "name": { + "value": "washington wizards" + } + }, + { + "id": "bryce_harper", + "name": { + "value": "bryce harper" + } + }, + { + "id": "capitals_playoff_hockey_capitals", + "name": { + "value": "capitals playoff hockey capitals" + } + }, + { + "id": "james_b._comey", + "name": { + "value": "james b. comey" + } + }, + { + "id": "mike_pompeo", + "name": { + "value": "mike pompeo" + } + }, + { + "id": "tom_toles", + "name": { + "value": "tom toles" + } + }, + { + "id": "white_house", + "name": { + "value": "white house" + } + }, + { + "id": "manny_machado", + "name": { + "value": "manny machado" + } + }, + { + "id": "national_league_east", + "name": { + "value": "national league east" + } + }, + { + "id": "otto_porter_jr._now", + "name": { + "value": "otto porter jr. now" + } + }, + { + "id": "hillary_clinton", + "name": { + "value": "hillary clinton" + } + }, + { + "id": "trea_turner", + "name": { + "value": "trea turner" + } + }, + { + "id": "max_scherzer", + "name": { + "value": "max scherzer" + } + }, + { + "id": "donald_trump", + "name": { + "value": "donald trump" + } + }, + { + "id": "bryce_harper_nationals", + "name": { + "value": "bryce harper nationals" + } + }, + { + "id": "michael_a._taylor", + "name": { + "value": "michael a. taylor" + } + }, + { + "id": "news_media", + "name": { + "value": "news media" + } + }, + { + "id": "conservative_political_action_conference", + "name": { + "value": "conservative political action conference" + } + }, + { + "id": "mainstream_media", + "name": { + "value": "mainstream media" + } + }, + { + "id": "baltimore_orioles", + "name": { + "value": "baltimore orioles" + } + }, + { + "id": "sean_hannity", + "name": { + "value": "sean hannity" + } + }, + { + "id": "privilege", + "name": { + "value": "privilege" + } + }, + { + "id": "sarah_hart", + "name": { + "value": "sarah hart" + } + }, + { + "id": "matt_kemp", + "name": { + "value": "matt kemp" + } + }, + { + "id": "stephen_strasburg", + "name": { + "value": "stephen strasburg" + } + }, + { + "id": "police_misconduct", + "name": { + "value": "police misconduct" + } + }, + { + "id": "sarah_huckabee_sanders", + "name": { + "value": "sarah huckabee sanders" + } + }, + { + "id": "washington_wizards_april", + "name": { + "value": "washington wizards april" + } + }, + { + "id": "environmental_protection_agency_administrator_scott_pruitt", + "name": { + "value": "environmental protection agency administrator scott pruitt" + } + }, + { + "id": "dodger_stadium", + "name": { + "value": "dodger stadium" + } + }, + { + "id": "environmental_protection_agency", + "name": { + "value": "environmental protection agency" + } + }, + { + "id": "barbara_bush", + "name": { + "value": "barbara bush" + } + }, + { + "id": "lewis_\"scooter\"_libby", + "name": { + "value": "lewis \"scooter\" libby" + } + }, + { + "id": "lewis_scooter_libby", + "name": { + "value": "lewis scooter libby" + } + }, + { + "id": "game_3._lowry", + "name": { + "value": "game 3. lowry" + } + }, + { + "id": "columbus_blue_jackets", + "name": { + "value": "columbus blue jackets" + } + }, + { + "id": "john_tortorella", + "name": { + "value": "john tortorella" + } + }, + { + "id": "george_w._bush", + "name": { + "value": "george w. bush" + } + }, + { + "id": "george_h.w._bush", + "name": { + "value": "george h.w. bush" + } + }, + { + "id": "jarrett_hurd", + "name": { + "value": "jarrett hurd" + } + }, + { + "id": "said_fred_hurd_sr.", + "name": { + "value": "said fred hurd sr." + } + }, + { + "id": "fred_hurd_sr.", + "name": { + "value": "fred hurd sr." + } + }, + { + "id": "san_antonio", + "name": { + "value": "san antonio" + } + }, + { + "id": "san_antonio_spurs", + "name": { + "value": "san antonio spurs" + } + }, + { + "id": "gregg_popovich", + "name": { + "value": "gregg popovich" + } + }, + { + "id": "kawhi_leonard", + "name": { + "value": "kawhi leonard" + } + }, + { + "id": "tim_bontemps_seth_jones", + "name": { + "value": "tim bontemps seth jones" + } + }, + { + "id": "consumer_sentiment_index", + "name": { + "value": "consumer sentiment index" + } + }, + { + "id": "pew_research_center", + "name": { + "value": "pew research center" + } + }, + { + "id": "conference_board_consumer_confidence_survey", + "name": { + "value": "conference board consumer confidence survey" + } + }, + { + "id": "speech_rights", + "name": { + "value": "speech rights" + } + }, + { + "id": "first_amendment", + "name": { + "value": "first amendment" + } + }, + { + "id": "golden_state", + "name": { + "value": "golden state" + } + }, + { + "id": "north_korea", + "name": { + "value": "north korea" + } + }, + { + "id": "woman_pilot", + "name": { + "value": "woman pilot" + } + }, + { + "id": "airline_pilot_population", + "name": { + "value": "airline pilot population" + } + }, + { + "id": "air_transport_pilot", + "name": { + "value": "air transport pilot" + } + }, + { + "id": "southwest_airlines", + "name": { + "value": "southwest airlines" + } + }, + { + "id": "democratic_national_committee", + "name": { + "value": "democratic national committee" + } + }, + { + "id": "senate_foreign_relations_committee", + "name": { + "value": "senate foreign relations committee" + } + }, + { + "id": "cia_director_mike_pompeo", + "name": { + "value": "cia director mike pompeo" + } + }, + { + "id": "playoff_overtime_games", + "name": { + "value": "playoff overtime games" + } + }, + { + "id": "lord_jesus", + "name": { + "value": "lord jesus" + } + }, + { + "id": "lgbtq_community", + "name": { + "value": "lgbtq community" + } + }, + { + "id": "health_and_human_services_department", + "name": { + "value": "health and human services department" + } + }, + { + "id": "group_prayer", + "name": { + "value": "group prayer" + } + }, + { + "id": "princess_charlotte_elizabeth_diana", + "name": { + "value": "princess charlotte elizabeth diana" + } + }, + { + "id": "term_war_economy", + "name": { + "value": "term war economy" + } + }, + { + "id": "melissa_kirk", + "name": { + "value": "melissa kirk" + } + }, + { + "id": "captain_america", + "name": { + "value": "captain america" + } + }, + { + "id": "draft_position", + "name": { + "value": "draft position" + } + }, + { + "id": "elysee_mbem-bosse", + "name": { + "value": "elysee mbem-bosse" + } + }, + { + "id": "water_crisis", + "name": { + "value": "water crisis" + } + }, + { + "id": "nationals_pitchers", + "name": { + "value": "nationals pitchers" + } + }, + { + "id": "sen._jennifer_t._wexton", + "name": { + "value": "sen. jennifer t. wexton" + } + }, + { + "id": "interest_rates", + "name": { + "value": "interest rates" + } + }, + { + "id": "town_crier", + "name": { + "value": "town crier" + } + }, + { + "id": "nancy_goes_millennial", + "name": { + "value": "nancy goes millennial" + } + }, + { + "id": "steve_rogers", + "name": { + "value": "steve rogers" + } + }, + { + "id": "game_3._lebron_james", + "name": { + "value": "game 3. lebron james" + } + }, + { + "id": "anthony_rendon", + "name": { + "value": "anthony rendon" + } + }, + { + "id": "buckingham_palace", + "name": { + "value": "buckingham palace" + } + }, + { + "id": "travis_reinking_suspected", + "name": { + "value": "travis reinking suspected" + } + }, + { + "id": "detroit_free_press", + "name": { + "value": "detroit free press" + } + }, + { + "id": "national_rifle_association", + "name": { + "value": "national rifle association" + } + }, + { + "id": "ed_harris", + "name": { + "value": "ed harris" + } + }, + { + "id": "overtime_playoff_games", + "name": { + "value": "overtime playoff games" + } + }, + { + "id": "republican_sen._bob_corker", + "name": { + "value": "republican sen. bob corker" + } + }, + { + "id": "electricity_sector_reforms", + "name": { + "value": "electricity sector reforms" + } + }, + { + "id": "baltimore_manager_buck_showalter", + "name": { + "value": "baltimore manager buck showalter" + } + }, + { + "id": "sen._joe_manchin_iii", + "name": { + "value": "sen. joe manchin iii" + } + }, + { + "id": "car_seat_belts", + "name": { + "value": "car seat belts" + } + }, + { + "id": "andrews_mcmeel.", + "name": { + "value": "andrews mcmeel." + } + }, + { + "id": "north_africa_program", + "name": { + "value": "north africa program" + } + }, + { + "id": "state_prosecutor_lobby", + "name": { + "value": "state prosecutor lobby" + } + }, + { + "id": "cape_town", + "name": { + "value": "cape town" + } + }, + { + "id": "data_privacy_law", + "name": { + "value": "data privacy law" + } + }, + { + "id": "president_trump_down", + "name": { + "value": "president trump down" + } + }, + { + "id": "christian_kirk", + "name": { + "value": "christian kirk" + } + }, + { + "id": "mitch_mcconnell", + "name": { + "value": "mitch mcconnell" + } + }, + { + "id": "federal_reserve", + "name": { + "value": "federal reserve" + } + } + ], + "name": "TopicType" + }, + { + "values": [ + { + "name": { + "value": "cancer" + } + }, + { + "name": { + "value": "scorpio" + } + }, + { + "name": { + "value": "scorpion" + } + } + ], + "name": "signs" + }, + { + "values": [ + { + "name": { + "value": "satheesh" + } + }, + { + "name": { + "value": "raman" + } + }, + { + "name": { + "value": "yadhu" + } + } + ], + "name": "complexNames" + }, + { + "values": [ + { + "name": { + "value": "tester" + } + }, + { + "name": { + "value": "engineer" + } + }, + { + "name": { + "value": "manager" + } + } + ], + "name": "position" + }, + { + "values": [ + { + "name": { + "value": "blue" + } + }, + { + "name": { + "value": "red" + } + }, + { + "name": { + "value": "rocket" + } + } + ], + "name": "myColors" + }, + { + "values": [ + { + "name": { + "value": "flower city" + } + }, + { + "name": { + "value": "temple city" + } + }, + { + "name": { + "value": "ramapuram" + } + }, + { + "name": { + "value": "guindy" + } + }, + { + "name": { + "value": "porur" + } + } + ], + "name": "myCustomCities" + } + ] + } + }, + "version": "18" +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/interactionModels/custom/en-US.json b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/interactionModels/custom/en-US.json new file mode 100644 index 00000000..f9d930e7 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/interactionModels/custom/en-US.json @@ -0,0 +1,919 @@ +{ + "interactionModel": { + "languageModel": { + "invocationName": "waka waka test skill", + "intents": [ + { + "name": "AMAZON.CancelIntent", + "samples": [] + }, + { + "name": "AMAZON.HelpIntent", + "samples": [] + }, + { + "name": "AMAZON.StopIntent", + "samples": [] + }, + { + "name": "GetWeatherIntent", + "samples": ["what is the weather", "how is the weather", "tell me the weather"] + }, + { + "name": "AMAZON.NavigateHomeIntent", + "samples": [] + }, + { + "name": "AMAZON.FallbackIntent", + "samples": [] + } + ], + "types": [ + { + "values": [ + { + "id": "movies", + "name": { + "value": "movies", + "synonyms": [] + } + }, + { + "id": "politics", + "name": { + "value": "politics", + "synonyms": [] + } + }, + { + "id": "sports", + "name": { + "value": "sports", + "synonyms": [] + } + }, + { + "id": "hobbies", + "name": { + "value": "hobbies", + "synonyms": [] + } + }, + { + "id": "astronomy", + "name": { + "value": "astronomy", + "synonyms": [] + } + }, + { + "id": "physics", + "name": { + "value": "physics", + "synonyms": [] + } + }, + { + "id": "los_angeles_dodgers", + "name": { + "value": "los angeles dodgers" + } + }, + { + "id": "president_emmanuel_macron", + "name": { + "value": "president emmanuel macron" + } + }, + { + "id": "emmanuel_macron", + "name": { + "value": "emmanuel macron" + } + }, + { + "id": "tax_cuts", + "name": { + "value": "tax cuts" + } + }, + { + "id": "middle_class", + "name": { + "value": "middle class" + } + }, + { + "id": "inequality_divide", + "name": { + "value": "inequality divide" + } + }, + { + "id": "wealth_inequality", + "name": { + "value": "wealth inequality" + } + }, + { + "id": "n._p._r.", + "name": { + "value": "n. p. r." + } + }, + { + "id": "president_trump", + "name": { + "value": "president trump" + } + }, + { + "id": "fox", + "name": { + "value": "fox" + } + }, + { + "id": "police_officers", + "name": { + "value": "police officers" + } + }, + { + "id": "jerome_hall", + "name": { + "value": "jerome hall" + } + }, + { + "id": "diversity_training_program", + "name": { + "value": "diversity training program" + } + }, + { + "id": "read_preble", + "name": { + "value": "read preble" + } + }, + { + "id": "christopher_preble", + "name": { + "value": "christopher preble" + } + }, + { + "id": "pacific_rim", + "name": { + "value": "pacific rim" + } + }, + { + "id": "washington_nationals", + "name": { + "value": "washington nationals" + } + }, + { + "id": "michael_cohen", + "name": { + "value": "michael cohen" + } + }, + { + "id": "john_wall", + "name": { + "value": "john wall" + } + }, + { + "id": "united_states", + "name": { + "value": "united states" + } + }, + { + "id": "washington_wizards", + "name": { + "value": "washington wizards" + } + }, + { + "id": "bryce_harper", + "name": { + "value": "bryce harper" + } + }, + { + "id": "capitals_playoff_hockey_capitals", + "name": { + "value": "capitals playoff hockey capitals" + } + }, + { + "id": "james_b._comey", + "name": { + "value": "james b. comey" + } + }, + { + "id": "mike_pompeo", + "name": { + "value": "mike pompeo" + } + }, + { + "id": "tom_toles", + "name": { + "value": "tom toles" + } + }, + { + "id": "white_house", + "name": { + "value": "white house" + } + }, + { + "id": "manny_machado", + "name": { + "value": "manny machado" + } + }, + { + "id": "national_league_east", + "name": { + "value": "national league east" + } + }, + { + "id": "otto_porter_jr._now", + "name": { + "value": "otto porter jr. now" + } + }, + { + "id": "hillary_clinton", + "name": { + "value": "hillary clinton" + } + }, + { + "id": "trea_turner", + "name": { + "value": "trea turner" + } + }, + { + "id": "max_scherzer", + "name": { + "value": "max scherzer" + } + }, + { + "id": "donald_trump", + "name": { + "value": "donald trump" + } + }, + { + "id": "bryce_harper_nationals", + "name": { + "value": "bryce harper nationals" + } + }, + { + "id": "michael_a._taylor", + "name": { + "value": "michael a. taylor" + } + }, + { + "id": "news_media", + "name": { + "value": "news media" + } + }, + { + "id": "conservative_political_action_conference", + "name": { + "value": "conservative political action conference" + } + }, + { + "id": "mainstream_media", + "name": { + "value": "mainstream media" + } + }, + { + "id": "baltimore_orioles", + "name": { + "value": "baltimore orioles" + } + }, + { + "id": "sean_hannity", + "name": { + "value": "sean hannity" + } + }, + { + "id": "privilege", + "name": { + "value": "privilege" + } + }, + { + "id": "sarah_hart", + "name": { + "value": "sarah hart" + } + }, + { + "id": "matt_kemp", + "name": { + "value": "matt kemp" + } + }, + { + "id": "stephen_strasburg", + "name": { + "value": "stephen strasburg" + } + }, + { + "id": "police_misconduct", + "name": { + "value": "police misconduct" + } + }, + { + "id": "sarah_huckabee_sanders", + "name": { + "value": "sarah huckabee sanders" + } + }, + { + "id": "washington_wizards_april", + "name": { + "value": "washington wizards april" + } + }, + { + "id": "environmental_protection_agency_administrator_scott_pruitt", + "name": { + "value": "environmental protection agency administrator scott pruitt" + } + }, + { + "id": "dodger_stadium", + "name": { + "value": "dodger stadium" + } + }, + { + "id": "environmental_protection_agency", + "name": { + "value": "environmental protection agency" + } + }, + { + "id": "barbara_bush", + "name": { + "value": "barbara bush" + } + }, + { + "id": "lewis_\"scooter\"_libby", + "name": { + "value": "lewis \"scooter\" libby" + } + }, + { + "id": "lewis_scooter_libby", + "name": { + "value": "lewis scooter libby" + } + }, + { + "id": "game_3._lowry", + "name": { + "value": "game 3. lowry" + } + }, + { + "id": "columbus_blue_jackets", + "name": { + "value": "columbus blue jackets" + } + }, + { + "id": "john_tortorella", + "name": { + "value": "john tortorella" + } + }, + { + "id": "george_w._bush", + "name": { + "value": "george w. bush" + } + }, + { + "id": "george_h.w._bush", + "name": { + "value": "george h.w. bush" + } + }, + { + "id": "jarrett_hurd", + "name": { + "value": "jarrett hurd" + } + }, + { + "id": "said_fred_hurd_sr.", + "name": { + "value": "said fred hurd sr." + } + }, + { + "id": "fred_hurd_sr.", + "name": { + "value": "fred hurd sr." + } + }, + { + "id": "san_antonio", + "name": { + "value": "san antonio" + } + }, + { + "id": "san_antonio_spurs", + "name": { + "value": "san antonio spurs" + } + }, + { + "id": "gregg_popovich", + "name": { + "value": "gregg popovich" + } + }, + { + "id": "kawhi_leonard", + "name": { + "value": "kawhi leonard" + } + }, + { + "id": "tim_bontemps_seth_jones", + "name": { + "value": "tim bontemps seth jones" + } + }, + { + "id": "consumer_sentiment_index", + "name": { + "value": "consumer sentiment index" + } + }, + { + "id": "pew_research_center", + "name": { + "value": "pew research center" + } + }, + { + "id": "conference_board_consumer_confidence_survey", + "name": { + "value": "conference board consumer confidence survey" + } + }, + { + "id": "speech_rights", + "name": { + "value": "speech rights" + } + }, + { + "id": "first_amendment", + "name": { + "value": "first amendment" + } + }, + { + "id": "golden_state", + "name": { + "value": "golden state" + } + }, + { + "id": "north_korea", + "name": { + "value": "north korea" + } + }, + { + "id": "woman_pilot", + "name": { + "value": "woman pilot" + } + }, + { + "id": "airline_pilot_population", + "name": { + "value": "airline pilot population" + } + }, + { + "id": "air_transport_pilot", + "name": { + "value": "air transport pilot" + } + }, + { + "id": "southwest_airlines", + "name": { + "value": "southwest airlines" + } + }, + { + "id": "democratic_national_committee", + "name": { + "value": "democratic national committee" + } + }, + { + "id": "senate_foreign_relations_committee", + "name": { + "value": "senate foreign relations committee" + } + }, + { + "id": "cia_director_mike_pompeo", + "name": { + "value": "cia director mike pompeo" + } + }, + { + "id": "playoff_overtime_games", + "name": { + "value": "playoff overtime games" + } + }, + { + "id": "lord_jesus", + "name": { + "value": "lord jesus" + } + }, + { + "id": "lgbtq_community", + "name": { + "value": "lgbtq community" + } + }, + { + "id": "health_and_human_services_department", + "name": { + "value": "health and human services department" + } + }, + { + "id": "group_prayer", + "name": { + "value": "group prayer" + } + }, + { + "id": "princess_charlotte_elizabeth_diana", + "name": { + "value": "princess charlotte elizabeth diana" + } + }, + { + "id": "term_war_economy", + "name": { + "value": "term war economy" + } + }, + { + "id": "melissa_kirk", + "name": { + "value": "melissa kirk" + } + }, + { + "id": "captain_america", + "name": { + "value": "captain america" + } + }, + { + "id": "draft_position", + "name": { + "value": "draft position" + } + }, + { + "id": "elysee_mbem-bosse", + "name": { + "value": "elysee mbem-bosse" + } + }, + { + "id": "water_crisis", + "name": { + "value": "water crisis" + } + }, + { + "id": "nationals_pitchers", + "name": { + "value": "nationals pitchers" + } + }, + { + "id": "sen._jennifer_t._wexton", + "name": { + "value": "sen. jennifer t. wexton" + } + }, + { + "id": "interest_rates", + "name": { + "value": "interest rates" + } + }, + { + "id": "town_crier", + "name": { + "value": "town crier" + } + }, + { + "id": "nancy_goes_millennial", + "name": { + "value": "nancy goes millennial" + } + }, + { + "id": "steve_rogers", + "name": { + "value": "steve rogers" + } + }, + { + "id": "game_3._lebron_james", + "name": { + "value": "game 3. lebron james" + } + }, + { + "id": "anthony_rendon", + "name": { + "value": "anthony rendon" + } + }, + { + "id": "buckingham_palace", + "name": { + "value": "buckingham palace" + } + }, + { + "id": "travis_reinking_suspected", + "name": { + "value": "travis reinking suspected" + } + }, + { + "id": "detroit_free_press", + "name": { + "value": "detroit free press" + } + }, + { + "id": "national_rifle_association", + "name": { + "value": "national rifle association" + } + }, + { + "id": "ed_harris", + "name": { + "value": "ed harris" + } + }, + { + "id": "overtime_playoff_games", + "name": { + "value": "overtime playoff games" + } + }, + { + "id": "republican_sen._bob_corker", + "name": { + "value": "republican sen. bob corker" + } + }, + { + "id": "electricity_sector_reforms", + "name": { + "value": "electricity sector reforms" + } + }, + { + "id": "baltimore_manager_buck_showalter", + "name": { + "value": "baltimore manager buck showalter" + } + }, + { + "id": "sen._joe_manchin_iii", + "name": { + "value": "sen. joe manchin iii" + } + }, + { + "id": "car_seat_belts", + "name": { + "value": "car seat belts" + } + }, + { + "id": "andrews_mcmeel.", + "name": { + "value": "andrews mcmeel." + } + }, + { + "id": "north_africa_program", + "name": { + "value": "north africa program" + } + }, + { + "id": "state_prosecutor_lobby", + "name": { + "value": "state prosecutor lobby" + } + }, + { + "id": "cape_town", + "name": { + "value": "cape town" + } + }, + { + "id": "data_privacy_law", + "name": { + "value": "data privacy law" + } + }, + { + "id": "president_trump_down", + "name": { + "value": "president trump down" + } + }, + { + "id": "christian_kirk", + "name": { + "value": "christian kirk" + } + }, + { + "id": "mitch_mcconnell", + "name": { + "value": "mitch mcconnell" + } + }, + { + "id": "federal_reserve", + "name": { + "value": "federal reserve" + } + } + ], + "name": "TopicType" + }, + { + "values": [ + { + "name": { + "value": "cancer" + } + }, + { + "name": { + "value": "scorpio" + } + }, + { + "name": { + "value": "scorpion" + } + } + ], + "name": "signs" + }, + { + "values": [ + { + "name": { + "value": "satheesh" + } + }, + { + "name": { + "value": "raman" + } + }, + { + "name": { + "value": "yadhu" + } + } + ], + "name": "complexNames" + }, + { + "values": [ + { + "name": { + "value": "tester" + } + }, + { + "name": { + "value": "engineer" + } + }, + { + "name": { + "value": "manager" + } + } + ], + "name": "position" + }, + { + "values": [ + { + "name": { + "value": "blue" + } + }, + { + "name": { + "value": "red" + } + }, + { + "name": { + "value": "rocket" + } + } + ], + "name": "myColors" + }, + { + "values": [ + { + "name": { + "value": "flower city" + } + }, + { + "name": { + "value": "temple city" + } + }, + { + "name": { + "value": "ramapuram" + } + }, + { + "name": { + "value": "guindy" + } + }, + { + "name": { + "value": "porur" + } + } + ], + "name": "myCustomCities" + } + ] + } + }, + "version": "18" +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/display/confirm_city_apl_display/document.json b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/display/confirm_city_apl_display/document.json new file mode 100644 index 00000000..6fea1ff7 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/display/confirm_city_apl_display/document.json @@ -0,0 +1,331 @@ +{ + "type": "APL", + "version": "1.1", + "settings": {}, + "theme": "dark", + "import": [ + { + "name": "alexa-layouts", + "version": "1.0.0" + } + ], + "resources": [ + { + "description": "Stock color for the light theme", + "colors": { + "colorTextPrimary": "#151920" + } + }, + { + "description": "Stock color for the dark theme", + "when": "${viewport.theme == 'dark'}", + "colors": { + "colorTextPrimary": "#f0f1ef" + } + }, + { + "description": "Standard font sizes", + "dimensions": { + "textSizeBody": 48, + "textSizePrimary": 27, + "textSizeSecondary": 23, + "textSizeDetails": 20, + "textSizeSecondaryHint": 25 + } + }, + { + "description": "Common spacing values", + "dimensions": { + "spacingThin": 6, + "spacingSmall": 12, + "spacingMedium": 24, + "spacingLarge": 48, + "spacingExtraLarge": 72 + } + }, + { + "description": "Common margins and padding", + "dimensions": { + "marginTop": 40, + "marginLeft": 60, + "marginRight": 60, + "marginBottom": 40 + } + } + ], + "styles": { + "textStyleBase": { + "description": "Base font description; set color", + "values": [ + { + "color": "@colorTextPrimary" + } + ] + }, + "textStyleBase0": { + "description": "Thin version of basic font", + "extend": "textStyleBase", + "values": { + "fontWeight": "100" + } + }, + "textStyleBase1": { + "description": "Light version of basic font", + "extend": "textStyleBase", + "values": { + "fontWeight": "300" + } + }, + "textStyleBase2": { + "description": "Regular version of basic font", + "extend": "textStyleBase", + "values": { + "fontWeight": "500" + } + }, + "mixinBody": { + "values": { + "fontSize": "@textSizeBody" + } + }, + "mixinPrimary": { + "values": { + "fontSize": "@textSizePrimary" + } + }, + "mixinDetails": { + "values": { + "fontSize": "@textSizeDetails" + } + }, + "mixinSecondary": { + "values": { + "fontSize": "@textSizeSecondary" + } + }, + "textStylePrimary": { + "extend": ["textStyleBase1", "mixinPrimary"] + }, + "textStyleSecondary": { + "extend": ["textStyleBase0", "mixinSecondary"] + }, + "textStyleBody": { + "extend": ["textStyleBase1", "mixinBody"] + }, + "textStyleSecondaryHint": { + "values": { + "fontFamily": "Bookerly", + "fontStyle": "italic", + "fontSize": "@textSizeSecondaryHint", + "color": "@colorTextPrimary" + } + }, + "textStyleDetails": { + "extend": ["textStyleBase2", "mixinDetails"] + } + }, + "onMount": [], + "graphics": {}, + "commands": {}, + "layouts": { + "ListTemplate1": { + "parameters": ["backgroundImage", "title", "logo", "hintText", "listData"], + "item": [ + { + "type": "Container", + "width": "100vw", + "height": "100vh", + "direction": "column", + "items": [ + { + "type": "Image", + "source": "${backgroundImage}", + "scale": "best-fill", + "width": "100vw", + "height": "100vh", + "position": "absolute" + }, + { + "type": "AlexaHeader", + "headerTitle": "${title}", + "headerAttributionImage": "${logo}" + }, + { + "type": "Sequence", + "grow": 1, + "height": "80vh", + "scrollDirection": "vertical", + "paddingLeft": "@marginLeft", + "paddingRight": "@marginRight", + "data": "${listData}", + "numbered": true, + "items": [ + { + "type": "VerticalListItem", + "image": "${data.image.sources[0].url}", + "primaryText": "${data.textContent.primaryText.text}", + "secondaryText": "${data.textContent.secondaryText.text}", + "tertiaryText": "${data.textContent.tertiaryText.text}" + } + ] + } + ] + } + ] + }, + "VerticalListItem": { + "parameters": ["primaryText", "secondaryText", "tertiaryText", "image"], + "item": [ + { + "when": "${viewport.shape == 'round'}", + "type": "Container", + "direction": "row", + "height": 200, + "width": 500, + "alignItems": "center", + "items": [ + { + "type": "Text", + "text": "${ordinal}", + "paddingBottom": "20dp", + "color": "white", + "spacing": "5dp" + }, + { + "type": "Image", + "when": "${image}", + "source": "${image}", + "height": 150, + "width": 150, + "spacing": 15, + "scale": "best-fit", + "align": "top" + }, + { + "type": "Container", + "direction": "column", + "spacing": 25, + "items": [ + { + "type": "Text", + "text": "${primaryText}", + "style": "textStyleDetail", + "grow": 1, + "shrink": 1, + "fontWeight": "300", + "maxLines": 1 + }, + { + "type": "Text", + "text": "${secondaryText}", + "style": "textStyleCaption", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + }, + { + "type": "Text", + "text": "${tertiaryText}", + "style": "textStyleDetails", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + } + ] + } + ] + }, + { + "type": "Container", + "direction": "row", + "height": 125, + "width": 800, + "alignItems": "center", + "items": [ + { + "type": "Text", + "text": "${ordinal}", + "paddingBottom": "20dp", + "color": "white", + "spacing": "5dp" + }, + { + "type": "Image", + "when": "${image}", + "source": "${image}", + "height": 100, + "width": 100, + "align": "top", + "spacing": 50, + "scale": "best-fit" + }, + { + "type": "Container", + "spacing": 30, + "direction": "column", + "items": [ + { + "type": "Text", + "text": "${primaryText}", + "style": "textStyleBody", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + }, + { + "type": "Text", + "text": "${secondaryText}", + "style": "textStyleDetails", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + } + ] + }, + { + "type": "Text", + "text": "${tertiaryText}", + "style": "textStyleBody", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "textAlign": "right", + "maxLines": 1 + } + ] + } + ] + } + }, + "mainTemplate": { + "parameters": ["payload"], + "item": [ + { + "type": "Container", + "id": "BookCabSimpleDialogAPL", + "items": [ + { + "type": "TouchWrapper", + "onPress": { + "type": "SendEvent", + "arguments": ["delegateToColtraneOld"] + }, + "item": { + "type": "Text", + "id": "BookCabSimpleDialogAPL", + "paddingTop": "100", + "paddingLeft": "100", + "color": "green", + "size": 50, + "text": "which city ?" + } + } + ] + } + ] + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/display/confirm_date_apl_display/document.json b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/display/confirm_date_apl_display/document.json new file mode 100644 index 00000000..d41ea236 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/display/confirm_date_apl_display/document.json @@ -0,0 +1,331 @@ +{ + "type": "APL", + "version": "1.1", + "settings": {}, + "theme": "dark", + "import": [ + { + "name": "alexa-layouts", + "version": "1.0.0" + } + ], + "resources": [ + { + "description": "Stock color for the light theme", + "colors": { + "colorTextPrimary": "#151920" + } + }, + { + "description": "Stock color for the dark theme", + "when": "${viewport.theme == 'dark'}", + "colors": { + "colorTextPrimary": "#f0f1ef" + } + }, + { + "description": "Standard font sizes", + "dimensions": { + "textSizeBody": 48, + "textSizePrimary": 27, + "textSizeSecondary": 23, + "textSizeDetails": 20, + "textSizeSecondaryHint": 25 + } + }, + { + "description": "Common spacing values", + "dimensions": { + "spacingThin": 6, + "spacingSmall": 12, + "spacingMedium": 24, + "spacingLarge": 48, + "spacingExtraLarge": 72 + } + }, + { + "description": "Common margins and padding", + "dimensions": { + "marginTop": 40, + "marginLeft": 60, + "marginRight": 60, + "marginBottom": 40 + } + } + ], + "styles": { + "textStyleBase": { + "description": "Base font description; set color", + "values": [ + { + "color": "@colorTextPrimary" + } + ] + }, + "textStyleBase0": { + "description": "Thin version of basic font", + "extend": "textStyleBase", + "values": { + "fontWeight": "100" + } + }, + "textStyleBase1": { + "description": "Light version of basic font", + "extend": "textStyleBase", + "values": { + "fontWeight": "300" + } + }, + "textStyleBase2": { + "description": "Regular version of basic font", + "extend": "textStyleBase", + "values": { + "fontWeight": "500" + } + }, + "mixinBody": { + "values": { + "fontSize": "@textSizeBody" + } + }, + "mixinPrimary": { + "values": { + "fontSize": "@textSizePrimary" + } + }, + "mixinDetails": { + "values": { + "fontSize": "@textSizeDetails" + } + }, + "mixinSecondary": { + "values": { + "fontSize": "@textSizeSecondary" + } + }, + "textStylePrimary": { + "extend": ["textStyleBase1", "mixinPrimary"] + }, + "textStyleSecondary": { + "extend": ["textStyleBase0", "mixinSecondary"] + }, + "textStyleBody": { + "extend": ["textStyleBase1", "mixinBody"] + }, + "textStyleSecondaryHint": { + "values": { + "fontFamily": "Bookerly", + "fontStyle": "italic", + "fontSize": "@textSizeSecondaryHint", + "color": "@colorTextPrimary" + } + }, + "textStyleDetails": { + "extend": ["textStyleBase2", "mixinDetails"] + } + }, + "onMount": [], + "graphics": {}, + "commands": {}, + "layouts": { + "ListTemplate1": { + "parameters": ["backgroundImage", "title", "logo", "hintText", "listData"], + "item": [ + { + "type": "Container", + "width": "100vw", + "height": "100vh", + "direction": "column", + "items": [ + { + "type": "Image", + "source": "${backgroundImage}", + "scale": "best-fill", + "width": "100vw", + "height": "100vh", + "position": "absolute" + }, + { + "type": "AlexaHeader", + "headerTitle": "${title}", + "headerAttributionImage": "${logo}" + }, + { + "type": "Sequence", + "grow": 1, + "height": "80vh", + "scrollDirection": "vertical", + "paddingLeft": "@marginLeft", + "paddingRight": "@marginRight", + "data": "${listData}", + "numbered": true, + "items": [ + { + "type": "VerticalListItem", + "image": "${data.image.sources[0].url}", + "primaryText": "${data.textContent.primaryText.text}", + "secondaryText": "${data.textContent.secondaryText.text}", + "tertiaryText": "${data.textContent.tertiaryText.text}" + } + ] + } + ] + } + ] + }, + "VerticalListItem": { + "parameters": ["primaryText", "secondaryText", "tertiaryText", "image"], + "item": [ + { + "when": "${viewport.shape == 'round'}", + "type": "Container", + "direction": "row", + "height": 200, + "width": 500, + "alignItems": "center", + "items": [ + { + "type": "Text", + "text": "${ordinal}", + "paddingBottom": "20dp", + "color": "white", + "spacing": "5dp" + }, + { + "type": "Image", + "when": "${image}", + "source": "${image}", + "height": 150, + "width": 150, + "spacing": 15, + "scale": "best-fit", + "align": "top" + }, + { + "type": "Container", + "direction": "column", + "spacing": 25, + "items": [ + { + "type": "Text", + "text": "${primaryText}", + "style": "textStyleDetail", + "grow": 1, + "shrink": 1, + "fontWeight": "300", + "maxLines": 1 + }, + { + "type": "Text", + "text": "${secondaryText}", + "style": "textStyleCaption", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + }, + { + "type": "Text", + "text": "${tertiaryText}", + "style": "textStyleDetails", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + } + ] + } + ] + }, + { + "type": "Container", + "direction": "row", + "height": 125, + "width": 800, + "alignItems": "center", + "items": [ + { + "type": "Text", + "text": "${ordinal}", + "paddingBottom": "20dp", + "color": "white", + "spacing": "5dp" + }, + { + "type": "Image", + "when": "${image}", + "source": "${image}", + "height": 100, + "width": 100, + "align": "top", + "spacing": 50, + "scale": "best-fit" + }, + { + "type": "Container", + "spacing": 30, + "direction": "column", + "items": [ + { + "type": "Text", + "text": "${primaryText}", + "style": "textStyleBody", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + }, + { + "type": "Text", + "text": "${secondaryText}", + "style": "textStyleDetails", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + } + ] + }, + { + "type": "Text", + "text": "${tertiaryText}", + "style": "textStyleBody", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "textAlign": "right", + "maxLines": 1 + } + ] + } + ] + } + }, + "mainTemplate": { + "parameters": ["payload"], + "item": [ + { + "type": "Container", + "id": "BookCabSimpleDialogAPL", + "items": [ + { + "type": "TouchWrapper", + "onPress": { + "type": "SendEvent", + "arguments": ["delegateToColtraneOld"] + }, + "item": { + "type": "Text", + "id": "BookCabSimpleDialogAPL", + "paddingTop": "100", + "paddingLeft": "100", + "color": "green", + "size": 50, + "text": "which date ?" + } + } + ] + } + ] + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/display/confirm_weather_apla_display/document.json b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/display/confirm_weather_apla_display/document.json new file mode 100644 index 00000000..3bcc0e4a --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/display/confirm_weather_apla_display/document.json @@ -0,0 +1,379 @@ +{ + "type": "APL", + "version": "1.1", + "settings": {}, + "theme": "dark", + "import": [ + { + "name": "alexa-layouts", + "version": "1.0.0" + } + ], + "resources": [ + { + "description": "Stock color for the light theme", + "colors": { + "colorTextPrimary": "#151920" + } + }, + { + "description": "Stock color for the dark theme", + "when": "${viewport.theme == 'dark'}", + "colors": { + "colorTextPrimary": "#f0f1ef" + } + }, + { + "description": "Standard font sizes", + "dimensions": { + "textSizeBody": 48, + "textSizePrimary": 27, + "textSizeSecondary": 23, + "textSizeDetails": 20, + "textSizeSecondaryHint": 25 + } + }, + { + "description": "Common spacing values", + "dimensions": { + "spacingThin": 6, + "spacingSmall": 12, + "spacingMedium": 24, + "spacingLarge": 48, + "spacingExtraLarge": 72 + } + }, + { + "description": "Common margins and padding", + "dimensions": { + "marginTop": 40, + "marginLeft": 60, + "marginRight": 60, + "marginBottom": 40 + } + } + ], + "styles": { + "textStyleBase": { + "description": "Base font description; set color", + "values": [ + { + "color": "@colorTextPrimary" + } + ] + }, + "textStyleBase0": { + "description": "Thin version of basic font", + "extend": "textStyleBase", + "values": { + "fontWeight": "100" + } + }, + "textStyleBase1": { + "description": "Light version of basic font", + "extend": "textStyleBase", + "values": { + "fontWeight": "300" + } + }, + "textStyleBase2": { + "description": "Regular version of basic font", + "extend": "textStyleBase", + "values": { + "fontWeight": "500" + } + }, + "mixinBody": { + "values": { + "fontSize": "@textSizeBody" + } + }, + "mixinPrimary": { + "values": { + "fontSize": "@textSizePrimary" + } + }, + "mixinDetails": { + "values": { + "fontSize": "@textSizeDetails" + } + }, + "mixinSecondary": { + "values": { + "fontSize": "@textSizeSecondary" + } + }, + "textStylePrimary": { + "extend": ["textStyleBase1", "mixinPrimary"] + }, + "textStyleSecondary": { + "extend": ["textStyleBase0", "mixinSecondary"] + }, + "textStyleBody": { + "extend": ["textStyleBase1", "mixinBody"] + }, + "textStyleSecondaryHint": { + "values": { + "fontFamily": "Bookerly", + "fontStyle": "italic", + "fontSize": "@textSizeSecondaryHint", + "color": "@colorTextPrimary" + } + }, + "textStyleDetails": { + "extend": ["textStyleBase2", "mixinDetails"] + } + }, + "onMount": [], + "graphics": {}, + "commands": {}, + "layouts": { + "ListTemplate1": { + "parameters": ["backgroundImage", "title", "logo", "hintText", "listData"], + "item": [ + { + "type": "Container", + "width": "100vw", + "height": "100vh", + "direction": "column", + "items": [ + { + "type": "Image", + "source": "${backgroundImage}", + "scale": "best-fill", + "width": "100vw", + "height": "100vh", + "position": "absolute" + }, + { + "type": "AlexaHeader", + "headerTitle": "${title}", + "headerAttributionImage": "${logo}" + }, + { + "type": "Sequence", + "grow": 1, + "height": "80vh", + "scrollDirection": "vertical", + "paddingLeft": "@marginLeft", + "paddingRight": "@marginRight", + "data": "${listData}", + "numbered": true, + "items": [ + { + "type": "VerticalListItem", + "image": "${data.image.sources[0].url}", + "primaryText": "${data.textContent.primaryText.text}", + "secondaryText": "${data.textContent.secondaryText.text}", + "tertiaryText": "${data.textContent.tertiaryText.text}" + } + ] + } + ] + } + ] + }, + "VerticalListItem": { + "parameters": ["primaryText", "secondaryText", "tertiaryText", "image"], + "item": [ + { + "when": "${viewport.shape == 'round'}", + "type": "Container", + "direction": "row", + "height": 200, + "width": 500, + "alignItems": "center", + "items": [ + { + "type": "Text", + "text": "${ordinal}", + "paddingBottom": "20dp", + "color": "white", + "spacing": "5dp" + }, + { + "type": "Image", + "when": "${image}", + "source": "${image}", + "height": 150, + "width": 150, + "spacing": 15, + "scale": "best-fit", + "align": "top" + }, + { + "type": "Container", + "direction": "column", + "spacing": 25, + "items": [ + { + "type": "Text", + "text": "${primaryText}", + "style": "textStyleDetail", + "grow": 1, + "shrink": 1, + "fontWeight": "300", + "maxLines": 1 + }, + { + "type": "Text", + "text": "${secondaryText}", + "style": "textStyleCaption", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + }, + { + "type": "Text", + "text": "${tertiaryText}", + "style": "textStyleDetails", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + } + ] + } + ] + }, + { + "type": "Container", + "direction": "row", + "height": 125, + "width": 800, + "alignItems": "center", + "items": [ + { + "type": "Text", + "text": "${ordinal}", + "paddingBottom": "20dp", + "color": "white", + "spacing": "5dp" + }, + { + "type": "Image", + "when": "${image}", + "source": "${image}", + "height": 100, + "width": 100, + "align": "top", + "spacing": 50, + "scale": "best-fit" + }, + { + "type": "Container", + "spacing": 30, + "direction": "column", + "items": [ + { + "type": "Text", + "text": "${primaryText}", + "style": "textStyleBody", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + }, + { + "type": "Text", + "text": "${secondaryText}", + "style": "textStyleDetails", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + } + ] + }, + { + "type": "Text", + "text": "${tertiaryText}", + "style": "textStyleBody", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "textAlign": "right", + "maxLines": 1 + } + ] + } + ] + } + }, + "mainTemplate": { + "parameters": ["payload"], + "item": [ + { + "type": "Container", + "id": "BookCabSimpleDialogAPL", + "items": [ + { + "type": "TouchWrapper", + "onPress": { + "type": "SendEvent", + "arguments": ["delegateToSkillNew"] + }, + "item": { + "type": "Text", + "id": "BookCabSimpleDialogAPL", + "paddingTop": "100", + "paddingLeft": "100", + "color": "green", + "size": 50, + "text": "delegateToSkillNew" + } + }, + { + "type": "TouchWrapper", + "onPress": { + "type": "SendEvent", + "arguments": ["delegateToSkillOld"] + }, + "item": { + "type": "Text", + "id": "BookCabSimpleDialogAPL", + "paddingTop": "100", + "paddingLeft": "100", + "color": "green", + "size": 50, + "text": "delegateToSkillOld" + } + }, + { + "type": "TouchWrapper", + "onPress": { + "type": "SendEvent", + "arguments": ["delegateToColtraneNew"] + }, + "item": { + "type": "Text", + "id": "BookCabSimpleDialogAPL", + "paddingTop": "100", + "paddingLeft": "100", + "color": "green", + "size": 50, + "text": "delegateToColtraneNew" + } + }, + { + "type": "TouchWrapper", + "onPress": { + "type": "SendEvent", + "arguments": ["delegateToColtraneOld"] + }, + "item": { + "type": "Text", + "id": "BookCabSimpleDialogAPL", + "paddingTop": "100", + "paddingLeft": "100", + "color": "green", + "size": 50, + "text": "delegateToColtraneOld" + } + } + ] + } + ] + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/display/display_de_apl/document.json b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/display/display_de_apl/document.json new file mode 100644 index 00000000..6fea1ff7 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/display/display_de_apl/document.json @@ -0,0 +1,331 @@ +{ + "type": "APL", + "version": "1.1", + "settings": {}, + "theme": "dark", + "import": [ + { + "name": "alexa-layouts", + "version": "1.0.0" + } + ], + "resources": [ + { + "description": "Stock color for the light theme", + "colors": { + "colorTextPrimary": "#151920" + } + }, + { + "description": "Stock color for the dark theme", + "when": "${viewport.theme == 'dark'}", + "colors": { + "colorTextPrimary": "#f0f1ef" + } + }, + { + "description": "Standard font sizes", + "dimensions": { + "textSizeBody": 48, + "textSizePrimary": 27, + "textSizeSecondary": 23, + "textSizeDetails": 20, + "textSizeSecondaryHint": 25 + } + }, + { + "description": "Common spacing values", + "dimensions": { + "spacingThin": 6, + "spacingSmall": 12, + "spacingMedium": 24, + "spacingLarge": 48, + "spacingExtraLarge": 72 + } + }, + { + "description": "Common margins and padding", + "dimensions": { + "marginTop": 40, + "marginLeft": 60, + "marginRight": 60, + "marginBottom": 40 + } + } + ], + "styles": { + "textStyleBase": { + "description": "Base font description; set color", + "values": [ + { + "color": "@colorTextPrimary" + } + ] + }, + "textStyleBase0": { + "description": "Thin version of basic font", + "extend": "textStyleBase", + "values": { + "fontWeight": "100" + } + }, + "textStyleBase1": { + "description": "Light version of basic font", + "extend": "textStyleBase", + "values": { + "fontWeight": "300" + } + }, + "textStyleBase2": { + "description": "Regular version of basic font", + "extend": "textStyleBase", + "values": { + "fontWeight": "500" + } + }, + "mixinBody": { + "values": { + "fontSize": "@textSizeBody" + } + }, + "mixinPrimary": { + "values": { + "fontSize": "@textSizePrimary" + } + }, + "mixinDetails": { + "values": { + "fontSize": "@textSizeDetails" + } + }, + "mixinSecondary": { + "values": { + "fontSize": "@textSizeSecondary" + } + }, + "textStylePrimary": { + "extend": ["textStyleBase1", "mixinPrimary"] + }, + "textStyleSecondary": { + "extend": ["textStyleBase0", "mixinSecondary"] + }, + "textStyleBody": { + "extend": ["textStyleBase1", "mixinBody"] + }, + "textStyleSecondaryHint": { + "values": { + "fontFamily": "Bookerly", + "fontStyle": "italic", + "fontSize": "@textSizeSecondaryHint", + "color": "@colorTextPrimary" + } + }, + "textStyleDetails": { + "extend": ["textStyleBase2", "mixinDetails"] + } + }, + "onMount": [], + "graphics": {}, + "commands": {}, + "layouts": { + "ListTemplate1": { + "parameters": ["backgroundImage", "title", "logo", "hintText", "listData"], + "item": [ + { + "type": "Container", + "width": "100vw", + "height": "100vh", + "direction": "column", + "items": [ + { + "type": "Image", + "source": "${backgroundImage}", + "scale": "best-fill", + "width": "100vw", + "height": "100vh", + "position": "absolute" + }, + { + "type": "AlexaHeader", + "headerTitle": "${title}", + "headerAttributionImage": "${logo}" + }, + { + "type": "Sequence", + "grow": 1, + "height": "80vh", + "scrollDirection": "vertical", + "paddingLeft": "@marginLeft", + "paddingRight": "@marginRight", + "data": "${listData}", + "numbered": true, + "items": [ + { + "type": "VerticalListItem", + "image": "${data.image.sources[0].url}", + "primaryText": "${data.textContent.primaryText.text}", + "secondaryText": "${data.textContent.secondaryText.text}", + "tertiaryText": "${data.textContent.tertiaryText.text}" + } + ] + } + ] + } + ] + }, + "VerticalListItem": { + "parameters": ["primaryText", "secondaryText", "tertiaryText", "image"], + "item": [ + { + "when": "${viewport.shape == 'round'}", + "type": "Container", + "direction": "row", + "height": 200, + "width": 500, + "alignItems": "center", + "items": [ + { + "type": "Text", + "text": "${ordinal}", + "paddingBottom": "20dp", + "color": "white", + "spacing": "5dp" + }, + { + "type": "Image", + "when": "${image}", + "source": "${image}", + "height": 150, + "width": 150, + "spacing": 15, + "scale": "best-fit", + "align": "top" + }, + { + "type": "Container", + "direction": "column", + "spacing": 25, + "items": [ + { + "type": "Text", + "text": "${primaryText}", + "style": "textStyleDetail", + "grow": 1, + "shrink": 1, + "fontWeight": "300", + "maxLines": 1 + }, + { + "type": "Text", + "text": "${secondaryText}", + "style": "textStyleCaption", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + }, + { + "type": "Text", + "text": "${tertiaryText}", + "style": "textStyleDetails", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + } + ] + } + ] + }, + { + "type": "Container", + "direction": "row", + "height": 125, + "width": 800, + "alignItems": "center", + "items": [ + { + "type": "Text", + "text": "${ordinal}", + "paddingBottom": "20dp", + "color": "white", + "spacing": "5dp" + }, + { + "type": "Image", + "when": "${image}", + "source": "${image}", + "height": 100, + "width": 100, + "align": "top", + "spacing": 50, + "scale": "best-fit" + }, + { + "type": "Container", + "spacing": 30, + "direction": "column", + "items": [ + { + "type": "Text", + "text": "${primaryText}", + "style": "textStyleBody", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + }, + { + "type": "Text", + "text": "${secondaryText}", + "style": "textStyleDetails", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + } + ] + }, + { + "type": "Text", + "text": "${tertiaryText}", + "style": "textStyleBody", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "textAlign": "right", + "maxLines": 1 + } + ] + } + ] + } + }, + "mainTemplate": { + "parameters": ["payload"], + "item": [ + { + "type": "Container", + "id": "BookCabSimpleDialogAPL", + "items": [ + { + "type": "TouchWrapper", + "onPress": { + "type": "SendEvent", + "arguments": ["delegateToColtraneOld"] + }, + "item": { + "type": "Text", + "id": "BookCabSimpleDialogAPL", + "paddingTop": "100", + "paddingLeft": "100", + "color": "green", + "size": 50, + "text": "which city ?" + } + } + ] + } + ] + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/display/request_city_apl_display/document.json b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/display/request_city_apl_display/document.json new file mode 100644 index 00000000..6fea1ff7 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/display/request_city_apl_display/document.json @@ -0,0 +1,331 @@ +{ + "type": "APL", + "version": "1.1", + "settings": {}, + "theme": "dark", + "import": [ + { + "name": "alexa-layouts", + "version": "1.0.0" + } + ], + "resources": [ + { + "description": "Stock color for the light theme", + "colors": { + "colorTextPrimary": "#151920" + } + }, + { + "description": "Stock color for the dark theme", + "when": "${viewport.theme == 'dark'}", + "colors": { + "colorTextPrimary": "#f0f1ef" + } + }, + { + "description": "Standard font sizes", + "dimensions": { + "textSizeBody": 48, + "textSizePrimary": 27, + "textSizeSecondary": 23, + "textSizeDetails": 20, + "textSizeSecondaryHint": 25 + } + }, + { + "description": "Common spacing values", + "dimensions": { + "spacingThin": 6, + "spacingSmall": 12, + "spacingMedium": 24, + "spacingLarge": 48, + "spacingExtraLarge": 72 + } + }, + { + "description": "Common margins and padding", + "dimensions": { + "marginTop": 40, + "marginLeft": 60, + "marginRight": 60, + "marginBottom": 40 + } + } + ], + "styles": { + "textStyleBase": { + "description": "Base font description; set color", + "values": [ + { + "color": "@colorTextPrimary" + } + ] + }, + "textStyleBase0": { + "description": "Thin version of basic font", + "extend": "textStyleBase", + "values": { + "fontWeight": "100" + } + }, + "textStyleBase1": { + "description": "Light version of basic font", + "extend": "textStyleBase", + "values": { + "fontWeight": "300" + } + }, + "textStyleBase2": { + "description": "Regular version of basic font", + "extend": "textStyleBase", + "values": { + "fontWeight": "500" + } + }, + "mixinBody": { + "values": { + "fontSize": "@textSizeBody" + } + }, + "mixinPrimary": { + "values": { + "fontSize": "@textSizePrimary" + } + }, + "mixinDetails": { + "values": { + "fontSize": "@textSizeDetails" + } + }, + "mixinSecondary": { + "values": { + "fontSize": "@textSizeSecondary" + } + }, + "textStylePrimary": { + "extend": ["textStyleBase1", "mixinPrimary"] + }, + "textStyleSecondary": { + "extend": ["textStyleBase0", "mixinSecondary"] + }, + "textStyleBody": { + "extend": ["textStyleBase1", "mixinBody"] + }, + "textStyleSecondaryHint": { + "values": { + "fontFamily": "Bookerly", + "fontStyle": "italic", + "fontSize": "@textSizeSecondaryHint", + "color": "@colorTextPrimary" + } + }, + "textStyleDetails": { + "extend": ["textStyleBase2", "mixinDetails"] + } + }, + "onMount": [], + "graphics": {}, + "commands": {}, + "layouts": { + "ListTemplate1": { + "parameters": ["backgroundImage", "title", "logo", "hintText", "listData"], + "item": [ + { + "type": "Container", + "width": "100vw", + "height": "100vh", + "direction": "column", + "items": [ + { + "type": "Image", + "source": "${backgroundImage}", + "scale": "best-fill", + "width": "100vw", + "height": "100vh", + "position": "absolute" + }, + { + "type": "AlexaHeader", + "headerTitle": "${title}", + "headerAttributionImage": "${logo}" + }, + { + "type": "Sequence", + "grow": 1, + "height": "80vh", + "scrollDirection": "vertical", + "paddingLeft": "@marginLeft", + "paddingRight": "@marginRight", + "data": "${listData}", + "numbered": true, + "items": [ + { + "type": "VerticalListItem", + "image": "${data.image.sources[0].url}", + "primaryText": "${data.textContent.primaryText.text}", + "secondaryText": "${data.textContent.secondaryText.text}", + "tertiaryText": "${data.textContent.tertiaryText.text}" + } + ] + } + ] + } + ] + }, + "VerticalListItem": { + "parameters": ["primaryText", "secondaryText", "tertiaryText", "image"], + "item": [ + { + "when": "${viewport.shape == 'round'}", + "type": "Container", + "direction": "row", + "height": 200, + "width": 500, + "alignItems": "center", + "items": [ + { + "type": "Text", + "text": "${ordinal}", + "paddingBottom": "20dp", + "color": "white", + "spacing": "5dp" + }, + { + "type": "Image", + "when": "${image}", + "source": "${image}", + "height": 150, + "width": 150, + "spacing": 15, + "scale": "best-fit", + "align": "top" + }, + { + "type": "Container", + "direction": "column", + "spacing": 25, + "items": [ + { + "type": "Text", + "text": "${primaryText}", + "style": "textStyleDetail", + "grow": 1, + "shrink": 1, + "fontWeight": "300", + "maxLines": 1 + }, + { + "type": "Text", + "text": "${secondaryText}", + "style": "textStyleCaption", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + }, + { + "type": "Text", + "text": "${tertiaryText}", + "style": "textStyleDetails", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + } + ] + } + ] + }, + { + "type": "Container", + "direction": "row", + "height": 125, + "width": 800, + "alignItems": "center", + "items": [ + { + "type": "Text", + "text": "${ordinal}", + "paddingBottom": "20dp", + "color": "white", + "spacing": "5dp" + }, + { + "type": "Image", + "when": "${image}", + "source": "${image}", + "height": 100, + "width": 100, + "align": "top", + "spacing": 50, + "scale": "best-fit" + }, + { + "type": "Container", + "spacing": 30, + "direction": "column", + "items": [ + { + "type": "Text", + "text": "${primaryText}", + "style": "textStyleBody", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + }, + { + "type": "Text", + "text": "${secondaryText}", + "style": "textStyleDetails", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + } + ] + }, + { + "type": "Text", + "text": "${tertiaryText}", + "style": "textStyleBody", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "textAlign": "right", + "maxLines": 1 + } + ] + } + ] + } + }, + "mainTemplate": { + "parameters": ["payload"], + "item": [ + { + "type": "Container", + "id": "BookCabSimpleDialogAPL", + "items": [ + { + "type": "TouchWrapper", + "onPress": { + "type": "SendEvent", + "arguments": ["delegateToColtraneOld"] + }, + "item": { + "type": "Text", + "id": "BookCabSimpleDialogAPL", + "paddingTop": "100", + "paddingLeft": "100", + "color": "green", + "size": 50, + "text": "which city ?" + } + } + ] + } + ] + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/display/request_date_apl_display/document.json b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/display/request_date_apl_display/document.json new file mode 100644 index 00000000..d41ea236 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/display/request_date_apl_display/document.json @@ -0,0 +1,331 @@ +{ + "type": "APL", + "version": "1.1", + "settings": {}, + "theme": "dark", + "import": [ + { + "name": "alexa-layouts", + "version": "1.0.0" + } + ], + "resources": [ + { + "description": "Stock color for the light theme", + "colors": { + "colorTextPrimary": "#151920" + } + }, + { + "description": "Stock color for the dark theme", + "when": "${viewport.theme == 'dark'}", + "colors": { + "colorTextPrimary": "#f0f1ef" + } + }, + { + "description": "Standard font sizes", + "dimensions": { + "textSizeBody": 48, + "textSizePrimary": 27, + "textSizeSecondary": 23, + "textSizeDetails": 20, + "textSizeSecondaryHint": 25 + } + }, + { + "description": "Common spacing values", + "dimensions": { + "spacingThin": 6, + "spacingSmall": 12, + "spacingMedium": 24, + "spacingLarge": 48, + "spacingExtraLarge": 72 + } + }, + { + "description": "Common margins and padding", + "dimensions": { + "marginTop": 40, + "marginLeft": 60, + "marginRight": 60, + "marginBottom": 40 + } + } + ], + "styles": { + "textStyleBase": { + "description": "Base font description; set color", + "values": [ + { + "color": "@colorTextPrimary" + } + ] + }, + "textStyleBase0": { + "description": "Thin version of basic font", + "extend": "textStyleBase", + "values": { + "fontWeight": "100" + } + }, + "textStyleBase1": { + "description": "Light version of basic font", + "extend": "textStyleBase", + "values": { + "fontWeight": "300" + } + }, + "textStyleBase2": { + "description": "Regular version of basic font", + "extend": "textStyleBase", + "values": { + "fontWeight": "500" + } + }, + "mixinBody": { + "values": { + "fontSize": "@textSizeBody" + } + }, + "mixinPrimary": { + "values": { + "fontSize": "@textSizePrimary" + } + }, + "mixinDetails": { + "values": { + "fontSize": "@textSizeDetails" + } + }, + "mixinSecondary": { + "values": { + "fontSize": "@textSizeSecondary" + } + }, + "textStylePrimary": { + "extend": ["textStyleBase1", "mixinPrimary"] + }, + "textStyleSecondary": { + "extend": ["textStyleBase0", "mixinSecondary"] + }, + "textStyleBody": { + "extend": ["textStyleBase1", "mixinBody"] + }, + "textStyleSecondaryHint": { + "values": { + "fontFamily": "Bookerly", + "fontStyle": "italic", + "fontSize": "@textSizeSecondaryHint", + "color": "@colorTextPrimary" + } + }, + "textStyleDetails": { + "extend": ["textStyleBase2", "mixinDetails"] + } + }, + "onMount": [], + "graphics": {}, + "commands": {}, + "layouts": { + "ListTemplate1": { + "parameters": ["backgroundImage", "title", "logo", "hintText", "listData"], + "item": [ + { + "type": "Container", + "width": "100vw", + "height": "100vh", + "direction": "column", + "items": [ + { + "type": "Image", + "source": "${backgroundImage}", + "scale": "best-fill", + "width": "100vw", + "height": "100vh", + "position": "absolute" + }, + { + "type": "AlexaHeader", + "headerTitle": "${title}", + "headerAttributionImage": "${logo}" + }, + { + "type": "Sequence", + "grow": 1, + "height": "80vh", + "scrollDirection": "vertical", + "paddingLeft": "@marginLeft", + "paddingRight": "@marginRight", + "data": "${listData}", + "numbered": true, + "items": [ + { + "type": "VerticalListItem", + "image": "${data.image.sources[0].url}", + "primaryText": "${data.textContent.primaryText.text}", + "secondaryText": "${data.textContent.secondaryText.text}", + "tertiaryText": "${data.textContent.tertiaryText.text}" + } + ] + } + ] + } + ] + }, + "VerticalListItem": { + "parameters": ["primaryText", "secondaryText", "tertiaryText", "image"], + "item": [ + { + "when": "${viewport.shape == 'round'}", + "type": "Container", + "direction": "row", + "height": 200, + "width": 500, + "alignItems": "center", + "items": [ + { + "type": "Text", + "text": "${ordinal}", + "paddingBottom": "20dp", + "color": "white", + "spacing": "5dp" + }, + { + "type": "Image", + "when": "${image}", + "source": "${image}", + "height": 150, + "width": 150, + "spacing": 15, + "scale": "best-fit", + "align": "top" + }, + { + "type": "Container", + "direction": "column", + "spacing": 25, + "items": [ + { + "type": "Text", + "text": "${primaryText}", + "style": "textStyleDetail", + "grow": 1, + "shrink": 1, + "fontWeight": "300", + "maxLines": 1 + }, + { + "type": "Text", + "text": "${secondaryText}", + "style": "textStyleCaption", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + }, + { + "type": "Text", + "text": "${tertiaryText}", + "style": "textStyleDetails", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + } + ] + } + ] + }, + { + "type": "Container", + "direction": "row", + "height": 125, + "width": 800, + "alignItems": "center", + "items": [ + { + "type": "Text", + "text": "${ordinal}", + "paddingBottom": "20dp", + "color": "white", + "spacing": "5dp" + }, + { + "type": "Image", + "when": "${image}", + "source": "${image}", + "height": 100, + "width": 100, + "align": "top", + "spacing": 50, + "scale": "best-fit" + }, + { + "type": "Container", + "spacing": 30, + "direction": "column", + "items": [ + { + "type": "Text", + "text": "${primaryText}", + "style": "textStyleBody", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + }, + { + "type": "Text", + "text": "${secondaryText}", + "style": "textStyleDetails", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + } + ] + }, + { + "type": "Text", + "text": "${tertiaryText}", + "style": "textStyleBody", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "textAlign": "right", + "maxLines": 1 + } + ] + } + ] + } + }, + "mainTemplate": { + "parameters": ["payload"], + "item": [ + { + "type": "Container", + "id": "BookCabSimpleDialogAPL", + "items": [ + { + "type": "TouchWrapper", + "onPress": { + "type": "SendEvent", + "arguments": ["delegateToColtraneOld"] + }, + "item": { + "type": "Text", + "id": "BookCabSimpleDialogAPL", + "paddingTop": "100", + "paddingLeft": "100", + "color": "green", + "size": 50, + "text": "which date ?" + } + } + ] + } + ] + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/display/weather_success_apl_display/document.json b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/display/weather_success_apl_display/document.json new file mode 100644 index 00000000..3bcc0e4a --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/display/weather_success_apl_display/document.json @@ -0,0 +1,379 @@ +{ + "type": "APL", + "version": "1.1", + "settings": {}, + "theme": "dark", + "import": [ + { + "name": "alexa-layouts", + "version": "1.0.0" + } + ], + "resources": [ + { + "description": "Stock color for the light theme", + "colors": { + "colorTextPrimary": "#151920" + } + }, + { + "description": "Stock color for the dark theme", + "when": "${viewport.theme == 'dark'}", + "colors": { + "colorTextPrimary": "#f0f1ef" + } + }, + { + "description": "Standard font sizes", + "dimensions": { + "textSizeBody": 48, + "textSizePrimary": 27, + "textSizeSecondary": 23, + "textSizeDetails": 20, + "textSizeSecondaryHint": 25 + } + }, + { + "description": "Common spacing values", + "dimensions": { + "spacingThin": 6, + "spacingSmall": 12, + "spacingMedium": 24, + "spacingLarge": 48, + "spacingExtraLarge": 72 + } + }, + { + "description": "Common margins and padding", + "dimensions": { + "marginTop": 40, + "marginLeft": 60, + "marginRight": 60, + "marginBottom": 40 + } + } + ], + "styles": { + "textStyleBase": { + "description": "Base font description; set color", + "values": [ + { + "color": "@colorTextPrimary" + } + ] + }, + "textStyleBase0": { + "description": "Thin version of basic font", + "extend": "textStyleBase", + "values": { + "fontWeight": "100" + } + }, + "textStyleBase1": { + "description": "Light version of basic font", + "extend": "textStyleBase", + "values": { + "fontWeight": "300" + } + }, + "textStyleBase2": { + "description": "Regular version of basic font", + "extend": "textStyleBase", + "values": { + "fontWeight": "500" + } + }, + "mixinBody": { + "values": { + "fontSize": "@textSizeBody" + } + }, + "mixinPrimary": { + "values": { + "fontSize": "@textSizePrimary" + } + }, + "mixinDetails": { + "values": { + "fontSize": "@textSizeDetails" + } + }, + "mixinSecondary": { + "values": { + "fontSize": "@textSizeSecondary" + } + }, + "textStylePrimary": { + "extend": ["textStyleBase1", "mixinPrimary"] + }, + "textStyleSecondary": { + "extend": ["textStyleBase0", "mixinSecondary"] + }, + "textStyleBody": { + "extend": ["textStyleBase1", "mixinBody"] + }, + "textStyleSecondaryHint": { + "values": { + "fontFamily": "Bookerly", + "fontStyle": "italic", + "fontSize": "@textSizeSecondaryHint", + "color": "@colorTextPrimary" + } + }, + "textStyleDetails": { + "extend": ["textStyleBase2", "mixinDetails"] + } + }, + "onMount": [], + "graphics": {}, + "commands": {}, + "layouts": { + "ListTemplate1": { + "parameters": ["backgroundImage", "title", "logo", "hintText", "listData"], + "item": [ + { + "type": "Container", + "width": "100vw", + "height": "100vh", + "direction": "column", + "items": [ + { + "type": "Image", + "source": "${backgroundImage}", + "scale": "best-fill", + "width": "100vw", + "height": "100vh", + "position": "absolute" + }, + { + "type": "AlexaHeader", + "headerTitle": "${title}", + "headerAttributionImage": "${logo}" + }, + { + "type": "Sequence", + "grow": 1, + "height": "80vh", + "scrollDirection": "vertical", + "paddingLeft": "@marginLeft", + "paddingRight": "@marginRight", + "data": "${listData}", + "numbered": true, + "items": [ + { + "type": "VerticalListItem", + "image": "${data.image.sources[0].url}", + "primaryText": "${data.textContent.primaryText.text}", + "secondaryText": "${data.textContent.secondaryText.text}", + "tertiaryText": "${data.textContent.tertiaryText.text}" + } + ] + } + ] + } + ] + }, + "VerticalListItem": { + "parameters": ["primaryText", "secondaryText", "tertiaryText", "image"], + "item": [ + { + "when": "${viewport.shape == 'round'}", + "type": "Container", + "direction": "row", + "height": 200, + "width": 500, + "alignItems": "center", + "items": [ + { + "type": "Text", + "text": "${ordinal}", + "paddingBottom": "20dp", + "color": "white", + "spacing": "5dp" + }, + { + "type": "Image", + "when": "${image}", + "source": "${image}", + "height": 150, + "width": 150, + "spacing": 15, + "scale": "best-fit", + "align": "top" + }, + { + "type": "Container", + "direction": "column", + "spacing": 25, + "items": [ + { + "type": "Text", + "text": "${primaryText}", + "style": "textStyleDetail", + "grow": 1, + "shrink": 1, + "fontWeight": "300", + "maxLines": 1 + }, + { + "type": "Text", + "text": "${secondaryText}", + "style": "textStyleCaption", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + }, + { + "type": "Text", + "text": "${tertiaryText}", + "style": "textStyleDetails", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + } + ] + } + ] + }, + { + "type": "Container", + "direction": "row", + "height": 125, + "width": 800, + "alignItems": "center", + "items": [ + { + "type": "Text", + "text": "${ordinal}", + "paddingBottom": "20dp", + "color": "white", + "spacing": "5dp" + }, + { + "type": "Image", + "when": "${image}", + "source": "${image}", + "height": 100, + "width": 100, + "align": "top", + "spacing": 50, + "scale": "best-fit" + }, + { + "type": "Container", + "spacing": 30, + "direction": "column", + "items": [ + { + "type": "Text", + "text": "${primaryText}", + "style": "textStyleBody", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + }, + { + "type": "Text", + "text": "${secondaryText}", + "style": "textStyleDetails", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + } + ] + }, + { + "type": "Text", + "text": "${tertiaryText}", + "style": "textStyleBody", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "textAlign": "right", + "maxLines": 1 + } + ] + } + ] + } + }, + "mainTemplate": { + "parameters": ["payload"], + "item": [ + { + "type": "Container", + "id": "BookCabSimpleDialogAPL", + "items": [ + { + "type": "TouchWrapper", + "onPress": { + "type": "SendEvent", + "arguments": ["delegateToSkillNew"] + }, + "item": { + "type": "Text", + "id": "BookCabSimpleDialogAPL", + "paddingTop": "100", + "paddingLeft": "100", + "color": "green", + "size": 50, + "text": "delegateToSkillNew" + } + }, + { + "type": "TouchWrapper", + "onPress": { + "type": "SendEvent", + "arguments": ["delegateToSkillOld"] + }, + "item": { + "type": "Text", + "id": "BookCabSimpleDialogAPL", + "paddingTop": "100", + "paddingLeft": "100", + "color": "green", + "size": 50, + "text": "delegateToSkillOld" + } + }, + { + "type": "TouchWrapper", + "onPress": { + "type": "SendEvent", + "arguments": ["delegateToColtraneNew"] + }, + "item": { + "type": "Text", + "id": "BookCabSimpleDialogAPL", + "paddingTop": "100", + "paddingLeft": "100", + "color": "green", + "size": 50, + "text": "delegateToColtraneNew" + } + }, + { + "type": "TouchWrapper", + "onPress": { + "type": "SendEvent", + "arguments": ["delegateToColtraneOld"] + }, + "item": { + "type": "Text", + "id": "BookCabSimpleDialogAPL", + "paddingTop": "100", + "paddingLeft": "100", + "color": "green", + "size": 50, + "text": "delegateToColtraneOld" + } + } + ] + } + ] + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/AlexaConversationsBye/document.json b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/AlexaConversationsBye/document.json new file mode 100644 index 00000000..a0e2b3a8 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/AlexaConversationsBye/document.json @@ -0,0 +1,19 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": ["payload"], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "Bye.", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/AlexaConversationsNotifyFailure/document.json b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/AlexaConversationsNotifyFailure/document.json new file mode 100644 index 00000000..61d75e08 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/AlexaConversationsNotifyFailure/document.json @@ -0,0 +1,19 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": ["payload"], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "Sorry, there was an error in the request.", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/AlexaConversationsOutOfDomain/document.json b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/AlexaConversationsOutOfDomain/document.json new file mode 100644 index 00000000..e23d5986 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/AlexaConversationsOutOfDomain/document.json @@ -0,0 +1,19 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": ["payload"], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "Sorry, I don't understand.", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/AlexaConversationsProvideHelp/document.json b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/AlexaConversationsProvideHelp/document.json new file mode 100644 index 00000000..612a6f6e --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/AlexaConversationsProvideHelp/document.json @@ -0,0 +1,19 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": ["payload"], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "I can give you the weather report. Just say \"what's the weather\" to start.", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/AlexaConversationsRequestMore/document.json b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/AlexaConversationsRequestMore/document.json new file mode 100644 index 00000000..32a98507 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/AlexaConversationsRequestMore/document.json @@ -0,0 +1,19 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": ["payload"], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "What do you want to do.", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/AlexaConversationsThankYou/document.json b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/AlexaConversationsThankYou/document.json new file mode 100644 index 00000000..4aeb6f4b --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/AlexaConversationsThankYou/document.json @@ -0,0 +1,19 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": ["payload"], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "Thank you.", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/AlexaConversationsWelcome/document.json b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/AlexaConversationsWelcome/document.json new file mode 100644 index 00000000..b4ce85fe --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/AlexaConversationsWelcome/document.json @@ -0,0 +1,19 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": ["payload"], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "Welcome to the weather bot, I can give you the weather report. Just say \"what's the weather\" to start.", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/AlexaConversationsYouAreWelcome/document.json b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/AlexaConversationsYouAreWelcome/document.json new file mode 100644 index 00000000..2cd1b9a8 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/AlexaConversationsYouAreWelcome/document.json @@ -0,0 +1,19 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": ["payload"], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "You are welcome.", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/alexa_prize_preconditions_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/alexa_prize_preconditions_apla/document.json new file mode 100644 index 00000000..60503182 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/alexa_prize_preconditions_apla/document.json @@ -0,0 +1,89 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": ["payload"], + "item": { + "type": "Selector", + "description": "Selects the speech response to render when device/locale is not supported", + "items": [ + { + "when": "${payload.result.isDeviceSupported == 0}", + "type": "Speech", + "contentType": "text", + "content": "Sorry, Alexa Prize is not available on this device.", + "description": "" + }, + { + "when": "${payload.result.isLocaleSupported == 0}", + "type": "Speech", + "contentType": "text", + "content": "Sorry, Alexa Prize is not available in your locale.", + "description": "" + }, + { + "when": "${payload.result.isSocialBotAvailable == 0}", + "type": "Speech", + "contentType": "text", + "content": "Right now the Alexa Prize socialbots are busy. Please try again soon and help the university students in their competition to advance conversational A I.", + "description": "" + }, + { + "when": "${payload.result.isAlexaPrizeEnabled == 0}", + "type": "Speech", + "contentType": "text", + "content": "Alexa Prize is currently disabled for this account. Please visit the skill store in the Alexa App to re-enable it.", + "description": "" + }, + { + "when": "${payload.result.isTopicBanned == 1}", + "type": "Speech", + "contentType": "text", + "content": "I’d rather not talk about that, but there’s lots of other things to chat about. Do you still wanna chat?", + "description": "The topic that user wants to talk about is banned, ask if they still want to chat about something else" + }, + { + "when": "${payload.result.isFalseWake == 1}", + "type": "Speech", + "contentType": "text", + "content": "Would you like to chat with an Alexa Prize socialbot?", + "description": "" + }, + { + "when": "${payload.result.handoffPromptOverride == 'HandOffConversationForFilming'}", + "type": "Speech", + "contentType": "text", + "content": "Welcome to the Finals of the Alexa Prize Socialbot Grand Challenge 3, a university competition to advance AI. I’ll get you a socialbot now.", + "description": "" + }, + { + "when": "${payload.result.handoffPromptOverride == 'HandOffConversationForFinals'}", + "type": "Speech", + "contentType": "text", + "content": "Welcome to the Alexa Prize Socialbot Grand Challenge 3: Grand Finale. Here’s one of the finalists.", + "description": "" + }, + { + "when": "${payload.result.handoffPromptOverride == 'HandOffConversationForRepeatUser'}", + "type": "Speech", + "contentType": "text", + "content": "Welcome to the Alexa Prize, a university competition to advance AI. It’s quarterfinals for these socialbots and your ratings help determine who makes it to the semifinals. I’ll get you a socialbot now. When you’re done, say stop, and I’ll ask you for your rating. Your conversation and feedback will be shared with the university to help the socialbots improve.", + "description": "" + }, + { + "when": "${payload.result.handoffPromptOverride == 'CancelHandoff'}", + "type": "Speech", + "contentType": "text", + "content": "Okay", + "description": "" + }, + { + "type": "Speech", + "contentType": "text", + "content": "Welcome to the Alexa Prize, a university competition to advance AI. It’s quarterfinals for these socialbots and your ratings help determine who makes it to the semifinals. I’ll get you a socialbot now. When you’re done, say stop, and I’ll ask you for your rating. Your conversation and feedback will be shared with the university to help the socialbots improve.", + "description": "This is the current default handoff prompt" + } + ] + } + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/confirm_color_for_fruit_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/confirm_color_for_fruit_apla/document.json new file mode 100644 index 00000000..62c9758b --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/confirm_color_for_fruit_apla/document.json @@ -0,0 +1,19 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": ["payload"], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "confirm color is ${payload.colorName} ? ", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/confirm_fruitName_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/confirm_fruitName_apla/document.json new file mode 100644 index 00000000..47433a49 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/confirm_fruitName_apla/document.json @@ -0,0 +1,19 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": ["payload"], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "confirm fruit ${payload.fruitName} ? ", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/getEmployeePosition_success_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/getEmployeePosition_success_apla/document.json new file mode 100644 index 00000000..d0a91481 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/getEmployeePosition_success_apla/document.json @@ -0,0 +1,19 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": ["payload"], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "${payload.result.name1} born on ${payload.result.a_dateOfBirth} with employee id ${payload.result.emplyee1id} , is an ${payload.result.position} ", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/no_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/no_apla/document.json new file mode 100644 index 00000000..96a3af82 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/no_apla/document.json @@ -0,0 +1,19 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": ["payload"], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "I'm sorry you didn't like it", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/nothing2_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/nothing2_apla/document.json new file mode 100644 index 00000000..af75a7a5 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/nothing2_apla/document.json @@ -0,0 +1,19 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": ["payload"], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "The number you gave us was not 3.", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/nothing_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/nothing_apla/document.json new file mode 100644 index 00000000..bca77c74 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/nothing_apla/document.json @@ -0,0 +1,19 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": ["payload"], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "The number you gave us was 3.", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/numericfeedback_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/numericfeedback_apla/document.json new file mode 100644 index 00000000..2219120c --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/numericfeedback_apla/document.json @@ -0,0 +1,19 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": ["payload"], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "Your random number was ${payload.num}. How did we do? Please give this interaction a rating between 1-5, where 5 is the highest rating", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/rating_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/rating_apla/document.json new file mode 100644 index 00000000..06b50d68 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/rating_apla/document.json @@ -0,0 +1,19 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": ["payload"], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "rating please?", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/requestArgs_request_fruitName_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/requestArgs_request_fruitName_apla/document.json new file mode 100644 index 00000000..5e5d608a --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/requestArgs_request_fruitName_apla/document.json @@ -0,0 +1,25 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": ["payload"], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "tell me the fruit name ?", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + }, + { + "type": "Speech", + "contentType": "text", + "content": "random slection tell me the fruit name ?", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/request_city_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/request_city_apla/document.json new file mode 100644 index 00000000..64297b5e --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/request_city_apla/document.json @@ -0,0 +1,19 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": ["payload"], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "Which city?", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/request_city_date_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/request_city_date_apla/document.json new file mode 100644 index 00000000..a55ea5e1 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/request_city_date_apla/document.json @@ -0,0 +1,19 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": ["payload"], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "Which city and for which date?", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/request_colorName_multiple_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/request_colorName_multiple_apla/document.json new file mode 100644 index 00000000..5e5891e1 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/request_colorName_multiple_apla/document.json @@ -0,0 +1,19 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": ["payload"], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "which color?", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/request_date_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/request_date_apla/document.json new file mode 100644 index 00000000..af3a3f7d --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/request_date_apla/document.json @@ -0,0 +1,19 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": ["payload"], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "Which date?", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/request_dob_getDate_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/request_dob_getDate_apla/document.json new file mode 100644 index 00000000..b70a2ac6 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/request_dob_getDate_apla/document.json @@ -0,0 +1,19 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": ["payload"], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "SSML", + "content": "provide date?", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/request_getEmploeeID_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/request_getEmploeeID_apla/document.json new file mode 100644 index 00000000..32c39133 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/request_getEmploeeID_apla/document.json @@ -0,0 +1,19 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": ["payload"], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "SSML", + "content": "provide employee id?", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/request_name_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/request_name_apla/document.json new file mode 100644 index 00000000..db05dfee --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/request_name_apla/document.json @@ -0,0 +1,19 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": ["payload"], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "SSML", + "content": "what is your cool name?", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/success_colorFruitAPI_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/success_colorFruitAPI_apla/document.json new file mode 100644 index 00000000..b566e3fb --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/success_colorFruitAPI_apla/document.json @@ -0,0 +1,19 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": ["payload"], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "price of an ${payload.result.fruitName} is free bucks ", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/success_fruitPriceAPI_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/success_fruitPriceAPI_apla/document.json new file mode 100644 index 00000000..0db81389 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/success_fruitPriceAPI_apla/document.json @@ -0,0 +1,19 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": ["payload"], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "price of an ${payload.result.fruitName} is ${payload.result.price} bucks ", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/weather_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/weather_apla/document.json new file mode 100644 index 00000000..b2f5f3d9 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/weather_apla/document.json @@ -0,0 +1,27 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": ["payload"], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "when": "${payload.weatherResult != null && payload.weatherResult.cityName != null && payload.weatherResult.highTemp != null && payload.weatherResult.lowTemp != null}", + "type": "Speech", + "contentType": "text", + "content": "In ${payload.weatherResult.cityName}, it's a high of ${payload.weatherResult.highTemp} degrees and a low of ${payload.weatherResult.lowTemp} degrees.", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + }, + { + "when": "${payload.weatherResult != null && payload.weatherResult.cityNameChanged != null && payload.weatherResult.highTemp != null && payload.weatherResult.lowTemp != null}", + "type": "Speech", + "contentType": "text", + "content": "In ${payload.weatherResult.cityName}, it's a high of ${payload.weatherResult.highTemp} degrees and a low of ${payload.weatherResult.lowTemp} degrees.", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/weather_apla_de_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/weather_apla_de_apla/document.json new file mode 100644 index 00000000..1571f788 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/weather_apla_de_apla/document.json @@ -0,0 +1,27 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": ["payload"], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "when": "${payload.weatherResult != null && payload.weatherResult.cityName != null && payload.weatherResult.highTemp != null && payload.weatherResult.lowTemp != null}", + "type": "Speech", + "contentType": "text", + "content": "German result satheesh In ${payload.weatherResult.cityName}, it's a high of ${payload.weatherResult.highTemp} degrees and a low of ${payload.weatherResult.lowTemp} degrees.", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + }, + { + "when": "${payload.weatherResult != null && payload.weatherResult.cityNameChanged != null && payload.weatherResult.highTemp != null && payload.weatherResult.lowTemp != null}", + "type": "Speech", + "contentType": "text", + "content": "German result satheesh In ${payload.weatherResult.cityName}, it's a high of ${payload.weatherResult.highTemp} degrees and a low of ${payload.weatherResult.lowTemp} degrees.", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/yes_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/yes_apla/document.json new file mode 100644 index 00000000..a443c91e --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/yes_apla/document.json @@ -0,0 +1,19 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": ["payload"], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "Nice! Glad you like it", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/yesnofeedback_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/yesnofeedback_apla/document.json new file mode 100644 index 00000000..fd08347e --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/yesnofeedback_apla/document.json @@ -0,0 +1,19 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": ["payload"], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "Your number was ${payload.num}. Is this a good number, yes or no?", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/skill.json b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/skill.json new file mode 100644 index 00000000..8cc42910 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/skill.json @@ -0,0 +1,105 @@ +{ + "manifest": { + "apis": { + "custom": { + "dialogManagement": { + "dialogManagers": [ + { + "type": "AMAZON.Conversations" + } + ] + }, + "endpoint": { + "uri": "arn:aws:lambda:us-east-1:658396899051:function:6735d9fd-a8b2-4a97-bb37-7435c55c9ff0:Release_0" + }, + "interfaces": [ + { + "supportedViewports": [ + { + "maxHeight": 540, + "maxWidth": 960, + "minHeight": 540, + "minWidth": 960, + "mode": "TV", + "shape": "RECTANGLE" + }, + { + "maxHeight": 480, + "maxWidth": 480, + "minHeight": 480, + "minWidth": 480, + "mode": "HUB", + "shape": "ROUND" + }, + { + "maxHeight": 600, + "maxWidth": 1024, + "minHeight": 600, + "minWidth": 1024, + "mode": "HUB", + "shape": "RECTANGLE" + }, + { + "maxHeight": 800, + "maxWidth": 1280, + "minHeight": 800, + "minWidth": 1280, + "mode": "HUB", + "shape": "RECTANGLE" + }, + { + "maxHeight": 480, + "maxWidth": 960, + "minHeight": 480, + "minWidth": 960, + "mode": "HUB", + "shape": "RECTANGLE" + } + ], + "type": "ALEXA_PRESENTATION_APL" + } + ], + "regions": { + "EU": { + "endpoint": { + "uri": "arn:aws:lambda:eu-west-1:658396899051:function:6735d9fd-a8b2-4a97-bb37-7435c55c9ff0:Release_0" + } + }, + "NA": { + "endpoint": { + "uri": "arn:aws:lambda:us-east-1:658396899051:function:6735d9fd-a8b2-4a97-bb37-7435c55c9ff0:Release_0" + } + }, + "FE": { + "endpoint": { + "uri": "arn:aws:lambda:us-west-2:658396899051:function:6735d9fd-a8b2-4a97-bb37-7435c55c9ff0:Release_0" + } + } + } + } + }, + "manifestVersion": "1.0", + "publishingInformation": { + "category": "KNOWLEDGE_AND_TRIVIA", + "distributionCountries": [], + "isAvailableWorldwide": true, + "locales": { + "en-US": { + "description": "Sample Full Description", + "examplePhrases": ["Alexa open pizza reference", "order a pizza", "help"], + "keywords": [], + "name": "engineering test skill three", + "summary": "Sample Short Description" + }, + "de-DE": { + "description": "Sample Full Description", + "examplePhrases": ["Alexa open pizza reference", "order a pizza", "help"], + "keywords": [], + "name": "engineering test skill three", + "summary": "Sample Short Description" + } + }, + "testingInstructions": "Sample Testing Instructions." + } + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/.ask/ask-states.json b/test/unit/fixture/dialog-evaluate/test-project-5/.ask/ask-states.json new file mode 100644 index 00000000..e605e322 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-5/.ask/ask-states.json @@ -0,0 +1,8 @@ +{ + "askcliStatesVersion": "2020-03-31", + "profiles": { + "default": { + "skillId": "amzn1.ask.skill.b2d1f6dd-e43f-40eb-87a5-8cfd9650d249" + } + } +} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/ask-resources.json b/test/unit/fixture/dialog-evaluate/test-project-5/ask-resources.json new file mode 100644 index 00000000..be9cb8d1 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-5/ask-resources.json @@ -0,0 +1,10 @@ +{ + "askcliResourcesVersion": "2020-03-31", + "profiles": { + "default": { + "skillMetadata": { + "src": "./skill-package" + } + } + } +} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/conversations/Samenamespace.acdl b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/conversations/Samenamespace.acdl new file mode 100644 index 00000000..b173cdf7 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/conversations/Samenamespace.acdl @@ -0,0 +1,7 @@ +namespace com.weatherbot.apis + +import com.amazon.ask.types.builtins.AMAZON.DATE +import com.weatherbot.types.WeatherResult +import slotTypes.customCity + +action WeatherResult getWeather(customCity cityName, DATE date) diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/conversations/apisMine.acdl b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/conversations/apisMine.acdl new file mode 100644 index 00000000..8154a222 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/conversations/apisMine.acdl @@ -0,0 +1,50 @@ +namespace com.weatherbot.apis + +import com.amazon.alexa.schema.Nothing +import com.amazon.ask.types.builtins.AMAZON.Color +import com.amazon.ask.types.builtins.AMAZON.Food +import com.amazon.ask.types.builtins.AMAZON.NUMBER +import com.amazon.ask.types.builtins.AMAZON.US_CITY +import com.weatherbot.types.bookCabResult +import com.weatherbot.types.bookedFlightResult +import com.weatherbot.types.result +import com.weatherbot.types.result_one +import com.weatherbot.types.resultthree +import slotTypes.StringLiteral +import slotTypes.city_name_one +import slotTypes.city_name_two +import slotTypes.complexNames +import slotTypes.crust +import slotTypes.pickUpFrom +import slotTypes.size +import slotTypes.toppings + +action result colorFruitNameAAA(Food fruitName = nothing) + +action resultthree colorFruitName(Color colorName, Food fruitName = nothing) + +action result fruitNameAPI(Color colorName = nothing, Food fruitName = nothing) + +action result fruitNameAPIAA(Color colorName) + +action NUMBER numberOfVisits() + +action NUMBER getCooler() + +action NUMBER welcomeApi() + +action Nothing getHeater() + +action result_one favColorSign_Name(complexNames name) + +action bookedFlightResult bookFlightAPI(city_name_one source, city_name_two destination) + +action bookCabResult bookCabAPI(pickUpFrom pickUpFrom, city_name_one dropTo) + +action Nothing secondEarthAPI() + +action StringLiteral OrderTwoToppingPizza(toppings second_topping, toppings first_topping, crust crust, size size = nothing) + +action Nothing satheesh(US_CITY citsy) + +action Nothing Satheesh(US_CITY citsy) diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/conversations/basicOfferDialog.acdl b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/conversations/basicOfferDialog.acdl new file mode 100644 index 00000000..c53a0a9f --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/conversations/basicOfferDialog.acdl @@ -0,0 +1,134 @@ +namespace offerDialogFile + +import com.amazon.alexa.ask.conversations.Affirm +import com.amazon.alexa.ask.conversations.CarryOverArgument +import com.amazon.alexa.ask.conversations.Inform +import com.amazon.alexa.ask.conversations.Invoke +import com.amazon.alexa.ask.conversations.Notify +import com.amazon.alexa.ask.conversations.Offer +import com.amazon.alexa.ask.conversations.Request +import com.amazon.alexa.ask.conversations.expect +import com.amazon.alexa.ask.conversations.response +import com.amazon.alexa.schema.Nothing +import com.weatherbot.apis.bookCabAPI +import com.weatherbot.apis.bookFlightAPI +import com.weatherbot.types.bookCabResult +import com.weatherbot.types.bookedFlightResult +import com.weatherbot.utteracesets.affirmCabAPIEvent +import com.weatherbot.utteracesets.bookFlightEvent +import com.weatherbot.utteracesets.informFromBookFlight +import com.weatherbot.utteracesets.informPickUpFromBookCab +import com.weatherbot.utteracesets.informToBookFlight +import prompts.requestFromBookFlight_apla +import prompts.requestPickUpFromBookCab_apla +import prompts.requestToBookFlight_apla +import prompts.successBookCabAPI_apla +import prompts.successBookFlightAPI_apla + +type payloadBookFlightAPI { + bookedFlightResult resultTwo +} + +type payloadOfferResult { + bookCabResult result +} + +dialog Nothing complex_two() { + sample { + expect( + Invoke, + bookFlightEvent + ) + response( + requestFromBookFlight_apla, + Request { + arguments = [ + bookFlightAPI.arguments.source + ] + }, + nothing, + nothing, + nothing + ) + sourceFlightEvent = expect( + Inform, + informFromBookFlight + ) + response( + requestToBookFlight_apla, + Request { + arguments = [ + bookFlightAPI.arguments.destination + ] + }, + nothing, + nothing, + nothing + ) + destinationFlightEvent = expect( + Inform, + informToBookFlight + ) + resultFlightApi = bookFlightAPI( + sourceFlightEvent.source, + destinationFlightEvent.destination + ) + response( + successBookFlightAPI_apla, + Notify { + actionName = bookFlightAPI, + success = true + }, + Offer { + actionName = bookCabAPI, + arguments = [ + bookCabAPI.arguments.pickUpFrom + ], + carryOverArguments = [ + CarryOverArgument { + argument = bookCabAPI.arguments.dropTo, + source = resultFlightApi.source + } + ] + }, + payloadBookFlightAPI { + resultTwo = resultFlightApi + }, + nothing + ) + expect( + Affirm, + affirmCabAPIEvent + ) + response( + requestPickUpFromBookCab_apla, + Request { + arguments = [ + bookCabAPI.arguments.pickUpFrom + ] + }, + nothing, + nothing, + nothing + ) + PickUpCabEvent = expect( + Inform, + informPickUpFromBookCab + ) + resultOne = bookCabAPI( + PickUpCabEvent.pickUpFrom, + resultFlightApi.source + ) + response( + successBookCabAPI_apla, + Notify { + actionName = bookCabAPI + }, + nothing, + payloadOfferResult { + result = resultOne + }, + nothing + ) + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/conversations/conditions.acdl b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/conversations/conditions.acdl new file mode 100644 index 00000000..b14437ee --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/conversations/conditions.acdl @@ -0,0 +1,172 @@ +namespace conditionsACDlFile + +import com.amazon.alexa.ask.conversations.Inform +import com.amazon.alexa.ask.conversations.Invoke +import com.amazon.alexa.ask.conversations.MultiModalResponse +import com.amazon.alexa.ask.conversations.Notify +import com.amazon.alexa.ask.conversations.Offer +import com.amazon.alexa.ask.conversations.ReqAlt +import com.amazon.alexa.ask.conversations.Request +import com.amazon.alexa.ask.conversations.RequestArguments +import com.amazon.alexa.ask.conversations.ensure +import com.amazon.alexa.ask.conversations.expect +import com.amazon.alexa.ask.conversations.response +import com.amazon.alexa.ask.conversations.size +import com.amazon.alexa.schema.Nothing +import com.amazon.alexa.schema.Thing +import com.weatherbot.apis.favColorSign_Name +import com.weatherbot.apis.getWeather +import com.weatherbot.types.WeatherResult +import com.weatherbot.types.result_one +import com.weatherbot.utteracesets.getWeatherEventNoArgs +import com.weatherbot.utteracesets.informCityEvent +import com.weatherbot.utteracesets.informComplexNameEvent +import com.weatherbot.utteracesets.informDateEvent +import displays.request_city_apl_display +import prompts.request_city_apla +import prompts.request_date_apla +import prompts.request_name_apla +import prompts.success_favColorSign_Name_apla +import prompts.weather_success_apla + +type payload_one { + result_one result +} + +type payload_one_two { + WeatherResult weatherResult +} + +dialog Nothing conditionComplex() { + sample { + expect( + Invoke, + getWeatherEventNoArgs + ) + request_city_multimodal = MultiModalResponse { + apla = request_city_apla, + apl = request_city_apl_display + } + request_date_multimodal = MultiModalResponse { + apla = request_date_apla, + apl = request_city_apl_display + } + response( + request_city_multimodal, + Request { + arguments = [ + getWeather.arguments.cityName + ] + }, + nothing, + nothing, + nothing + ) + cityEvent = expect( + Inform, + informCityEvent + ) + response( + request_date_multimodal, + Request { + arguments = [ + getWeather.arguments.date + ] + }, + nothing, + nothing, + nothing + ) + dateEvent = expect( + Inform, + informDateEvent + ) + weatherResult = getWeather( + cityEvent.cityName, + dateEvent.date + ) + if (((weatherResult.highTemp < 3 && weatherResult.lowTemp > 0) && size( + weatherResult.itemsToUse + ) > 1)) { + response( + weather_success_apla, + Notify { + actionName = getWeather + }, + Offer { + actionName = favColorSign_Name, + arguments = [ + favColorSign_Name.arguments.name + ] + }, + nothing, + nothing + ) + ensure( + RequestArguments { + arguments = [ + favColorSign_Name.arguments.name + ], + response = request_name_apla + } + ) + ComplexNameEvent = expect( + Inform, + informComplexNameEvent + ) + resultOne_one = favColorSign_Name( + ComplexNameEvent.name + ) + response( + success_favColorSign_Name_apla, + Notify { + actionName = favColorSign_Name + }, + nothing, + payload_one { + result = resultOne_one + }, + nothing + ) + } else { + response( + weather_success_apla, + Notify { + actionName = getWeather, + success = false + }, + ReqAlt { + arguments = [ + getWeather.arguments.cityName + ] + }, + payload_one_two { + weatherResult = weatherResult + }, + nothing + ) + cityEvent_new = expect( + Inform, + informCityEvent + ) + weatherResult_two = getWeather( + cityEvent_new.cityName, + dateEvent.date + ) + successAPLWithAPLsa_nw = MultiModalResponse { + apla = weather_success_apla + } + response( + successAPLWithAPLsa_nw, + Notify { + actionName = getWeather + }, + nothing, + payload_one_two { + weatherResult = weatherResult_two + }, + nothing + ) + } + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/conversations/conversation_empty.acdl b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/conversations/conversation_empty.acdl new file mode 100644 index 00000000..0c63977c --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/conversations/conversation_empty.acdl @@ -0,0 +1,109 @@ +namespace com.numberbot + +import com.amazon.alexa.ask.conversations.APLA +import com.amazon.alexa.ask.conversations.Action +import com.amazon.alexa.ask.conversations.Bye +import com.amazon.alexa.ask.conversations.Invoke +import com.amazon.alexa.ask.conversations.Notify +import com.amazon.alexa.ask.conversations.Offer +import com.amazon.alexa.ask.conversations.RequestArguments +import com.amazon.alexa.ask.conversations.ensure +import com.amazon.alexa.ask.conversations.expect +import com.amazon.alexa.ask.conversations.response +import com.amazon.alexa.ask.conversations.utterances +import com.amazon.alexa.schema.Nothing +import com.amazon.alexa.schema.Number +import com.amazon.alexa.schema.Thing +import com.amazon.ask.types.builtins.AMAZON.NUMBER +import prompts.AlexaConversationsBye +import prompts.numericfeedback_apla +import prompts.rating_apla + +type NumPayload { + Number num +} + +type RatingRequest { + NUMBER rating +} + +InformRatingEvent = utterances( + [ + "my score is {rating}", + "that was a {rating} conversation", + "i rate you a {rating}", + "{rating}" + ] +) + +getStart = utterances( + [ + "give me a number please" + ] +) + +action Nothing saveRating(Number rating) + +action Number getNumber() + +dialog Nothing GetFeedback(APLA feedback_prompt, Thing payload, Action notifyAction) { + sample { + response( + feedback_prompt, + Notify { + actionName = notifyAction, + success = true + }, + Offer { + actionName = saveRating, + arguments = [ + saveRating.arguments.rating + ] + }, + payload, + nothing + ) + myRating = expect( + Invoke, + InformRatingEvent + ) + ensure( + RequestArguments { + arguments = [ + saveRating.arguments.rating + ], + response = rating_apla + } + ) + saveRating( + myRating.rating + ) + } +} + +dialog Nothing MainDialog() { + sample { + expect( + Invoke, + getStart + ) + num = getNumber() + GetFeedback( + feedback_prompt = numericfeedback_apla, + payload = NumPayload { + num = num + }, + notifyAction = getNumber + ) + response( + AlexaConversationsBye, + Notify { + actionName = saveRating, + success = true + }, + Bye {}, + nothing, + nothing + ) + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/conversations/delegateToSkill.acdl b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/conversations/delegateToSkill.acdl new file mode 100644 index 00000000..e9c9d884 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/conversations/delegateToSkill.acdl @@ -0,0 +1,29 @@ +namespace delegateToSkill + +import com.amazon.alexa.ask.conversations.Invoke +import com.amazon.alexa.ask.conversations.Notify +import com.amazon.alexa.ask.conversations.expect +import com.amazon.alexa.ask.conversations.response +import com.amazon.alexa.schema.Nothing +import com.weatherbot.apis.secondEarthAPI +import com.weatherbot.utteracesets.delegateToSkill +import prompts.secondEarthAPI_apla + +dialog Nothing testTwo() { + sample { + expect( + Invoke, + delegateToSkill + ) + secondEarthAPI() + response( + secondEarthAPI_apla, + Notify { + actionName = secondEarthAPI + }, + nothing, + nothing, + nothing + ) + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/conversations/dialogWeather.acdl b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/conversations/dialogWeather.acdl new file mode 100644 index 00000000..60962dc9 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/conversations/dialogWeather.acdl @@ -0,0 +1,9 @@ +namespace dialogWeather + +import com.amazon.ask.types.builtins.AMAZON.DATE +import slotTypes.customCity + +type payloadConfirmArgsDialogWeather { + optional customCity cityName + optional DATE date +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/conversations/listDialogWithConditions.acdl b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/conversations/listDialogWithConditions.acdl new file mode 100644 index 00000000..58f932f7 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/conversations/listDialogWithConditions.acdl @@ -0,0 +1,250 @@ +namespace listDialog + +import com.amazon.alexa.ask.conversations.Affirm +import com.amazon.alexa.ask.conversations.ConfirmAction +import com.amazon.alexa.ask.conversations.Inform +import com.amazon.alexa.ask.conversations.Invoke +import com.amazon.alexa.ask.conversations.Notify +import com.amazon.alexa.ask.conversations.Request +import com.amazon.alexa.ask.conversations.expect +import com.amazon.alexa.ask.conversations.response +import com.amazon.alexa.ask.conversations.size +import com.amazon.alexa.ask.conversations.utterances +import com.amazon.alexa.schema.List +import com.amazon.alexa.schema.Nothing +import com.amazon.ask.types.builtins.AMAZON.Food +import com.weatherbot.apis.colorFruitNameAAA +import com.weatherbot.apis.fruitNameAPI +import com.weatherbot.apis.numberOfVisits +import com.weatherbot.types.result +import com.weatherbot.utteracesets.GiveMeTodaySpecialsEvent +import com.weatherbot.utteracesets.affirmCookAPIEvent +import com.weatherbot.utteracesets.cookWithTwoIngredientsEvent +import com.weatherbot.utteracesets.getFruitPriceEvent +import com.weatherbot.utteracesets.getMarketPlaceEvent +import com.weatherbot.utteracesets.informFoodNameEvent +import com.weatherbot.utteracesets.informMarketPlaceNameEvent +import com.weatherbot.utteracesets.informfruitNameEvent +import prompts.SuccessGiveMeTodaySpecialsEvent_apla +import prompts.confirm_main_addon_list_apla +import prompts.requestArgs_request_fruitName_apla +import prompts.request_listAddOns_apla +import prompts.request_mainFoodName_apla +import prompts.success_cookingAPI_apla +import prompts.success_fruitPriceAPI_apla +import slotTypes.Mix +import slotTypes.orderStatus + +type addOnShell { + List addOn +} + +action orderStatus cookingAPI(Food foodName, List addOn) + +action List todaySpecials() + +informlistAddOnsEvent = utterances( + [ + "{addOn}", + "add {addOn}", + "mix {addOn}" + ] +) + +type payloadStatuscookWithTwoIngredients { + orderStatus status +} + +type payloadGiveMeTodaySpecials { + List result +} + +type payloadgetFruitPriceEvent { + result result +} + +type payloadConfirmActionComplex { + optional Food foodName + List addOn +} + +type paylaodCompleFruit { + Food fruitName +} + +type WrongpayloadGiveMeTodaySpecialsNew { + List ListOfMix1 + Mix Mix1 +} + +type payloadGiveMeTodaySpecialsNew { + List ListOfMix1 +} + +type InteractionFoodName { + Food foodName +} + +dialog Nothing complex() { + sample { + expect( + Invoke, + cookWithTwoIngredientsEvent + ) + response( + request_listAddOns_apla, + Request { + arguments = [ + cookingAPI.arguments.addOn + ] + }, + nothing, + nothing, + nothing + ) + listAddOnsEvent = expect( + Inform, + informlistAddOnsEvent + ) + response( + request_mainFoodName_apla, + Request { + arguments = [ + cookingAPI.arguments.foodName + ] + }, + nothing, + nothing, + nothing + ) + FoodNameEvent = expect( + Inform, + informFoodNameEvent + ) + response( + confirm_main_addon_list_apla, + ConfirmAction { + actionName = cookingAPI + }, + nothing, + payloadConfirmActionComplex { + foodName = FoodNameEvent.foodName, + addOn = listAddOnsEvent.addOn + }, + nothing + ) + expect( + Affirm, + affirmCookAPIEvent + ) + resultOne = cookingAPI( + FoodNameEvent.foodName, + listAddOnsEvent.addOn + ) + response( + success_cookingAPI_apla, + Notify { + actionName = cookingAPI + }, + nothing, + payloadStatuscookWithTwoIngredients { + status = resultOne + }, + nothing + ) + } + sample { + expect( + Invoke, + GiveMeTodaySpecialsEvent + ) + numberOfVisits() + resultOne = todaySpecials() + if (size( + resultOne + ) == 1) { + response( + SuccessGiveMeTodaySpecialsEvent_apla, + Notify { + actionName = todaySpecials + }, + nothing, + payloadGiveMeTodaySpecials { + result = resultOne + }, + nothing + ) + } + } + sample { + expect( + Invoke, + getFruitPriceEvent + ) + response( + requestArgs_request_fruitName_apla, + Request { + arguments = [ + fruitNameAPI.arguments.fruitName + ] + }, + nothing, + nothing, + nothing + ) + fruitNameEvent = expect( + Inform, + informfruitNameEvent + ) + resultOne = fruitNameAPI( + nothing, + fruitNameEvent.fruitName + ) + response( + success_fruitPriceAPI_apla, + Notify { + actionName = fruitNameAPI + }, + nothing, + payloadgetFruitPriceEvent { + result = resultOne + }, + nothing + ) + } + sample { + expect( + Invoke, + getMarketPlaceEvent + ) + response( + requestArgs_request_fruitName_apla, + Request { + arguments = [ + colorFruitNameAAA.arguments.fruitName + ] + }, + nothing, + nothing, + nothing + ) + MarketPlaceInformResponseEvent = expect( + Inform, + informMarketPlaceNameEvent + ) + resultOne = colorFruitNameAAA( + MarketPlaceInformResponseEvent.fruitName + ) + response( + success_fruitPriceAPI_apla, + Notify { + actionName = colorFruitNameAAA + }, + nothing, + payloadgetFruitPriceEvent { + result = resultOne + }, + nothing + ) + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/conversations/optionalDelegate.acdl b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/conversations/optionalDelegate.acdl new file mode 100644 index 00000000..200a624f --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/conversations/optionalDelegate.acdl @@ -0,0 +1,162 @@ +namespace optionalArgACDL + +import com.amazon.alexa.ask.conversations.Affirm +import com.amazon.alexa.ask.conversations.ConfirmAction +import com.amazon.alexa.ask.conversations.ConfirmArgs +import com.amazon.alexa.ask.conversations.Inform +import com.amazon.alexa.ask.conversations.Invoke +import com.amazon.alexa.ask.conversations.MultiModalResponse +import com.amazon.alexa.ask.conversations.Notify +import com.amazon.alexa.ask.conversations.Request +import com.amazon.alexa.ask.conversations.expect +import com.amazon.alexa.ask.conversations.response +import com.amazon.alexa.ask.conversations.utterances +import com.amazon.alexa.schema.Nothing +import com.amazon.alexa.schema.Thing +import com.weatherbot.apis.favColorSign_Name +import com.weatherbot.types.payloadConfirmActionConditionComplex +import com.weatherbot.types.result_one +import com.weatherbot.utteracesets.affirmFavColorEvent +import com.weatherbot.utteracesets.informComplexNameEvent +import prompts.confirmAction_complexNames_apla +import prompts.confirmArgs_complexNames_apla +import prompts.request_name_apla +import prompts.success_favColorSign_Name_apla +import slotTypes.complexNames + +type payloadResult_optional { + result_one result +} + +type payloadResult_optional_name { + complexNames name +} + +getFavColorEvent = utterances( + [ + "what is my favourite color", + "tell my favourite color" + ] +) + +getFavColorEventTwo = utterances( + [ + "guess the color" + ] +) + +dialog Nothing optiOnal() { + sample { + expect( + Invoke, + getFavColorEvent + ) + response( + MultiModalResponse { + apla = request_name_apla + }, + Request { + arguments = [ + favColorSign_Name.arguments.name + ] + }, + nothing, + nothing, + nothing + ) + ComplexNameEvent = expect( + Inform, + informComplexNameEvent + ) + response( + confirmArgs_complexNames_apla, + ConfirmArgs { + arguments = [ + favColorSign_Name.arguments.name + ] + }, + nothing, + payloadConfirmActionConditionComplex { + name = ComplexNameEvent.name + }, + nothing + ) + expect( + Affirm, + affirmFavColorEvent + ) + resultOne = favColorSign_Name( + ComplexNameEvent.name + ) + response( + success_favColorSign_Name_apla, + Notify { + actionName = favColorSign_Name + }, + nothing, + payloadResult_optional { + result = resultOne + }, + nothing + ) + } +} + +type PAYLOAD_TYPE01 { + complexNames name +} + +dialog Nothing optiOnalTwo() { + sample { + expect( + Invoke, + getFavColorEventTwo + ) + response( + MultiModalResponse { + apla = request_name_apla + }, + Request { + arguments = [ + favColorSign_Name.arguments.name + ] + }, + nothing, + nothing, + nothing + ) + ComplexNameEvent = expect( + Inform, + informComplexNameEvent + ) + response( + confirmAction_complexNames_apla, + ConfirmAction { + actionName = favColorSign_Name + }, + nothing, + payloadConfirmActionConditionComplex { + name = ComplexNameEvent.name + }, + nothing + ) + expect( + Affirm, + affirmFavColorEvent + ) + result1 = favColorSign_Name( + ComplexNameEvent.name + ) + response( + success_favColorSign_Name_apla, + Notify { + actionName = favColorSign_Name + }, + nothing, + payloadResult_optional { + result = result1 + }, + nothing + ) + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/conversations/pizza.acdl b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/conversations/pizza.acdl new file mode 100644 index 00000000..777ac168 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/conversations/pizza.acdl @@ -0,0 +1,196 @@ +namespace pizzaAcdl + +import com.amazon.alexa.ask.conversations.Affirm +import com.amazon.alexa.ask.conversations.ConfirmAction +import com.amazon.alexa.ask.conversations.ConfirmArgs +import com.amazon.alexa.ask.conversations.Inform +import com.amazon.alexa.ask.conversations.Invoke +import com.amazon.alexa.ask.conversations.MultiModalResponse +import com.amazon.alexa.ask.conversations.Notify +import com.amazon.alexa.ask.conversations.Request +import com.amazon.alexa.ask.conversations.RequestArguments +import com.amazon.alexa.ask.conversations.ensure +import com.amazon.alexa.ask.conversations.expect +import com.amazon.alexa.ask.conversations.response +import com.amazon.alexa.schema.Nothing +import com.amazon.alexa.schema.Thing +import com.weatherbot.apis.OrderTwoToppingPizza +import com.weatherbot.types.PAYLOAD_TYPE6 +import com.weatherbot.types.PAYLOAD_TYPE7 +import com.weatherbot.types.PAYLOAD_TYPE88 +import com.weatherbot.types.PAYLOAD_TYPE9 +import com.weatherbot.utteracesets.Yes +import com.weatherbot.utteracesets.specifyCrust +import com.weatherbot.utteracesets.specifySize +import com.weatherbot.utteracesets.specifyTwoToppings +import com.weatherbot.utteracesets.startTwoToppingPizzaOrder +import prompts.askForCrustPrompts +import prompts.askForSizePrompts +import prompts.askForToppingOnePrompt +import prompts.askForToppingTwoPrompt +import prompts.askForTwoToppingsPrompts +import prompts.confirmSizePrompt +import prompts.confirmTwoToppingOrderPromptcopy +import prompts.confirmTwoToppingsPrompt +import prompts.twoToppingOrderSuccessPrompt + +dialog Nothing orderTwoToppingPizza() { + sample { + expect( + Invoke, + startTwoToppingPizzaOrder + ) + ensure( + RequestArguments { + arguments = [ + OrderTwoToppingPizza.arguments.first_topping + ], + response = MultiModalResponse { + apla = askForToppingOnePrompt + } + } + ) + ensure( + RequestArguments { + arguments = [ + OrderTwoToppingPizza.arguments.second_topping + ], + response = MultiModalResponse { + apla = askForToppingTwoPrompt + } + } + ) + response( + MultiModalResponse { + apla = askForSizePrompts + }, + Request { + arguments = [ + OrderTwoToppingPizza.arguments.size + ] + }, + nothing, + nothing, + nothing + ) + specifySizeRequest = expect( + Inform, + specifySize + ) + response( + MultiModalResponse { + apla = confirmSizePrompt + }, + ConfirmArgs { + arguments = [ + OrderTwoToppingPizza.arguments.size + ] + }, + nothing, + PAYLOAD_TYPE6 { + size = specifySizeRequest.size + }, + nothing + ) + expect( + Affirm, + Yes + ) + response( + MultiModalResponse { + apla = askForCrustPrompts + }, + Request { + arguments = [ + OrderTwoToppingPizza.arguments.crust + ] + }, + nothing, + nothing, + nothing + ) + specifyCrustRequest = expect( + Inform, + specifyCrust + ) + response( + MultiModalResponse { + apla = askForTwoToppingsPrompts + }, + Request { + arguments = [ + OrderTwoToppingPizza.arguments.first_topping, + OrderTwoToppingPizza.arguments.second_topping + ] + }, + nothing, + nothing, + nothing + ) + specifyTwoToppingsRequest = expect( + Inform, + specifyTwoToppings + ) + response( + MultiModalResponse { + apla = confirmTwoToppingsPrompt + }, + ConfirmArgs { + arguments = [ + OrderTwoToppingPizza.arguments.first_topping, + OrderTwoToppingPizza.arguments.second_topping + ] + }, + nothing, + PAYLOAD_TYPE7 { + second_topping = specifyTwoToppingsRequest.second_topping, + first_topping = specifyTwoToppingsRequest.first_topping + }, + nothing + ) + expect( + Affirm, + Yes + ) + response( + MultiModalResponse { + apla = confirmTwoToppingOrderPromptcopy + }, + ConfirmAction { + actionName = OrderTwoToppingPizza + }, + nothing, + PAYLOAD_TYPE88 { + size = specifySizeRequest.size, + second_topping = specifyTwoToppingsRequest.second_topping, + first_topping = specifyTwoToppingsRequest.first_topping, + crust = specifyCrustRequest.crust + }, + nothing + ) + expect( + Affirm, + Yes + ) + stringLiteral1 = OrderTwoToppingPizza( + specifyTwoToppingsRequest.second_topping, + specifyTwoToppingsRequest.first_topping, + specifyCrustRequest.crust, + specifySizeRequest.size + ) + response( + MultiModalResponse { + apla = twoToppingOrderSuccessPrompt + }, + Notify { + success = true, + actionName = OrderTwoToppingPizza + }, + nothing, + PAYLOAD_TYPE9 { + speech = stringLiteral1 + }, + nothing + ) + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/conversations/soaDialog.acdl b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/conversations/soaDialog.acdl new file mode 100644 index 00000000..d4c0acb5 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/conversations/soaDialog.acdl @@ -0,0 +1,89 @@ +namespace soaACDl + +import com.amazon.alexa.ask.conversations.Affirm +import com.amazon.alexa.ask.conversations.ConfirmArgs +import com.amazon.alexa.ask.conversations.Inform +import com.amazon.alexa.ask.conversations.Invoke +import com.amazon.alexa.ask.conversations.Notify +import com.amazon.alexa.ask.conversations.Request +import com.amazon.alexa.ask.conversations.expect +import com.amazon.alexa.ask.conversations.response +import com.amazon.alexa.schema.Nothing +import com.amazon.ask.types.builtins.AMAZON.Color +import com.weatherbot.apis.colorFruitName +import com.weatherbot.apis.fruitNameAPI +import com.weatherbot.types.result +import com.weatherbot.utteracesets.MultipleDialogEvent +import com.weatherbot.utteracesets.affirmMultipleColorEvent +import com.weatherbot.utteracesets.informColorMultipleEvent +import prompts.confirm_color_for_fruit_apla +import prompts.request_colorName_multiple_apla +import prompts.success_fruitPriceAPI_apla + +type payloadMultipleDialogEvent { + result result +} + +type payloadsOAConfirmArgs { + Color colorName +} + +dialog Nothing sOA() { + sample { + expect( + Invoke, + MultipleDialogEvent + ) + response( + request_colorName_multiple_apla, + Request { + arguments = [ + colorFruitName.arguments.colorName + ] + }, + nothing, + nothing, + nothing + ) + colorEvent = expect( + Inform, + informColorMultipleEvent + ) + response( + confirm_color_for_fruit_apla, + ConfirmArgs { + arguments = [ + colorFruitName.arguments.colorName + ] + }, + nothing, + payloadsOAConfirmArgs { + colorName = colorEvent.colorName + }, + nothing + ) + expect( + Affirm, + affirmMultipleColorEvent + ) + resultEvent = colorFruitName( + colorEvent.colorName, + nothing + ) + resultOne = fruitNameAPI( + nothing, + resultEvent.fruitName + ) + response( + success_fruitPriceAPI_apla, + Notify { + actionName = fruitNameAPI + }, + nothing, + payloadMultipleDialogEvent { + result = resultOne + }, + nothing + ) + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/conversations/typesMine.acdl b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/conversations/typesMine.acdl new file mode 100644 index 00000000..057115d1 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/conversations/typesMine.acdl @@ -0,0 +1,248 @@ +namespace com.weatherbot.types + +import com.amazon.alexa.schema.List +import com.amazon.ask.types.builtins.AMAZON.Color +import com.amazon.ask.types.builtins.AMAZON.DATE +import com.amazon.ask.types.builtins.AMAZON.Food +import com.amazon.ask.types.builtins.AMAZON.NUMBER +import slotTypes.Mix +import slotTypes.StringLiteral +import slotTypes.cheese +import slotTypes.city_name_one +import slotTypes.city_name_two +import slotTypes.complexNames +import slotTypes.crust +import slotTypes.customCity +import slotTypes.option +import slotTypes.orderStatus +import slotTypes.pickUpFrom +import slotTypes.signs +import slotTypes.size +import slotTypes.specialPizzaName +import slotTypes.toppings + +type customCityShell { + customCity cityName +} + +type signShell { + signs sign +} + +type dateValue { + DATE date +} + +type WeatherResult { + customCity cityName + NUMBER highTemp + NUMBER lowTemp + optional List itemsToUse +} + +type resultthree { + Food fruitName + Color colorName +} + +type result { + Food fruitName + NUMBER price +} + +type fruitNameShell { + Food fruitName +} + +type foodNameShell { + Food foodName +} + +type CityDateShell { + optional customCity cityName + optional DATE date +} + +type nameShell { + complexNames name +} + +type colorNameShell { + Color colorName +} + +type result_one { + Color colorName + complexNames name + signs sign +} + +type sourceShell { + city_name_one source +} + +type destinationShell { + city_name_two destination +} + +type pickUpFromShell { + pickUpFrom pickUpFrom +} + +type dropToShell { + city_name_one dropTo +} + +type bookedFlightResult { + city_name_two destination + city_name_one source + orderStatus orderStatus +} + +type bookCabResult { + pickUpFrom pickUpFrom + city_name_one dropTo + orderStatus orderStatus +} + +type ResponsePayload { + WeatherResult weatherResult +} + +type payloadConfirmActionConditionComplex { + optional complexNames name + optional signs sign +} + +type Response_Payload_one { + optional customCity cityName + optional DATE date +} + +type inform_menu_optionRequestType { + option option +} + +type specifySpecialNameRequestType { + specialPizzaName name +} + +type askMenuQuestionRequestType { + option option +} + +type specifySizeAndToppingsRequestType { + size size + List toppings +} + +type orderSpecificSizePizzaRequestType { + size size +} + +type specifyQtyRequestType { + NUMBER qty +} + +type customizePizzaReferenceSpecialRequestType { + specialPizzaName name +} + +type specifyTwoToppingsRequestType { + toppings second_topping + toppings first_topping +} + +type inquireAboutFeedingSizeRequestType { + size size +} + +type specifyToppingsRequestType { + List toppingsList +} + +type specifySizeRequestType { + size size +} + +type specifyCrustRequestType { + crust crust +} + +type specifyCheeseRequestType { + cheese cheese +} + +type pizza { + size size + List toppingsList + crust crust + cheese cheese +} + +type special { + pizza pizza + NUMBER cost + NUMBER qty + specialPizzaName name +} + +type PAYLOAD_TYPE0 { + size size + StringLiteral prompt +} + +type PAYLOAD_TYPE1 { + size size + List toppingsList + crust crust + cheese cheese +} + +type PAYLOAD_TYPE2 { + pizza pizza +} + +type PAYLOAD_TYPE3 { + size size + List toppingsList + crust crust + cheese cheese +} + +type PAYLOAD_TYPE4 { + pizza pizza +} + +type PAYLOAD_TYPE5 { + size size + StringLiteral prompt +} + +type PAYLOAD_TYPE6 { + size size +} + +type PAYLOAD_TYPE7 { + toppings second_topping + toppings first_topping +} + +type PAYLOAD_TYPE88 { + toppings second_topping + toppings first_topping + crust crust + optional size size +} + +type PAYLOAD_TYPE9 { + StringLiteral speech +} + +type PAYLOAD_TYPE10 { + StringLiteral optionResponse +} + +type PAYLOAD_TYPE11 { + StringLiteral optionResponse +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/conversations/utteracesetsMine.acdl b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/conversations/utteracesetsMine.acdl new file mode 100644 index 00000000..17a71d57 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/conversations/utteracesetsMine.acdl @@ -0,0 +1,455 @@ +namespace com.weatherbot.utteracesets + +import com.amazon.alexa.ask.conversations.utterances +import com.weatherbot.types.CityDateShell +import com.weatherbot.types.askMenuQuestionRequestType +import com.weatherbot.types.colorNameShell +import com.weatherbot.types.customCityShell +import com.weatherbot.types.customizePizzaReferenceSpecialRequestType +import com.weatherbot.types.dateValue +import com.weatherbot.types.destinationShell +import com.weatherbot.types.dropToShell +import com.weatherbot.types.foodNameShell +import com.weatherbot.types.fruitNameShell +import com.weatherbot.types.inform_menu_optionRequestType +import com.weatherbot.types.inquireAboutFeedingSizeRequestType +import com.weatherbot.types.nameShell +import com.weatherbot.types.orderSpecificSizePizzaRequestType +import com.weatherbot.types.pickUpFromShell +import com.weatherbot.types.signShell +import com.weatherbot.types.sourceShell +import com.weatherbot.types.specifyCheeseRequestType +import com.weatherbot.types.specifyCrustRequestType +import com.weatherbot.types.specifyQtyRequestType +import com.weatherbot.types.specifySizeAndToppingsRequestType +import com.weatherbot.types.specifySizeRequestType +import com.weatherbot.types.specifySpecialNameRequestType +import com.weatherbot.types.specifyToppingsRequestType +import com.weatherbot.types.specifyTwoToppingsRequestType + +values = [ + "what is the weather", + "what's the weather", + "tell me the weather" +] + +getWeatherEventNoArgs = utterances( + values +) + +getWeatherEventArgs = utterances( + [ + "tell me the weather in {cityName} {date}", + "how is the weather in {cityName} {date}" + ] +) + +getWeatherEvent = utterances( + [ + "What's the weather {date} in {cityName}", + "what is the weather {date}", + "How is the weather {date}", + "How is weather in {cityName} {date}", + "how is weather", + "can you please give me weather report for {date}" + ] +) + +informCityEvent = utterances( + [ + "{cityName}", + "city is {cityName}", + "city name is {cityName}" + ] +) + +informDateEvent = utterances( + [ + "date is {date}", + "for {date}", + "{date}" + ] +) + +affirmWeatherEvent = utterances( + [ + "yes", + "yeah" + ] +) + +delegateToSkill = utterances( + [ + "get me to paradise", + "take me to paradise" + ] +) + +getMarketPlaceEvent = utterances( + [ + "take me to marketplace", + "take me to market place", + "take me to market", + "take me to shopping", + "what is in marketplace", + "what is in market place", + "what is in market" + ] +) + +cookWithTwoIngredientsEvent = utterances( + [ + "let us cook", + "start cooking", + "cook with two ingredients", + "cook two ingredients", + "switch to coltrane", + "hit coltrane", + "make coltrane DM" + ] +) + +welcome = utterances( + [ + "get me car" + ] +) + +affirmMultipleColorEvent = utterances( + [ + "do it" + ] +) + +informMarketPlaceNameEvent = utterances( + [ + "{fruitName}", + "marketplace name is {fruitName}", + "marketplace is {fruitName}", + "market place is {fruitName}", + "market place name is {fruitName}" + ] +) + +informfruitNameEvent = utterances( + [ + "{fruitName}", + "fruit name is {fruitName}", + "fruit is {fruitName}" + ] +) + +MultipleDialogEvent = utterances( + [ + "i want to buy a fruit" + ] +) + +informColorMultipleEvent = utterances( + [ + "{colorName}", + "color is {colorName}", + "color {colorName}" + ] +) + +informFoodNameEvent = utterances( + [ + "{foodName}", + "food is {foodName}", + "let us make {foodName}" + ] +) + +affirmFruitAPIEvent = utterances( + [ + "uh huh", + "yup" + ] +) + +affirmCookAPIEvent = utterances( + [ + "ok", + "that is ok", + "ok for sure" + ] +) + +GiveMeTodaySpecialsEvent = utterances( + [ + "give me today specials", + "what is special today" + ] +) + +getFruitPriceEvent = utterances( + [ + "what is the price of the fruit", + "what is the price of fruit" + ] +) + +informsignEvent = utterances( + [ + "{sign}", + "sign is {sign}", + "sun sign is {sign}" + ] +) + +informComplexNameEvent = utterances( + [ + "{name}", + "name is {name}", + "i am {name}" + ] +) + +affirmFavColorEvent = utterances( + [ + "correct" + ] +) + +bookFlightEvent = utterances( + [ + "book a flight", + "book flight" + ] +) + +informFromBookFlight = utterances( + [ + "from {source}", + "travel from {source}", + "source is {source}" + ] +) + +informToBookFlight = utterances( + [ + "to {destination}", + "trave to {destination}", + "go to {destination}", + "destination to {destination}" + ] +) + +affirmCabAPIEvent = utterances( + [ + "sure do", + "sure please do", + "roger", + "indeed" + ] +) + +informPickUpFromBookCab = utterances( + [ + "{pickUpFrom}" + ] +) + +informdropToBookCab = utterances( + [ + "{dropTo}" + ] +) + +inform_menu_option = utterances( + [ + "{option}" + ] +) + +menuOptionsQuestion = utterances( + [ + "what options can I change?", + "what kinds of options are there?" + ] +) + +inquireAboutFeedingSizeNoArgs = utterances( + [ + "how many people does that feed", + "Is that enough for two adults and two kids" + ] +) + +specifySpecialName = utterances( + [ + "{name}" + ] +) + +askMenuQuestion = utterances( + [ + "what are your {option}", + "what {option} can i get", + "what types of {option} do you have", + "What kind of {option} do you have" + ] +) + +specifySizeAndToppings = utterances( + [ + "add a {size} {toppings} pizza to my order", + "order a {size} {toppings} pizza", + "I want a {size} {toppings} pizza" + ] +) + +orderSpecificSizePizza = utterances( + [ + "order a {size} pizza", + "I want a {size} pizza" + ] +) + +DummyInvokeOrderCustomizedPizzaReferenceSpecial = utterances( + [ + "dummy invoke needed when offer API is used in NotifySuccess request template + OfferAPI for OrderCustomizedPizzaReferenceSpecial" + ] +) + +startCustomizeFlow = utterances( + [ + "I want to customize a special" + ] +) + +confirmCustomizedSpecial = utterances( + [ + "sounds good", + "perfect", + "go ahead", + "sure", + "yeah", + "ok", + "yep" + ] +) + +specifyQty = utterances( + [ + "{qty} please", + "{qty}", + "give me {qty}", + "I will take {qty}", + "I want {qty}" + ] +) + +customizePizzaReferenceSpecial = utterances( + [ + "let's customize the {name}", + "I want to customize the {name}" + ] +) + +specifyTwoToppings = utterances( + [ + "no, make it {first_topping} and {second_topping}", + "no, {first_topping} and {second_topping}", + "actually make that {first_topping} and {second_topping}", + "change that to {first_topping} and {second_topping}", + "{first_topping} and {second_topping}", + "add {first_topping} and {second_topping}", + "I want {first_topping} and {second_topping}" + ] +) + +Yes = utterances( + [ + "Correct", + "Uh huh", + "Right", + "Yep", + "Yes" + ] +) + +inquireAboutFeedingSize = utterances( + [ + "is a {size} enough for four adults", + "how many people can a {size} feed", + "how many people can {size} pizza feed?" + ] +) + +tested = utterances( + [ + "launch skill" + ] +) + +startTwoToppingPizzaOrder = utterances( + [ + "order a two topping pizza", + "I want a two topping pizza" + ] +) + +specifyToppings = utterances( + [ + "{toppingsList}", + "I'd like {toppingsList}", + "give me {toppingsList}", + "we like {toppingsList}", + "The kids want {toppingsList}" + ] +) + +startPizzaOrder = utterances( + [ + "build my own pizza", + "I need my own custom pizza", + "Add one more order", + "I want another pizza", + "build another pizza", + "create another pizza", + "build a pizza", + "place an order for a pizza", + "add another pizza to my order", + "add another custom pizza to my order", + "create a custom pizza", + "start my pizza order", + "order me a custom pizza", + "order a pizza" + ] +) + +specifySize = utterances( + [ + "change it to {size}", + "make that a {size}", + "change that to a {size} pizza", + "{size}", + "I need a {size} pizza" + ] +) + +specifyCrust = utterances( + [ + "{crust}", + "I need {crust}" + ] +) + +specifyCheese = utterances( + [ + "{cheese}", + "I need {cheese}", + "Please add {cheese}" + ] +) + +confirmPizzaOrder = utterances( + [ + "yes", + "yup", + "go ahead", + "perfect" + ] +) diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/conversations/welcomeAPI.acdl b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/conversations/welcomeAPI.acdl new file mode 100644 index 00000000..bf1baa2f --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/conversations/welcomeAPI.acdl @@ -0,0 +1,34 @@ +namespace welcomeAPi + +import com.amazon.alexa.ask.conversations.Invoke +import com.amazon.alexa.ask.conversations.Notify +import com.amazon.alexa.ask.conversations.expect +import com.amazon.alexa.ask.conversations.response +import com.amazon.alexa.schema.Nothing +import com.amazon.ask.types.builtins.AMAZON.NUMBER +import com.weatherbot.apis.welcomeApi +import com.weatherbot.utteracesets.welcome +import prompts.welcome_apla_custom + +type welcomeApiPayloads { + NUMBER result +} + +dialog Nothing complex() { + sample { + expect( + Invoke, + welcome + ) + resultDam = welcomeApi() + response( + welcome_apla_custom, + Notify { + actionName = welcomeApi + }, + nothing, + nothing, + nothing + ) + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/interactionModels/custom/en-US.json b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/interactionModels/custom/en-US.json new file mode 100644 index 00000000..6a03344f --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/interactionModels/custom/en-US.json @@ -0,0 +1,564 @@ +{ + "interactionModel": { + "languageModel": { + "invocationName": "model feedback test skill five", + "intents": [ + { + "name": "AMAZON.CancelIntent", + "samples": [] + }, + { + "name": "AMAZON.HelpIntent", + "samples": [] + }, + { + "name": "AMAZON.StopIntent", + "samples": [] + }, + { + "name": "NoDialog", + "samples": [ + "show me the wonders" + ] + }, + { + "name": "test", + "samples": [ + "nanum rowdy dhann" + ] + }, + { + "name": "SkillToColtrane", + "samples": [ + "switch to coltrane", + "hit coltrane", + "make coltrane DM" + ] + }, + { + "name": "AMAZON.NavigateHomeIntent", + "samples": [] + }, + { + "name": "AMAZON.FallbackIntent", + "samples": [] + } + ], + "types": [ + { + "values": [ + { + "name": { + "value": "satheesh" + } + }, + { + "name": { + "value": "raman" + } + } + ], + "name": "request_city_apl_displaya" + }, + { + "values": [ + { + "name": { + "value": "satheesh" + } + }, + { + "name": { + "value": "raman" + } + } + ], + "name": "complexNames" + }, + { + "values": [ + { + "name": { + "value": "scorpion" + } + }, + { + "name": { + "value": "aeries" + } + }, + { + "name": { + "value": "virgo" + } + }, + { + "name": { + "value": "cancer" + } + } + ], + "name": "signs" + }, + { + "values": [ + { + "name": { + "value": "almonds" + } + }, + { + "name": { + "value": "bread" + } + }, + { + "name": { + "value": "egg" + } + }, + { + "name": { + "value": "sauce" + } + }, + { + "name": { + "value": "jam" + } + }, + { + "name": { + "value": "cheese" + } + } + ], + "name": "Mix" + }, + { + "values": [ + { + "name": { + "value": "small" + } + }, + { + "name": { + "value": "medium" + } + }, + { + "name": { + "value": "large" + } + }, + { + "name": { + "value": "extra large" + } + } + ], + "name": "size" + }, + { + "values": [ + { + "name": { + "value": "guindy" + } + }, + { + "name": { + "value": "paris" + } + }, + { + "name": { + "value": "anna nagar" + } + }, + { + "name": { + "value": "ramapuram" + } + } + ], + "name": "pickUpFrom" + }, + { + "values": [ + { + "name": { + "value": "dummy value for api response literal property" + } + } + ], + "name": "StringLiteral" + }, + { + "values": [ + { + "name": { + "value": "deep dish" + } + }, + { + "name": { + "value": "regular" + } + }, + { + "name": { + "value": "hand made" + } + }, + { + "name": { + "value": "gluten free" + } + }, + { + "name": { + "value": "thin crust" + } + }, + { + "name": { + "value": "brooklyn style" + } + } + ], + "name": "crust" + }, + { + "values": [ + { + "name": { + "value": "none", + "synonyms": [ + "no cheese", + "dont add cheese", + "nope", + "no" + ] + } + }, + { + "name": { + "value": "light", + "synonyms": [ + "light cheese" + ] + } + }, + { + "name": { + "value": "normal", + "synonyms": [ + "Normal cheese" + ] + } + }, + { + "name": { + "value": "extra", + "synonyms": [ + "Extra cheese" + ] + } + }, + { + "name": { + "value": "double", + "synonyms": [ + "Double cheese" + ] + } + } + ], + "name": "cheese" + }, + { + "values": [ + { + "name": { + "value": "cheese", + "synonyms": [ + "cheeses" + ] + } + }, + { + "name": { + "value": "crust", + "synonyms": [ + "crusts" + ] + } + }, + { + "name": { + "value": "size", + "synonyms": [ + "sizes" + ] + } + } + ], + "name": "option" + }, + { + "values": [ + { + "name": { + "value": "two medium, two topping" + } + }, + { + "name": { + "value": "three cheese delight" + } + }, + { + "name": { + "value": "pepperoni party" + } + }, + { + "name": { + "value": "meat lovers" + } + }, + { + "name": { + "value": "veggie supreme" + } + }, + { + "name": { + "value": "kitchen sink" + } + } + ], + "name": "specialPizzaName" + }, + { + "values": [ + { + "name": { + "value": "onion", + "synonyms": [ + "onions" + ] + } + }, + { + "name": { + "value": "banana peppers", + "synonyms": [ + "banana pepper" + ] + } + }, + { + "name": { + "value": "olives", + "synonyms": [ + "black olives" + ] + } + }, + { + "name": { + "value": "mushrooms", + "synonyms": [ + "mushroom" + ] + } + }, + { + "name": { + "value": "pineapple" + } + }, + { + "name": { + "value": "spinach", + "synonyms": [ + "spinach" + ] + } + } + ], + "name": "toppings" + }, + { + "values": [ + { + "name": { + "value": "failure" + } + }, + { + "name": { + "value": "failed" + } + }, + { + "name": { + "value": "success" + } + } + ], + "name": "orderStatus" + }, + { + "values": [ + { + "name": { + "value": "san diego" + } + }, + { + "name": { + "value": "los angeles" + } + }, + { + "name": { + "value": "denver" + } + }, + { + "name": { + "value": "paris" + } + }, + { + "name": { + "value": "seattle" + } + }, + { + "name": { + "value": "portland" + } + }, + { + "name": { + "value": "ramapuram" + } + }, + { + "name": { + "value": "chennai" + } + } + ], + "name": "city_name_one" + }, + { + "values": [ + { + "name": { + "value": "denver" + } + }, + { + "name": { + "value": "sydney" + } + }, + { + "name": { + "value": "portland" + } + }, + { + "name": { + "value": "new york" + } + }, + { + "name": { + "value": "visakhapatnam" + } + }, + { + "name": { + "value": "bangalore" + } + }, + { + "name": { + "value": "mumbai" + } + }, + { + "name": { + "value": "seattle" + } + }, + { + "name": { + "value": "chennai" + } + } + ], + "name": "customCity" + }, + { + "values": [ + { + "name": { + "value": "denver" + } + }, + { + "name": { + "value": "sydney" + } + }, + { + "name": { + "value": "portland" + } + }, + { + "name": { + "value": "new york" + } + }, + { + "name": { + "value": "visakhapatnam" + } + }, + { + "name": { + "value": "bangalore" + } + }, + { + "name": { + "value": "mumbai" + } + }, + { + "name": { + "value": "seattle" + } + }, + { + "name": { + "value": "chennai" + } + } + ], + "name": "city_name_two" + } + ] + } + }, + "version": "4" +} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/display/confirm_city_apl_display/document.json b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/display/confirm_city_apl_display/document.json new file mode 100644 index 00000000..741e1a5f --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/display/confirm_city_apl_display/document.json @@ -0,0 +1,358 @@ +{ + "type": "APL", + "version": "1.1", + "settings": {}, + "theme": "dark", + "import": [ + { + "name": "alexa-layouts", + "version": "1.0.0" + } + ], + "resources": [ + { + "description": "Stock color for the light theme", + "colors": { + "colorTextPrimary": "#151920" + } + }, + { + "description": "Stock color for the dark theme", + "when": "${viewport.theme == 'dark'}", + "colors": { + "colorTextPrimary": "#f0f1ef" + } + }, + { + "description": "Standard font sizes", + "dimensions": { + "textSizeBody": 48, + "textSizePrimary": 27, + "textSizeSecondary": 23, + "textSizeDetails": 20, + "textSizeSecondaryHint": 25 + } + }, + { + "description": "Common spacing values", + "dimensions": { + "spacingThin": 6, + "spacingSmall": 12, + "spacingMedium": 24, + "spacingLarge": 48, + "spacingExtraLarge": 72 + } + }, + { + "description": "Common margins and padding", + "dimensions": { + "marginTop": 40, + "marginLeft": 60, + "marginRight": 60, + "marginBottom": 40 + } + } + ], + "styles": { + "textStyleBase": { + "description": "Base font description; set color", + "values": [ + { + "color": "@colorTextPrimary" + } + ] + }, + "textStyleBase0": { + "description": "Thin version of basic font", + "extend": "textStyleBase", + "values": { + "fontWeight": "100" + } + }, + "textStyleBase1": { + "description": "Light version of basic font", + "extend": "textStyleBase", + "values": { + "fontWeight": "300" + } + }, + "textStyleBase2": { + "description": "Regular version of basic font", + "extend": "textStyleBase", + "values": { + "fontWeight": "500" + } + }, + "mixinBody": { + "values": { + "fontSize": "@textSizeBody" + } + }, + "mixinPrimary": { + "values": { + "fontSize": "@textSizePrimary" + } + }, + "mixinDetails": { + "values": { + "fontSize": "@textSizeDetails" + } + }, + "mixinSecondary": { + "values": { + "fontSize": "@textSizeSecondary" + } + }, + "textStylePrimary": { + "extend": [ + "textStyleBase1", + "mixinPrimary" + ] + }, + "textStyleSecondary": { + "extend": [ + "textStyleBase0", + "mixinSecondary" + ] + }, + "textStyleBody": { + "extend": [ + "textStyleBase1", + "mixinBody" + ] + }, + "textStyleSecondaryHint": { + "values": { + "fontFamily": "Bookerly", + "fontStyle": "italic", + "fontSize": "@textSizeSecondaryHint", + "color": "@colorTextPrimary" + } + }, + "textStyleDetails": { + "extend": [ + "textStyleBase2", + "mixinDetails" + ] + } + }, + "onMount": [], + "graphics": {}, + "commands": {}, + "layouts": { + "ListTemplate1": { + "parameters": [ + "backgroundImage", + "title", + "logo", + "hintText", + "listData" + ], + "item": [ + { + "type": "Container", + "width": "100vw", + "height": "100vh", + "direction": "column", + "items": [ + { + "type": "Image", + "source": "${backgroundImage}", + "scale": "best-fill", + "width": "100vw", + "height": "100vh", + "position": "absolute" + }, + { + "type": "AlexaHeader", + "headerTitle": "${title}", + "headerAttributionImage": "${logo}" + }, + { + "type": "Sequence", + "grow": 1, + "height": "80vh", + "scrollDirection": "vertical", + "paddingLeft": "@marginLeft", + "paddingRight": "@marginRight", + "data": "${listData}", + "numbered": true, + "items": [ + { + "type": "VerticalListItem", + "image": "${data.image.sources[0].url}", + "primaryText": "${data.textContent.primaryText.text}", + "secondaryText": "${data.textContent.secondaryText.text}", + "tertiaryText": "${data.textContent.tertiaryText.text}" + } + ] + } + ] + } + ] + }, + "VerticalListItem": { + "parameters": [ + "primaryText", + "secondaryText", + "tertiaryText", + "image" + ], + "item": [ + { + "when": "${viewport.shape == 'round'}", + "type": "Container", + "direction": "row", + "height": 200, + "width": 500, + "alignItems": "center", + "items": [ + { + "type": "Text", + "text": "${ordinal}", + "paddingBottom": "20dp", + "color": "white", + "spacing": "5dp" + }, + { + "type": "Image", + "when": "${image}", + "source": "${image}", + "height": 150, + "width": 150, + "spacing": 15, + "scale": "best-fit", + "align": "top" + }, + { + "type": "Container", + "direction": "column", + "spacing": 25, + "items": [ + { + "type": "Text", + "text": "${primaryText}", + "style": "textStyleDetail", + "grow": 1, + "shrink": 1, + "fontWeight": "300", + "maxLines": 1 + }, + { + "type": "Text", + "text": "${secondaryText}", + "style": "textStyleCaption", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + }, + { + "type": "Text", + "text": "${tertiaryText}", + "style": "textStyleDetails", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + } + ] + } + ] + }, + { + "type": "Container", + "direction": "row", + "height": 125, + "width": 800, + "alignItems": "center", + "items": [ + { + "type": "Text", + "text": "${ordinal}", + "paddingBottom": "20dp", + "color": "white", + "spacing": "5dp" + }, + { + "type": "Image", + "when": "${image}", + "source": "${image}", + "height": 100, + "width": 100, + "align": "top", + "spacing": 50, + "scale": "best-fit" + }, + { + "type": "Container", + "spacing": 30, + "direction": "column", + "items": [ + { + "type": "Text", + "text": "${primaryText}", + "style": "textStyleBody", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + }, + { + "type": "Text", + "text": "${secondaryText}", + "style": "textStyleDetails", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + } + ] + }, + { + "type": "Text", + "text": "${tertiaryText}", + "style": "textStyleBody", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "textAlign": "right", + "maxLines": 1 + } + ] + } + ] + } + }, + "mainTemplate": { + "parameters": [ + "payload" + ], + "item": [ + { + "type": "Container", + "id": "BookCabSimpleDialogAPL", + "items": [ + { + "type": "TouchWrapper", + "onPress": { + "type": "SendEvent", + "arguments": [ + "delegateToColtraneOld" + ] + }, + "item": { + "type": "Text", + "id": "BookCabSimpleDialogAPL", + "paddingTop": "100", + "paddingLeft": "100", + "color": "green", + "size": 50, + "text": "which city ?" + } + } + ] + } + ] + } +} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/display/confirm_date_apl_display/document.json b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/display/confirm_date_apl_display/document.json new file mode 100644 index 00000000..9ff71e5c --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/display/confirm_date_apl_display/document.json @@ -0,0 +1,358 @@ +{ + "type": "APL", + "version": "1.1", + "settings": {}, + "theme": "dark", + "import": [ + { + "name": "alexa-layouts", + "version": "1.0.0" + } + ], + "resources": [ + { + "description": "Stock color for the light theme", + "colors": { + "colorTextPrimary": "#151920" + } + }, + { + "description": "Stock color for the dark theme", + "when": "${viewport.theme == 'dark'}", + "colors": { + "colorTextPrimary": "#f0f1ef" + } + }, + { + "description": "Standard font sizes", + "dimensions": { + "textSizeBody": 48, + "textSizePrimary": 27, + "textSizeSecondary": 23, + "textSizeDetails": 20, + "textSizeSecondaryHint": 25 + } + }, + { + "description": "Common spacing values", + "dimensions": { + "spacingThin": 6, + "spacingSmall": 12, + "spacingMedium": 24, + "spacingLarge": 48, + "spacingExtraLarge": 72 + } + }, + { + "description": "Common margins and padding", + "dimensions": { + "marginTop": 40, + "marginLeft": 60, + "marginRight": 60, + "marginBottom": 40 + } + } + ], + "styles": { + "textStyleBase": { + "description": "Base font description; set color", + "values": [ + { + "color": "@colorTextPrimary" + } + ] + }, + "textStyleBase0": { + "description": "Thin version of basic font", + "extend": "textStyleBase", + "values": { + "fontWeight": "100" + } + }, + "textStyleBase1": { + "description": "Light version of basic font", + "extend": "textStyleBase", + "values": { + "fontWeight": "300" + } + }, + "textStyleBase2": { + "description": "Regular version of basic font", + "extend": "textStyleBase", + "values": { + "fontWeight": "500" + } + }, + "mixinBody": { + "values": { + "fontSize": "@textSizeBody" + } + }, + "mixinPrimary": { + "values": { + "fontSize": "@textSizePrimary" + } + }, + "mixinDetails": { + "values": { + "fontSize": "@textSizeDetails" + } + }, + "mixinSecondary": { + "values": { + "fontSize": "@textSizeSecondary" + } + }, + "textStylePrimary": { + "extend": [ + "textStyleBase1", + "mixinPrimary" + ] + }, + "textStyleSecondary": { + "extend": [ + "textStyleBase0", + "mixinSecondary" + ] + }, + "textStyleBody": { + "extend": [ + "textStyleBase1", + "mixinBody" + ] + }, + "textStyleSecondaryHint": { + "values": { + "fontFamily": "Bookerly", + "fontStyle": "italic", + "fontSize": "@textSizeSecondaryHint", + "color": "@colorTextPrimary" + } + }, + "textStyleDetails": { + "extend": [ + "textStyleBase2", + "mixinDetails" + ] + } + }, + "onMount": [], + "graphics": {}, + "commands": {}, + "layouts": { + "ListTemplate1": { + "parameters": [ + "backgroundImage", + "title", + "logo", + "hintText", + "listData" + ], + "item": [ + { + "type": "Container", + "width": "100vw", + "height": "100vh", + "direction": "column", + "items": [ + { + "type": "Image", + "source": "${backgroundImage}", + "scale": "best-fill", + "width": "100vw", + "height": "100vh", + "position": "absolute" + }, + { + "type": "AlexaHeader", + "headerTitle": "${title}", + "headerAttributionImage": "${logo}" + }, + { + "type": "Sequence", + "grow": 1, + "height": "80vh", + "scrollDirection": "vertical", + "paddingLeft": "@marginLeft", + "paddingRight": "@marginRight", + "data": "${listData}", + "numbered": true, + "items": [ + { + "type": "VerticalListItem", + "image": "${data.image.sources[0].url}", + "primaryText": "${data.textContent.primaryText.text}", + "secondaryText": "${data.textContent.secondaryText.text}", + "tertiaryText": "${data.textContent.tertiaryText.text}" + } + ] + } + ] + } + ] + }, + "VerticalListItem": { + "parameters": [ + "primaryText", + "secondaryText", + "tertiaryText", + "image" + ], + "item": [ + { + "when": "${viewport.shape == 'round'}", + "type": "Container", + "direction": "row", + "height": 200, + "width": 500, + "alignItems": "center", + "items": [ + { + "type": "Text", + "text": "${ordinal}", + "paddingBottom": "20dp", + "color": "white", + "spacing": "5dp" + }, + { + "type": "Image", + "when": "${image}", + "source": "${image}", + "height": 150, + "width": 150, + "spacing": 15, + "scale": "best-fit", + "align": "top" + }, + { + "type": "Container", + "direction": "column", + "spacing": 25, + "items": [ + { + "type": "Text", + "text": "${primaryText}", + "style": "textStyleDetail", + "grow": 1, + "shrink": 1, + "fontWeight": "300", + "maxLines": 1 + }, + { + "type": "Text", + "text": "${secondaryText}", + "style": "textStyleCaption", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + }, + { + "type": "Text", + "text": "${tertiaryText}", + "style": "textStyleDetails", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + } + ] + } + ] + }, + { + "type": "Container", + "direction": "row", + "height": 125, + "width": 800, + "alignItems": "center", + "items": [ + { + "type": "Text", + "text": "${ordinal}", + "paddingBottom": "20dp", + "color": "white", + "spacing": "5dp" + }, + { + "type": "Image", + "when": "${image}", + "source": "${image}", + "height": 100, + "width": 100, + "align": "top", + "spacing": 50, + "scale": "best-fit" + }, + { + "type": "Container", + "spacing": 30, + "direction": "column", + "items": [ + { + "type": "Text", + "text": "${primaryText}", + "style": "textStyleBody", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + }, + { + "type": "Text", + "text": "${secondaryText}", + "style": "textStyleDetails", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + } + ] + }, + { + "type": "Text", + "text": "${tertiaryText}", + "style": "textStyleBody", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "textAlign": "right", + "maxLines": 1 + } + ] + } + ] + } + }, + "mainTemplate": { + "parameters": [ + "payload" + ], + "item": [ + { + "type": "Container", + "id": "BookCabSimpleDialogAPL", + "items": [ + { + "type": "TouchWrapper", + "onPress": { + "type": "SendEvent", + "arguments": [ + "delegateToColtraneOld" + ] + }, + "item": { + "type": "Text", + "id": "BookCabSimpleDialogAPL", + "paddingTop": "100", + "paddingLeft": "100", + "color": "green", + "size": 50, + "text": "which date ?" + } + } + ] + } + ] + } + } \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/display/confirm_weather_apla_display/document.json b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/display/confirm_weather_apla_display/document.json new file mode 100644 index 00000000..1974945a --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/display/confirm_weather_apla_display/document.json @@ -0,0 +1,412 @@ +{ + "type": "APL", + "version": "1.1", + "settings": {}, + "theme": "dark", + "import": [ + { + "name": "alexa-layouts", + "version": "1.0.0" + } + ], + "resources": [ + { + "description": "Stock color for the light theme", + "colors": { + "colorTextPrimary": "#151920" + } + }, + { + "description": "Stock color for the dark theme", + "when": "${viewport.theme == 'dark'}", + "colors": { + "colorTextPrimary": "#f0f1ef" + } + }, + { + "description": "Standard font sizes", + "dimensions": { + "textSizeBody": 48, + "textSizePrimary": 27, + "textSizeSecondary": 23, + "textSizeDetails": 20, + "textSizeSecondaryHint": 25 + } + }, + { + "description": "Common spacing values", + "dimensions": { + "spacingThin": 6, + "spacingSmall": 12, + "spacingMedium": 24, + "spacingLarge": 48, + "spacingExtraLarge": 72 + } + }, + { + "description": "Common margins and padding", + "dimensions": { + "marginTop": 40, + "marginLeft": 60, + "marginRight": 60, + "marginBottom": 40 + } + } + ], + "styles": { + "textStyleBase": { + "description": "Base font description; set color", + "values": [ + { + "color": "@colorTextPrimary" + } + ] + }, + "textStyleBase0": { + "description": "Thin version of basic font", + "extend": "textStyleBase", + "values": { + "fontWeight": "100" + } + }, + "textStyleBase1": { + "description": "Light version of basic font", + "extend": "textStyleBase", + "values": { + "fontWeight": "300" + } + }, + "textStyleBase2": { + "description": "Regular version of basic font", + "extend": "textStyleBase", + "values": { + "fontWeight": "500" + } + }, + "mixinBody": { + "values": { + "fontSize": "@textSizeBody" + } + }, + "mixinPrimary": { + "values": { + "fontSize": "@textSizePrimary" + } + }, + "mixinDetails": { + "values": { + "fontSize": "@textSizeDetails" + } + }, + "mixinSecondary": { + "values": { + "fontSize": "@textSizeSecondary" + } + }, + "textStylePrimary": { + "extend": [ + "textStyleBase1", + "mixinPrimary" + ] + }, + "textStyleSecondary": { + "extend": [ + "textStyleBase0", + "mixinSecondary" + ] + }, + "textStyleBody": { + "extend": [ + "textStyleBase1", + "mixinBody" + ] + }, + "textStyleSecondaryHint": { + "values": { + "fontFamily": "Bookerly", + "fontStyle": "italic", + "fontSize": "@textSizeSecondaryHint", + "color": "@colorTextPrimary" + } + }, + "textStyleDetails": { + "extend": [ + "textStyleBase2", + "mixinDetails" + ] + } + }, + "onMount": [], + "graphics": {}, + "commands": {}, + "layouts": { + "ListTemplate1": { + "parameters": [ + "backgroundImage", + "title", + "logo", + "hintText", + "listData" + ], + "item": [ + { + "type": "Container", + "width": "100vw", + "height": "100vh", + "direction": "column", + "items": [ + { + "type": "Image", + "source": "${backgroundImage}", + "scale": "best-fill", + "width": "100vw", + "height": "100vh", + "position": "absolute" + }, + { + "type": "AlexaHeader", + "headerTitle": "${title}", + "headerAttributionImage": "${logo}" + }, + { + "type": "Sequence", + "grow": 1, + "height": "80vh", + "scrollDirection": "vertical", + "paddingLeft": "@marginLeft", + "paddingRight": "@marginRight", + "data": "${listData}", + "numbered": true, + "items": [ + { + "type": "VerticalListItem", + "image": "${data.image.sources[0].url}", + "primaryText": "${data.textContent.primaryText.text}", + "secondaryText": "${data.textContent.secondaryText.text}", + "tertiaryText": "${data.textContent.tertiaryText.text}" + } + ] + } + ] + } + ] + }, + "VerticalListItem": { + "parameters": [ + "primaryText", + "secondaryText", + "tertiaryText", + "image" + ], + "item": [ + { + "when": "${viewport.shape == 'round'}", + "type": "Container", + "direction": "row", + "height": 200, + "width": 500, + "alignItems": "center", + "items": [ + { + "type": "Text", + "text": "${ordinal}", + "paddingBottom": "20dp", + "color": "white", + "spacing": "5dp" + }, + { + "type": "Image", + "when": "${image}", + "source": "${image}", + "height": 150, + "width": 150, + "spacing": 15, + "scale": "best-fit", + "align": "top" + }, + { + "type": "Container", + "direction": "column", + "spacing": 25, + "items": [ + { + "type": "Text", + "text": "${primaryText}", + "style": "textStyleDetail", + "grow": 1, + "shrink": 1, + "fontWeight": "300", + "maxLines": 1 + }, + { + "type": "Text", + "text": "${secondaryText}", + "style": "textStyleCaption", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + }, + { + "type": "Text", + "text": "${tertiaryText}", + "style": "textStyleDetails", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + } + ] + } + ] + }, + { + "type": "Container", + "direction": "row", + "height": 125, + "width": 800, + "alignItems": "center", + "items": [ + { + "type": "Text", + "text": "${ordinal}", + "paddingBottom": "20dp", + "color": "white", + "spacing": "5dp" + }, + { + "type": "Image", + "when": "${image}", + "source": "${image}", + "height": 100, + "width": 100, + "align": "top", + "spacing": 50, + "scale": "best-fit" + }, + { + "type": "Container", + "spacing": 30, + "direction": "column", + "items": [ + { + "type": "Text", + "text": "${primaryText}", + "style": "textStyleBody", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + }, + { + "type": "Text", + "text": "${secondaryText}", + "style": "textStyleDetails", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + } + ] + }, + { + "type": "Text", + "text": "${tertiaryText}", + "style": "textStyleBody", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "textAlign": "right", + "maxLines": 1 + } + ] + } + ] + } + }, + "mainTemplate": { + "parameters": [ + "payload" + ], + "item": [ + { + "type": "Container", + "id": "BookCabSimpleDialogAPL", + "items": [ + { + "type": "TouchWrapper", + "onPress": { + "type": "SendEvent", + "arguments": [ + "delegateToSkillNew" + ] + }, + "item": { + "type": "Text", + "id": "BookCabSimpleDialogAPL", + "paddingTop": "100", + "paddingLeft": "100", + "color": "green", + "size": 50, + "text": "delegateToSkillNew" + } + }, + { + "type": "TouchWrapper", + "onPress": { + "type": "SendEvent", + "arguments": [ + "delegateToSkillOld" + ] + }, + "item": { + "type": "Text", + "id": "BookCabSimpleDialogAPL", + "paddingTop": "100", + "paddingLeft": "100", + "color": "green", + "size": 50, + "text": "delegateToSkillOld" + } + }, + { + "type": "TouchWrapper", + "onPress": { + "type": "SendEvent", + "arguments": [ + "delegateToColtraneNew" + ] + }, + "item": { + "type": "Text", + "id": "BookCabSimpleDialogAPL", + "paddingTop": "100", + "paddingLeft": "100", + "color": "green", + "size": 50, + "text": "delegateToColtraneNew" + } + }, + { + "type": "TouchWrapper", + "onPress": { + "type": "SendEvent", + "arguments": [ + "delegateToColtraneOld" + ] + }, + "item": { + "type": "Text", + "id": "BookCabSimpleDialogAPL", + "paddingTop": "100", + "paddingLeft": "100", + "color": "green", + "size": 50, + "text": "delegateToColtraneOld" + } + } + ] + } + ] + } +} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/display/request_city_apl_display/document.json b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/display/request_city_apl_display/document.json new file mode 100644 index 00000000..741e1a5f --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/display/request_city_apl_display/document.json @@ -0,0 +1,358 @@ +{ + "type": "APL", + "version": "1.1", + "settings": {}, + "theme": "dark", + "import": [ + { + "name": "alexa-layouts", + "version": "1.0.0" + } + ], + "resources": [ + { + "description": "Stock color for the light theme", + "colors": { + "colorTextPrimary": "#151920" + } + }, + { + "description": "Stock color for the dark theme", + "when": "${viewport.theme == 'dark'}", + "colors": { + "colorTextPrimary": "#f0f1ef" + } + }, + { + "description": "Standard font sizes", + "dimensions": { + "textSizeBody": 48, + "textSizePrimary": 27, + "textSizeSecondary": 23, + "textSizeDetails": 20, + "textSizeSecondaryHint": 25 + } + }, + { + "description": "Common spacing values", + "dimensions": { + "spacingThin": 6, + "spacingSmall": 12, + "spacingMedium": 24, + "spacingLarge": 48, + "spacingExtraLarge": 72 + } + }, + { + "description": "Common margins and padding", + "dimensions": { + "marginTop": 40, + "marginLeft": 60, + "marginRight": 60, + "marginBottom": 40 + } + } + ], + "styles": { + "textStyleBase": { + "description": "Base font description; set color", + "values": [ + { + "color": "@colorTextPrimary" + } + ] + }, + "textStyleBase0": { + "description": "Thin version of basic font", + "extend": "textStyleBase", + "values": { + "fontWeight": "100" + } + }, + "textStyleBase1": { + "description": "Light version of basic font", + "extend": "textStyleBase", + "values": { + "fontWeight": "300" + } + }, + "textStyleBase2": { + "description": "Regular version of basic font", + "extend": "textStyleBase", + "values": { + "fontWeight": "500" + } + }, + "mixinBody": { + "values": { + "fontSize": "@textSizeBody" + } + }, + "mixinPrimary": { + "values": { + "fontSize": "@textSizePrimary" + } + }, + "mixinDetails": { + "values": { + "fontSize": "@textSizeDetails" + } + }, + "mixinSecondary": { + "values": { + "fontSize": "@textSizeSecondary" + } + }, + "textStylePrimary": { + "extend": [ + "textStyleBase1", + "mixinPrimary" + ] + }, + "textStyleSecondary": { + "extend": [ + "textStyleBase0", + "mixinSecondary" + ] + }, + "textStyleBody": { + "extend": [ + "textStyleBase1", + "mixinBody" + ] + }, + "textStyleSecondaryHint": { + "values": { + "fontFamily": "Bookerly", + "fontStyle": "italic", + "fontSize": "@textSizeSecondaryHint", + "color": "@colorTextPrimary" + } + }, + "textStyleDetails": { + "extend": [ + "textStyleBase2", + "mixinDetails" + ] + } + }, + "onMount": [], + "graphics": {}, + "commands": {}, + "layouts": { + "ListTemplate1": { + "parameters": [ + "backgroundImage", + "title", + "logo", + "hintText", + "listData" + ], + "item": [ + { + "type": "Container", + "width": "100vw", + "height": "100vh", + "direction": "column", + "items": [ + { + "type": "Image", + "source": "${backgroundImage}", + "scale": "best-fill", + "width": "100vw", + "height": "100vh", + "position": "absolute" + }, + { + "type": "AlexaHeader", + "headerTitle": "${title}", + "headerAttributionImage": "${logo}" + }, + { + "type": "Sequence", + "grow": 1, + "height": "80vh", + "scrollDirection": "vertical", + "paddingLeft": "@marginLeft", + "paddingRight": "@marginRight", + "data": "${listData}", + "numbered": true, + "items": [ + { + "type": "VerticalListItem", + "image": "${data.image.sources[0].url}", + "primaryText": "${data.textContent.primaryText.text}", + "secondaryText": "${data.textContent.secondaryText.text}", + "tertiaryText": "${data.textContent.tertiaryText.text}" + } + ] + } + ] + } + ] + }, + "VerticalListItem": { + "parameters": [ + "primaryText", + "secondaryText", + "tertiaryText", + "image" + ], + "item": [ + { + "when": "${viewport.shape == 'round'}", + "type": "Container", + "direction": "row", + "height": 200, + "width": 500, + "alignItems": "center", + "items": [ + { + "type": "Text", + "text": "${ordinal}", + "paddingBottom": "20dp", + "color": "white", + "spacing": "5dp" + }, + { + "type": "Image", + "when": "${image}", + "source": "${image}", + "height": 150, + "width": 150, + "spacing": 15, + "scale": "best-fit", + "align": "top" + }, + { + "type": "Container", + "direction": "column", + "spacing": 25, + "items": [ + { + "type": "Text", + "text": "${primaryText}", + "style": "textStyleDetail", + "grow": 1, + "shrink": 1, + "fontWeight": "300", + "maxLines": 1 + }, + { + "type": "Text", + "text": "${secondaryText}", + "style": "textStyleCaption", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + }, + { + "type": "Text", + "text": "${tertiaryText}", + "style": "textStyleDetails", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + } + ] + } + ] + }, + { + "type": "Container", + "direction": "row", + "height": 125, + "width": 800, + "alignItems": "center", + "items": [ + { + "type": "Text", + "text": "${ordinal}", + "paddingBottom": "20dp", + "color": "white", + "spacing": "5dp" + }, + { + "type": "Image", + "when": "${image}", + "source": "${image}", + "height": 100, + "width": 100, + "align": "top", + "spacing": 50, + "scale": "best-fit" + }, + { + "type": "Container", + "spacing": 30, + "direction": "column", + "items": [ + { + "type": "Text", + "text": "${primaryText}", + "style": "textStyleBody", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + }, + { + "type": "Text", + "text": "${secondaryText}", + "style": "textStyleDetails", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + } + ] + }, + { + "type": "Text", + "text": "${tertiaryText}", + "style": "textStyleBody", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "textAlign": "right", + "maxLines": 1 + } + ] + } + ] + } + }, + "mainTemplate": { + "parameters": [ + "payload" + ], + "item": [ + { + "type": "Container", + "id": "BookCabSimpleDialogAPL", + "items": [ + { + "type": "TouchWrapper", + "onPress": { + "type": "SendEvent", + "arguments": [ + "delegateToColtraneOld" + ] + }, + "item": { + "type": "Text", + "id": "BookCabSimpleDialogAPL", + "paddingTop": "100", + "paddingLeft": "100", + "color": "green", + "size": 50, + "text": "which city ?" + } + } + ] + } + ] + } +} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/display/request_date_apl_display/document.json b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/display/request_date_apl_display/document.json new file mode 100644 index 00000000..9ff71e5c --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/display/request_date_apl_display/document.json @@ -0,0 +1,358 @@ +{ + "type": "APL", + "version": "1.1", + "settings": {}, + "theme": "dark", + "import": [ + { + "name": "alexa-layouts", + "version": "1.0.0" + } + ], + "resources": [ + { + "description": "Stock color for the light theme", + "colors": { + "colorTextPrimary": "#151920" + } + }, + { + "description": "Stock color for the dark theme", + "when": "${viewport.theme == 'dark'}", + "colors": { + "colorTextPrimary": "#f0f1ef" + } + }, + { + "description": "Standard font sizes", + "dimensions": { + "textSizeBody": 48, + "textSizePrimary": 27, + "textSizeSecondary": 23, + "textSizeDetails": 20, + "textSizeSecondaryHint": 25 + } + }, + { + "description": "Common spacing values", + "dimensions": { + "spacingThin": 6, + "spacingSmall": 12, + "spacingMedium": 24, + "spacingLarge": 48, + "spacingExtraLarge": 72 + } + }, + { + "description": "Common margins and padding", + "dimensions": { + "marginTop": 40, + "marginLeft": 60, + "marginRight": 60, + "marginBottom": 40 + } + } + ], + "styles": { + "textStyleBase": { + "description": "Base font description; set color", + "values": [ + { + "color": "@colorTextPrimary" + } + ] + }, + "textStyleBase0": { + "description": "Thin version of basic font", + "extend": "textStyleBase", + "values": { + "fontWeight": "100" + } + }, + "textStyleBase1": { + "description": "Light version of basic font", + "extend": "textStyleBase", + "values": { + "fontWeight": "300" + } + }, + "textStyleBase2": { + "description": "Regular version of basic font", + "extend": "textStyleBase", + "values": { + "fontWeight": "500" + } + }, + "mixinBody": { + "values": { + "fontSize": "@textSizeBody" + } + }, + "mixinPrimary": { + "values": { + "fontSize": "@textSizePrimary" + } + }, + "mixinDetails": { + "values": { + "fontSize": "@textSizeDetails" + } + }, + "mixinSecondary": { + "values": { + "fontSize": "@textSizeSecondary" + } + }, + "textStylePrimary": { + "extend": [ + "textStyleBase1", + "mixinPrimary" + ] + }, + "textStyleSecondary": { + "extend": [ + "textStyleBase0", + "mixinSecondary" + ] + }, + "textStyleBody": { + "extend": [ + "textStyleBase1", + "mixinBody" + ] + }, + "textStyleSecondaryHint": { + "values": { + "fontFamily": "Bookerly", + "fontStyle": "italic", + "fontSize": "@textSizeSecondaryHint", + "color": "@colorTextPrimary" + } + }, + "textStyleDetails": { + "extend": [ + "textStyleBase2", + "mixinDetails" + ] + } + }, + "onMount": [], + "graphics": {}, + "commands": {}, + "layouts": { + "ListTemplate1": { + "parameters": [ + "backgroundImage", + "title", + "logo", + "hintText", + "listData" + ], + "item": [ + { + "type": "Container", + "width": "100vw", + "height": "100vh", + "direction": "column", + "items": [ + { + "type": "Image", + "source": "${backgroundImage}", + "scale": "best-fill", + "width": "100vw", + "height": "100vh", + "position": "absolute" + }, + { + "type": "AlexaHeader", + "headerTitle": "${title}", + "headerAttributionImage": "${logo}" + }, + { + "type": "Sequence", + "grow": 1, + "height": "80vh", + "scrollDirection": "vertical", + "paddingLeft": "@marginLeft", + "paddingRight": "@marginRight", + "data": "${listData}", + "numbered": true, + "items": [ + { + "type": "VerticalListItem", + "image": "${data.image.sources[0].url}", + "primaryText": "${data.textContent.primaryText.text}", + "secondaryText": "${data.textContent.secondaryText.text}", + "tertiaryText": "${data.textContent.tertiaryText.text}" + } + ] + } + ] + } + ] + }, + "VerticalListItem": { + "parameters": [ + "primaryText", + "secondaryText", + "tertiaryText", + "image" + ], + "item": [ + { + "when": "${viewport.shape == 'round'}", + "type": "Container", + "direction": "row", + "height": 200, + "width": 500, + "alignItems": "center", + "items": [ + { + "type": "Text", + "text": "${ordinal}", + "paddingBottom": "20dp", + "color": "white", + "spacing": "5dp" + }, + { + "type": "Image", + "when": "${image}", + "source": "${image}", + "height": 150, + "width": 150, + "spacing": 15, + "scale": "best-fit", + "align": "top" + }, + { + "type": "Container", + "direction": "column", + "spacing": 25, + "items": [ + { + "type": "Text", + "text": "${primaryText}", + "style": "textStyleDetail", + "grow": 1, + "shrink": 1, + "fontWeight": "300", + "maxLines": 1 + }, + { + "type": "Text", + "text": "${secondaryText}", + "style": "textStyleCaption", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + }, + { + "type": "Text", + "text": "${tertiaryText}", + "style": "textStyleDetails", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + } + ] + } + ] + }, + { + "type": "Container", + "direction": "row", + "height": 125, + "width": 800, + "alignItems": "center", + "items": [ + { + "type": "Text", + "text": "${ordinal}", + "paddingBottom": "20dp", + "color": "white", + "spacing": "5dp" + }, + { + "type": "Image", + "when": "${image}", + "source": "${image}", + "height": 100, + "width": 100, + "align": "top", + "spacing": 50, + "scale": "best-fit" + }, + { + "type": "Container", + "spacing": 30, + "direction": "column", + "items": [ + { + "type": "Text", + "text": "${primaryText}", + "style": "textStyleBody", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + }, + { + "type": "Text", + "text": "${secondaryText}", + "style": "textStyleDetails", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + } + ] + }, + { + "type": "Text", + "text": "${tertiaryText}", + "style": "textStyleBody", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "textAlign": "right", + "maxLines": 1 + } + ] + } + ] + } + }, + "mainTemplate": { + "parameters": [ + "payload" + ], + "item": [ + { + "type": "Container", + "id": "BookCabSimpleDialogAPL", + "items": [ + { + "type": "TouchWrapper", + "onPress": { + "type": "SendEvent", + "arguments": [ + "delegateToColtraneOld" + ] + }, + "item": { + "type": "Text", + "id": "BookCabSimpleDialogAPL", + "paddingTop": "100", + "paddingLeft": "100", + "color": "green", + "size": 50, + "text": "which date ?" + } + } + ] + } + ] + } + } \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/display/weather_success_apl_display/document.json b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/display/weather_success_apl_display/document.json new file mode 100644 index 00000000..1974945a --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/display/weather_success_apl_display/document.json @@ -0,0 +1,412 @@ +{ + "type": "APL", + "version": "1.1", + "settings": {}, + "theme": "dark", + "import": [ + { + "name": "alexa-layouts", + "version": "1.0.0" + } + ], + "resources": [ + { + "description": "Stock color for the light theme", + "colors": { + "colorTextPrimary": "#151920" + } + }, + { + "description": "Stock color for the dark theme", + "when": "${viewport.theme == 'dark'}", + "colors": { + "colorTextPrimary": "#f0f1ef" + } + }, + { + "description": "Standard font sizes", + "dimensions": { + "textSizeBody": 48, + "textSizePrimary": 27, + "textSizeSecondary": 23, + "textSizeDetails": 20, + "textSizeSecondaryHint": 25 + } + }, + { + "description": "Common spacing values", + "dimensions": { + "spacingThin": 6, + "spacingSmall": 12, + "spacingMedium": 24, + "spacingLarge": 48, + "spacingExtraLarge": 72 + } + }, + { + "description": "Common margins and padding", + "dimensions": { + "marginTop": 40, + "marginLeft": 60, + "marginRight": 60, + "marginBottom": 40 + } + } + ], + "styles": { + "textStyleBase": { + "description": "Base font description; set color", + "values": [ + { + "color": "@colorTextPrimary" + } + ] + }, + "textStyleBase0": { + "description": "Thin version of basic font", + "extend": "textStyleBase", + "values": { + "fontWeight": "100" + } + }, + "textStyleBase1": { + "description": "Light version of basic font", + "extend": "textStyleBase", + "values": { + "fontWeight": "300" + } + }, + "textStyleBase2": { + "description": "Regular version of basic font", + "extend": "textStyleBase", + "values": { + "fontWeight": "500" + } + }, + "mixinBody": { + "values": { + "fontSize": "@textSizeBody" + } + }, + "mixinPrimary": { + "values": { + "fontSize": "@textSizePrimary" + } + }, + "mixinDetails": { + "values": { + "fontSize": "@textSizeDetails" + } + }, + "mixinSecondary": { + "values": { + "fontSize": "@textSizeSecondary" + } + }, + "textStylePrimary": { + "extend": [ + "textStyleBase1", + "mixinPrimary" + ] + }, + "textStyleSecondary": { + "extend": [ + "textStyleBase0", + "mixinSecondary" + ] + }, + "textStyleBody": { + "extend": [ + "textStyleBase1", + "mixinBody" + ] + }, + "textStyleSecondaryHint": { + "values": { + "fontFamily": "Bookerly", + "fontStyle": "italic", + "fontSize": "@textSizeSecondaryHint", + "color": "@colorTextPrimary" + } + }, + "textStyleDetails": { + "extend": [ + "textStyleBase2", + "mixinDetails" + ] + } + }, + "onMount": [], + "graphics": {}, + "commands": {}, + "layouts": { + "ListTemplate1": { + "parameters": [ + "backgroundImage", + "title", + "logo", + "hintText", + "listData" + ], + "item": [ + { + "type": "Container", + "width": "100vw", + "height": "100vh", + "direction": "column", + "items": [ + { + "type": "Image", + "source": "${backgroundImage}", + "scale": "best-fill", + "width": "100vw", + "height": "100vh", + "position": "absolute" + }, + { + "type": "AlexaHeader", + "headerTitle": "${title}", + "headerAttributionImage": "${logo}" + }, + { + "type": "Sequence", + "grow": 1, + "height": "80vh", + "scrollDirection": "vertical", + "paddingLeft": "@marginLeft", + "paddingRight": "@marginRight", + "data": "${listData}", + "numbered": true, + "items": [ + { + "type": "VerticalListItem", + "image": "${data.image.sources[0].url}", + "primaryText": "${data.textContent.primaryText.text}", + "secondaryText": "${data.textContent.secondaryText.text}", + "tertiaryText": "${data.textContent.tertiaryText.text}" + } + ] + } + ] + } + ] + }, + "VerticalListItem": { + "parameters": [ + "primaryText", + "secondaryText", + "tertiaryText", + "image" + ], + "item": [ + { + "when": "${viewport.shape == 'round'}", + "type": "Container", + "direction": "row", + "height": 200, + "width": 500, + "alignItems": "center", + "items": [ + { + "type": "Text", + "text": "${ordinal}", + "paddingBottom": "20dp", + "color": "white", + "spacing": "5dp" + }, + { + "type": "Image", + "when": "${image}", + "source": "${image}", + "height": 150, + "width": 150, + "spacing": 15, + "scale": "best-fit", + "align": "top" + }, + { + "type": "Container", + "direction": "column", + "spacing": 25, + "items": [ + { + "type": "Text", + "text": "${primaryText}", + "style": "textStyleDetail", + "grow": 1, + "shrink": 1, + "fontWeight": "300", + "maxLines": 1 + }, + { + "type": "Text", + "text": "${secondaryText}", + "style": "textStyleCaption", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + }, + { + "type": "Text", + "text": "${tertiaryText}", + "style": "textStyleDetails", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + } + ] + } + ] + }, + { + "type": "Container", + "direction": "row", + "height": 125, + "width": 800, + "alignItems": "center", + "items": [ + { + "type": "Text", + "text": "${ordinal}", + "paddingBottom": "20dp", + "color": "white", + "spacing": "5dp" + }, + { + "type": "Image", + "when": "${image}", + "source": "${image}", + "height": 100, + "width": 100, + "align": "top", + "spacing": 50, + "scale": "best-fit" + }, + { + "type": "Container", + "spacing": 30, + "direction": "column", + "items": [ + { + "type": "Text", + "text": "${primaryText}", + "style": "textStyleBody", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + }, + { + "type": "Text", + "text": "${secondaryText}", + "style": "textStyleDetails", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + } + ] + }, + { + "type": "Text", + "text": "${tertiaryText}", + "style": "textStyleBody", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "textAlign": "right", + "maxLines": 1 + } + ] + } + ] + } + }, + "mainTemplate": { + "parameters": [ + "payload" + ], + "item": [ + { + "type": "Container", + "id": "BookCabSimpleDialogAPL", + "items": [ + { + "type": "TouchWrapper", + "onPress": { + "type": "SendEvent", + "arguments": [ + "delegateToSkillNew" + ] + }, + "item": { + "type": "Text", + "id": "BookCabSimpleDialogAPL", + "paddingTop": "100", + "paddingLeft": "100", + "color": "green", + "size": 50, + "text": "delegateToSkillNew" + } + }, + { + "type": "TouchWrapper", + "onPress": { + "type": "SendEvent", + "arguments": [ + "delegateToSkillOld" + ] + }, + "item": { + "type": "Text", + "id": "BookCabSimpleDialogAPL", + "paddingTop": "100", + "paddingLeft": "100", + "color": "green", + "size": 50, + "text": "delegateToSkillOld" + } + }, + { + "type": "TouchWrapper", + "onPress": { + "type": "SendEvent", + "arguments": [ + "delegateToColtraneNew" + ] + }, + "item": { + "type": "Text", + "id": "BookCabSimpleDialogAPL", + "paddingTop": "100", + "paddingLeft": "100", + "color": "green", + "size": 50, + "text": "delegateToColtraneNew" + } + }, + { + "type": "TouchWrapper", + "onPress": { + "type": "SendEvent", + "arguments": [ + "delegateToColtraneOld" + ] + }, + "item": { + "type": "Text", + "id": "BookCabSimpleDialogAPL", + "paddingTop": "100", + "paddingLeft": "100", + "color": "green", + "size": 50, + "text": "delegateToColtraneOld" + } + } + ] + } + ] + } +} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/AlexaConversationsBye/document.json b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/AlexaConversationsBye/document.json new file mode 100644 index 00000000..bde5ee56 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/AlexaConversationsBye/document.json @@ -0,0 +1,21 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": [ + "payload" + ], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "Bye.", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/AlexaConversationsNotifyFailure/document.json b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/AlexaConversationsNotifyFailure/document.json new file mode 100644 index 00000000..c31fe279 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/AlexaConversationsNotifyFailure/document.json @@ -0,0 +1,21 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": [ + "payload" + ], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "Sorry, there was an error in the request.", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/AlexaConversationsOutOfDomain/document.json b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/AlexaConversationsOutOfDomain/document.json new file mode 100644 index 00000000..3796d4d5 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/AlexaConversationsOutOfDomain/document.json @@ -0,0 +1,21 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": [ + "payload" + ], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "Sorry, I don't understand.", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/AlexaConversationsProvideHelp/document.json b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/AlexaConversationsProvideHelp/document.json new file mode 100644 index 00000000..13b27c11 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/AlexaConversationsProvideHelp/document.json @@ -0,0 +1,21 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": [ + "payload" + ], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "I can give you the weather report. Just say \"what's the weather\" to start.", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/AlexaConversationsRequestMore/document.json b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/AlexaConversationsRequestMore/document.json new file mode 100644 index 00000000..fb3e56ae --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/AlexaConversationsRequestMore/document.json @@ -0,0 +1,21 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": [ + "payload" + ], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "What do you want to do.", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/AlexaConversationsThankYou/document.json b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/AlexaConversationsThankYou/document.json new file mode 100644 index 00000000..2112f02e --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/AlexaConversationsThankYou/document.json @@ -0,0 +1,21 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": [ + "payload" + ], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "Thank you.", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/AlexaConversationsWelcome/document.json b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/AlexaConversationsWelcome/document.json new file mode 100644 index 00000000..0c8e2588 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/AlexaConversationsWelcome/document.json @@ -0,0 +1,21 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": [ + "payload" + ], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "Welcome to the weatherOct16", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/AlexaConversationsYouAreWelcome/document.json b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/AlexaConversationsYouAreWelcome/document.json new file mode 100644 index 00000000..7ade07ba --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/AlexaConversationsYouAreWelcome/document.json @@ -0,0 +1,21 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": [ + "payload" + ], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "You are welcome.", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/SuccessGiveMeTodaySpecialsEvent_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/SuccessGiveMeTodaySpecialsEvent_apla/document.json new file mode 100644 index 00000000..f0b3055d --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/SuccessGiveMeTodaySpecialsEvent_apla/document.json @@ -0,0 +1,22 @@ +{ + "type": "APLA", + "version": "0.8", + "mainTemplate": { + "parameters": [ + "payload" + ], + "item": { + "type": "Selector", + "strategy": "randomItem", + "description": "Change 'type' above to try different Selector Component Types like Sequencer", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "today's special are ${payload.result.length} items , all items are ${payload.result}, first item is ${payload.result[0]}", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/SuccessGiveMeTodaySpecialsEvent_apla_failure/document.json b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/SuccessGiveMeTodaySpecialsEvent_apla_failure/document.json new file mode 100644 index 00000000..50468557 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/SuccessGiveMeTodaySpecialsEvent_apla_failure/document.json @@ -0,0 +1,22 @@ +{ + "type": "APLA", + "version": "0.8", + "mainTemplate": { + "parameters": [ + "payload" + ], + "item": { + "type": "Selector", + "strategy": "randomItem", + "description": "Change 'type' above to try different Selector Component Types like Sequencer", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "Failure : today's special are ${payload.result.length} items , all items are ${payload.result}, first item is ${payload.result[0]}", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/askForCrustPrompts/datasources/default.json b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/askForCrustPrompts/datasources/default.json new file mode 100644 index 00000000..9e26dfee --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/askForCrustPrompts/datasources/default.json @@ -0,0 +1 @@ +{} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/askForCrustPrompts/document.json b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/askForCrustPrompts/document.json new file mode 100644 index 00000000..3aec75b6 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/askForCrustPrompts/document.json @@ -0,0 +1 @@ +{"type":"APLA","version":"0.8","mainTemplate":{"parameters":["payload"],"item":{"type":"Selector","strategy":"randomItem","description":"Change 'type' above to try different Selector Component Types like Sequencer","items":[{"type":"Speech","contentType":"text","content":"On what kind of crust, we have thin, deep dish, regular and brooklyn style","description":"Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that"},{"type":"Speech","contentType":"text","content":"Ok, we have thin, deep dish, regular and brooklyn style, what would you like","description":"Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that"}]}}} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/askForSizePrompts/datasources/default.json b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/askForSizePrompts/datasources/default.json new file mode 100644 index 00000000..9e26dfee --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/askForSizePrompts/datasources/default.json @@ -0,0 +1 @@ +{} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/askForSizePrompts/document.json b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/askForSizePrompts/document.json new file mode 100644 index 00000000..87a88ee9 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/askForSizePrompts/document.json @@ -0,0 +1 @@ +{"type":"APLA","version":"0.8","mainTemplate":{"parameters":["payload"],"item":{"type":"Selector","strategy":"randomItem","description":"Change 'type' above to try different Selector Component Types like Sequencer","items":[{"type":"Speech","contentType":"text","content":"What size? We have small, medium, large and extra large","description":"Prompt for size"},{"type":"Speech","contentType":"text","content":"Ok. We have small to extra large pizzas. What size would you like? ","description":"Prompt for size"}]}}} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/askForToppingOnePrompt/datasources/default.json b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/askForToppingOnePrompt/datasources/default.json new file mode 100644 index 00000000..9e26dfee --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/askForToppingOnePrompt/datasources/default.json @@ -0,0 +1 @@ +{} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/askForToppingOnePrompt/document.json b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/askForToppingOnePrompt/document.json new file mode 100644 index 00000000..36ec7f0c --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/askForToppingOnePrompt/document.json @@ -0,0 +1 @@ +{"type":"APLA","version":"0.8","mainTemplate":{"parameters":["payload"],"item":{"type":"Selector","strategy":"randomItem","description":"Change 'type' above to try different Selector Component Types like Sequencer","items":[{"type":"Speech","contentType":"text","content":"What would you like for the 1st topping?","description":"Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that"}]}}} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/askForToppingTwoPrompt/datasources/default.json b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/askForToppingTwoPrompt/datasources/default.json new file mode 100644 index 00000000..9e26dfee --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/askForToppingTwoPrompt/datasources/default.json @@ -0,0 +1 @@ +{} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/askForToppingTwoPrompt/document.json b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/askForToppingTwoPrompt/document.json new file mode 100644 index 00000000..e12851f4 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/askForToppingTwoPrompt/document.json @@ -0,0 +1 @@ +{"type":"APLA","version":"0.8","mainTemplate":{"parameters":["payload"],"item":{"type":"Selector","strategy":"randomItem","description":"Change 'type' above to try different Selector Component Types like Sequencer","items":[{"type":"Speech","contentType":"text","content":"What about the 2nd topping?","description":"Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that"}]}}} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/askForToppingsPrompts/datasources/default.json b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/askForToppingsPrompts/datasources/default.json new file mode 100644 index 00000000..9e26dfee --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/askForToppingsPrompts/datasources/default.json @@ -0,0 +1 @@ +{} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/askForToppingsPrompts/document.json b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/askForToppingsPrompts/document.json new file mode 100644 index 00000000..ae44b6ef --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/askForToppingsPrompts/document.json @@ -0,0 +1 @@ +{"type":"APLA","version":"0.8","mainTemplate":{"parameters":["payload"],"item":{"type":"Selector","strategy":"randomItem","description":"Change 'type' above to try different Selector Component Types like Sequencer","items":[{"type":"Speech","contentType":"text","content":"What would you like on your pizza?","description":"Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that"}]}}} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/askForTwoToppingsPrompts/datasources/default.json b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/askForTwoToppingsPrompts/datasources/default.json new file mode 100644 index 00000000..9e26dfee --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/askForTwoToppingsPrompts/datasources/default.json @@ -0,0 +1 @@ +{} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/askForTwoToppingsPrompts/document.json b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/askForTwoToppingsPrompts/document.json new file mode 100644 index 00000000..24be5926 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/askForTwoToppingsPrompts/document.json @@ -0,0 +1 @@ +{"type":"APLA","version":"0.8","mainTemplate":{"parameters":["payload"],"item":{"type":"Selector","strategy":"randomItem","description":"Change 'type' above to try different Selector Component Types like Sequencer","items":[{"type":"Speech","contentType":"text","content":"Ok, what two toppings would you like?","description":"Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that"}]}}} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/askForTwoToppingsPrompts_copy/datasources/default.json b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/askForTwoToppingsPrompts_copy/datasources/default.json new file mode 100644 index 00000000..9e26dfee --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/askForTwoToppingsPrompts_copy/datasources/default.json @@ -0,0 +1 @@ +{} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/askForTwoToppingsPrompts_copy/document.json b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/askForTwoToppingsPrompts_copy/document.json new file mode 100644 index 00000000..24be5926 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/askForTwoToppingsPrompts_copy/document.json @@ -0,0 +1 @@ +{"type":"APLA","version":"0.8","mainTemplate":{"parameters":["payload"],"item":{"type":"Selector","strategy":"randomItem","description":"Change 'type' above to try different Selector Component Types like Sequencer","items":[{"type":"Speech","contentType":"text","content":"Ok, what two toppings would you like?","description":"Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that"}]}}} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/confirmAction_complexNames_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/confirmAction_complexNames_apla/document.json new file mode 100644 index 00000000..f9962e57 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/confirmAction_complexNames_apla/document.json @@ -0,0 +1,28 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": [ + "payload" + ], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [{ + "when": "${payload.sign!= null}", + "type": "Speech", + "contentType": "text", + "content": "confirm Action your cool name ${payload.name} and ${payload.sign}? ", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + }, + { + "when": "${payload.sign == null}", + "type": "Speech", + "contentType": "text", + "content": "confirm Action your cool name ${payload.name}? ", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/confirmArgs_complexNames_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/confirmArgs_complexNames_apla/document.json new file mode 100644 index 00000000..cfe959ca --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/confirmArgs_complexNames_apla/document.json @@ -0,0 +1,21 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": [ + "payload" + ], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "confirm args your cool name ${payload.name} and ${payload.sign}? ", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/confirmSizePrompt/datasources/default.json b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/confirmSizePrompt/datasources/default.json new file mode 100644 index 00000000..4bb69fc3 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/confirmSizePrompt/datasources/default.json @@ -0,0 +1 @@ +{"size":"extra large"} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/confirmSizePrompt/document.json b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/confirmSizePrompt/document.json new file mode 100644 index 00000000..052151e9 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/confirmSizePrompt/document.json @@ -0,0 +1 @@ +{"type":"APLA","version":"0.8","mainTemplate":{"parameters":["payload"],"item":{"type":"Sequencer","description":"Change 'type' above to try different Selector Component Types like Sequencer","items":[{"type":"Speech","contentType":"text","content":"You wanted "},{"type":"Speech","when":"${payload.size == 'small' || payload.size == 'large' || payload.size == 'medium'}","content":"a ${payload.size} pizza, is that correct?"},{"type":"Speech","when":"${payload.size == 'extra large'}","content":"an ${payload.size} pizza, is that correct?"}]}}} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/confirmTwoToppingOrderPrompt/datasources/default.json b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/confirmTwoToppingOrderPrompt/datasources/default.json new file mode 100644 index 00000000..9e26dfee --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/confirmTwoToppingOrderPrompt/datasources/default.json @@ -0,0 +1 @@ +{} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/confirmTwoToppingOrderPrompt/document.json b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/confirmTwoToppingOrderPrompt/document.json new file mode 100644 index 00000000..e17b3f78 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/confirmTwoToppingOrderPrompt/document.json @@ -0,0 +1,22 @@ +{ + "type": "APLA", + "version": "0.8", + "mainTemplate": { + "parameters": [ + "payload" + ], + "item": { + "type": "Selector", + "strategy": "randomItem", + "description": "Change 'type' above to try different Selector Component Types like Sequencer", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "Ok, that's a ${payload.first_topping} and ${payload.second_topping} on ${payload.crust} crust. Is that correct?", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/confirmTwoToppingOrderPromptcopy/datasources/default.json b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/confirmTwoToppingOrderPromptcopy/datasources/default.json new file mode 100644 index 00000000..9e26dfee --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/confirmTwoToppingOrderPromptcopy/datasources/default.json @@ -0,0 +1 @@ +{} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/confirmTwoToppingOrderPromptcopy/document.json b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/confirmTwoToppingOrderPromptcopy/document.json new file mode 100644 index 00000000..330ec5b7 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/confirmTwoToppingOrderPromptcopy/document.json @@ -0,0 +1,22 @@ +{ + "type": "APLA", + "version": "0.8", + "mainTemplate": { + "parameters": [ + "payload" + ], + "item": { + "type": "Selector", + "strategy": "randomItem", + "description": "Change 'type' above to try different Selector Component Types like Sequencer", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "Ok, that's a ${payload.size} ${payload.first_topping} and ${payload.second_topping} on ${payload.crust} crust. Is that correct?", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/confirmTwoToppingsPrompt/datasources/default.json b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/confirmTwoToppingsPrompt/datasources/default.json new file mode 100644 index 00000000..9e26dfee --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/confirmTwoToppingsPrompt/datasources/default.json @@ -0,0 +1 @@ +{} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/confirmTwoToppingsPrompt/document.json b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/confirmTwoToppingsPrompt/document.json new file mode 100644 index 00000000..d3c1e04b --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/confirmTwoToppingsPrompt/document.json @@ -0,0 +1 @@ +{"type":"APLA","version":"0.8","mainTemplate":{"parameters":["payload"],"item":{"type":"Selector","strategy":"randomItem","description":"Change 'type' above to try different Selector Component Types like Sequencer","items":[{"type":"Speech","contentType":"text","content":"Just to confirm, you want ${payload.first_topping} and ${payload.second_topping}","description":"Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that"}]}}} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/confirm_color_for_fruit_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/confirm_color_for_fruit_apla/document.json new file mode 100644 index 00000000..835d7a8e --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/confirm_color_for_fruit_apla/document.json @@ -0,0 +1,21 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": [ + "payload" + ], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "confirm color is ${payload.colorName} ? ", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/confirm_fruitName_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/confirm_fruitName_apla/document.json new file mode 100644 index 00000000..42d63adc --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/confirm_fruitName_apla/document.json @@ -0,0 +1,21 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": [ + "payload" + ], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "confirm fruit ${payload.fruitName} ? ", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/confirm_main_addon_list_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/confirm_main_addon_list_apla/document.json new file mode 100644 index 00000000..9b877ce9 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/confirm_main_addon_list_apla/document.json @@ -0,0 +1,21 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": [ + "payload" + ], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "confirm ${payload.foodName} with ${payload.addOn} ? ", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/confirm_weather_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/confirm_weather_apla/document.json new file mode 100644 index 00000000..66ea6d2a --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/confirm_weather_apla/document.json @@ -0,0 +1,21 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": [ + "payload" + ], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "Confirm weather forecast for ${payload.cityName} ${payload.date}?", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/confirm_weather_city_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/confirm_weather_city_apla/document.json new file mode 100644 index 00000000..fb9c3629 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/confirm_weather_city_apla/document.json @@ -0,0 +1,21 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": [ + "payload" + ], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "Confirm weather for ${payload.cityName}?", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/confirm_weather_date_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/confirm_weather_date_apla/document.json new file mode 100644 index 00000000..58b5a797 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/confirm_weather_date_apla/document.json @@ -0,0 +1,21 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": [ + "payload" + ], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "Confirm weather for ${payload.date}?", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/no_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/no_apla/document.json new file mode 100644 index 00000000..76610fcc --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/no_apla/document.json @@ -0,0 +1,21 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": [ + "payload" + ], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "I'm sorry you didn't like it", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/nothing2_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/nothing2_apla/document.json new file mode 100644 index 00000000..98f7ebef --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/nothing2_apla/document.json @@ -0,0 +1,21 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": [ + "payload" + ], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "The number you gave us was not 3.", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/nothing_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/nothing_apla/document.json new file mode 100644 index 00000000..5272f2a9 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/nothing_apla/document.json @@ -0,0 +1,21 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": [ + "payload" + ], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "The number you gave us was 3.", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/numericfeedback_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/numericfeedback_apla/document.json new file mode 100644 index 00000000..5278049b --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/numericfeedback_apla/document.json @@ -0,0 +1,19 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": [ + "payload" + ], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [{ + "type": "Speech", + "contentType": "text", + "content": "Your random number was ${payload.num}. How did we do? Please give this interaction a rating between 1-5, where 5 is the highest rating", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + }] + } + } +} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/rating_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/rating_apla/document.json new file mode 100644 index 00000000..7d50a649 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/rating_apla/document.json @@ -0,0 +1,21 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": [ + "payload" + ], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "rating please?", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/requestArgs_request_fruitName_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/requestArgs_request_fruitName_apla/document.json new file mode 100644 index 00000000..a27a7d1e --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/requestArgs_request_fruitName_apla/document.json @@ -0,0 +1,27 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": [ + "payload" + ], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "tell me the fruit name ?", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + }, + { + "type": "Speech", + "contentType": "text", + "content": "random slection tell me the fruit name ?", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/requestFromBookFlight_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/requestFromBookFlight_apla/document.json new file mode 100644 index 00000000..ca9378f4 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/requestFromBookFlight_apla/document.json @@ -0,0 +1,22 @@ +{ + "type": "APLA", + "version": "0.8", + "mainTemplate": { + "parameters": [ + "payload" + ], + "item": { + "type": "Selector", + "strategy": "randomItem", + "description": "Change 'type' above to try different Selector Component Types like Sequencer", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "from where?", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/requestPickUpFromBookCab_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/requestPickUpFromBookCab_apla/document.json new file mode 100644 index 00000000..78e43701 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/requestPickUpFromBookCab_apla/document.json @@ -0,0 +1,22 @@ +{ + "type": "APLA", + "version": "0.8", + "mainTemplate": { + "parameters": [ + "payload" + ], + "item": { + "type": "Selector", + "strategy": "randomItem", + "description": "Change 'type' above to try different Selector Component Types like Sequencer", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "request PickUp From BookCab apla, from where ?", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/requestToBookFlight_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/requestToBookFlight_apla/document.json new file mode 100644 index 00000000..487721a3 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/requestToBookFlight_apla/document.json @@ -0,0 +1,22 @@ +{ + "type": "APLA", + "version": "0.8", + "mainTemplate": { + "parameters": [ + "payload" + ], + "item": { + "type": "Selector", + "strategy": "randomItem", + "description": "Change 'type' above to try different Selector Component Types like Sequencer", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "to where ?", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/request_city_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/request_city_apla/document.json new file mode 100644 index 00000000..65c28562 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/request_city_apla/document.json @@ -0,0 +1,21 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": [ + "payload" + ], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "Which city?", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/request_city_cityName_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/request_city_cityName_apla/document.json new file mode 100644 index 00000000..5381b24e --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/request_city_cityName_apla/document.json @@ -0,0 +1,27 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": [ + "payload" + ], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "Which city?", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + }, + { + "type": "Speech", + "contentType": "text", + "content": "random selector Which city?", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/request_city_cityName_date_AMAZON_DATE_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/request_city_cityName_date_AMAZON_DATE_apla/document.json new file mode 100644 index 00000000..f685b93e --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/request_city_cityName_date_AMAZON_DATE_apla/document.json @@ -0,0 +1,21 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": [ + "payload" + ], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "Which city and for which date?", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/request_colorName_multiple_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/request_colorName_multiple_apla/document.json new file mode 100644 index 00000000..62911ca4 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/request_colorName_multiple_apla/document.json @@ -0,0 +1,21 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": [ + "payload" + ], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "which color?", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/request_date_AMAZON_DATE_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/request_date_AMAZON_DATE_apla/document.json new file mode 100644 index 00000000..3beebe7b --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/request_date_AMAZON_DATE_apla/document.json @@ -0,0 +1,21 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": [ + "payload" + ], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "Which date?", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/request_date_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/request_date_apla/document.json new file mode 100644 index 00000000..3beebe7b --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/request_date_apla/document.json @@ -0,0 +1,21 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": [ + "payload" + ], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "Which date?", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/request_listAddOns_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/request_listAddOns_apla/document.json new file mode 100644 index 00000000..a27b70ba --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/request_listAddOns_apla/document.json @@ -0,0 +1,21 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": [ + "payload" + ], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "what are the add ons?", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/request_mainFoodName_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/request_mainFoodName_apla/document.json new file mode 100644 index 00000000..5e18709e --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/request_mainFoodName_apla/document.json @@ -0,0 +1,21 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": [ + "payload" + ], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "What is the main food name?", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/request_name_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/request_name_apla/document.json new file mode 100644 index 00000000..8afc80bf --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/request_name_apla/document.json @@ -0,0 +1,21 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": [ + "payload" + ], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "SSML", + "content": "what is your cool name?", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/request_sign_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/request_sign_apla/document.json new file mode 100644 index 00000000..dc0099fd --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/request_sign_apla/document.json @@ -0,0 +1,21 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": [ + "payload" + ], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "SSML", + "content": "which sign", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/requestdropToBookCab_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/requestdropToBookCab_apla/document.json new file mode 100644 index 00000000..487721a3 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/requestdropToBookCab_apla/document.json @@ -0,0 +1,22 @@ +{ + "type": "APLA", + "version": "0.8", + "mainTemplate": { + "parameters": [ + "payload" + ], + "item": { + "type": "Selector", + "strategy": "randomItem", + "description": "Change 'type' above to try different Selector Component Types like Sequencer", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "to where ?", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/secondEarthAPI_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/secondEarthAPI_apla/document.json new file mode 100644 index 00000000..be1095b2 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/secondEarthAPI_apla/document.json @@ -0,0 +1,21 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": [ + "payload" + ], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "success delegating", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/seq_offer_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/seq_offer_apla/document.json new file mode 100644 index 00000000..44b8510b --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/seq_offer_apla/document.json @@ -0,0 +1,21 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": [ + "payload" + ], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "sequence offer , lets find fav color by sign and name?", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/successBookCabAPI_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/successBookCabAPI_apla/document.json new file mode 100644 index 00000000..bdeb2660 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/successBookCabAPI_apla/document.json @@ -0,0 +1,22 @@ +{ + "type": "APLA", + "version": "0.8", + "mainTemplate": { + "parameters": [ + "payload" + ], + "item": { + "type": "Selector", + "strategy": "randomItem", + "description": "Change 'type' above to try different Selector Component Types like Sequencer", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "Booked cab is ${payload.result.orderStatus}", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/successBookFlightAPI_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/successBookFlightAPI_apla/document.json new file mode 100644 index 00000000..c4b2ea1e --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/successBookFlightAPI_apla/document.json @@ -0,0 +1,22 @@ +{ + "type": "APLA", + "version": "0.8", + "mainTemplate": { + "parameters": [ + "payload" + ], + "item": { + "type": "Selector", + "strategy": "randomItem", + "description": "Change 'type' above to try different Selector Component Types like Sequencer", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "booked flight is ${payload.resultTwo.orderStatus} from ${payload.resultTwo.source} to ${payload.resultTwo.destination}, do you need cab to airport ?", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/success_cookingAPI_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/success_cookingAPI_apla/document.json new file mode 100644 index 00000000..2214532f --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/success_cookingAPI_apla/document.json @@ -0,0 +1,21 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": [ + "payload" + ], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "we have ${payload.status.orderStatus}", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/success_favColorSign_Name_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/success_favColorSign_Name_apla/document.json new file mode 100644 index 00000000..310bdb8a --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/success_favColorSign_Name_apla/document.json @@ -0,0 +1,22 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": [ + "payload" + ], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "Fav color of ${payload.result.name}, is ${payload.result.color}", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + + ] + } + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/success_fruitPriceAPI_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/success_fruitPriceAPI_apla/document.json new file mode 100644 index 00000000..b4a7272b --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/success_fruitPriceAPI_apla/document.json @@ -0,0 +1,21 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": [ + "payload" + ], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "price of an ${payload.result.fruitName} is ${payload.result.price} bucks ", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/twoToppingOrderSuccessPrompt/datasources/default.json b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/twoToppingOrderSuccessPrompt/datasources/default.json new file mode 100644 index 00000000..9e26dfee --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/twoToppingOrderSuccessPrompt/datasources/default.json @@ -0,0 +1 @@ +{} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/twoToppingOrderSuccessPrompt/document.json b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/twoToppingOrderSuccessPrompt/document.json new file mode 100644 index 00000000..6b0c5ce7 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/twoToppingOrderSuccessPrompt/document.json @@ -0,0 +1,22 @@ +{ + "type": "APLA", + "version": "0.8", + "mainTemplate": { + "parameters": [ + "payload" + ], + "item": { + "type": "Selector", + "strategy": "randomItem", + "description": "Change 'type' above to try different Selector Component Types like Sequencer", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "${payload.speech}", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/weather_success_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/weather_success_apla/document.json new file mode 100644 index 00000000..1d7b7405 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/weather_success_apla/document.json @@ -0,0 +1,29 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": [ + "payload" + ], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "when": "${payload.weatherResult.cityName != null && payload.weatherResult.highTemp < 3 && payload.weatherResult.lowTemp > 0}", + "type": "Speech", + "contentType": "text", + "content": "Offer In ${payload.weatherResult.cityName}, it's a high of ${payload.weatherResult.highTemp} degrees and a low of ${payload.weatherResult.lowTemp} degrees.", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + }, + { + "when": "${payload.weatherResult.cityName != null && payload.weatherResult.highTemp == null && payload.weatherResult.lowTemp == null}", + "type": "Speech", + "contentType": "text", + "content": "Alternate In ${payload.weatherResult.cityName}, it's a high of ${payload.weatherResult.highTemp} degrees and a low of ${payload.weatherResult.lowTemp} degrees.", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/welcome_apla_custom/document.json b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/welcome_apla_custom/document.json new file mode 100644 index 00000000..7447b614 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/welcome_apla_custom/document.json @@ -0,0 +1,21 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": [ + "payload" + ], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "Hi Satheesh , you have visited ${payload.result}", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/skill.json b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/skill.json new file mode 100644 index 00000000..9b59923c --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/skill.json @@ -0,0 +1,96 @@ +{ + "manifest": { + "apis": { + "custom": { + "dialogManagement": { + "dialogManagers": [ + { + "type": "AMAZON.Conversations" + } + ], + "sessionStartDelegationStrategy": { + "target": "AMAZON.Conversations" + } + }, + "endpoint": { + "uri": "arn:aws:lambda:us-west-2:267006587462:function:ramansatTestFunction" + }, + "interfaces": [ + { + "supportedViewports": [ + { + "maxHeight": 480, + "maxWidth": 480, + "minHeight": 480, + "minWidth": 480, + "mode": "HUB", + "shape": "ROUND" + }, + { + "maxHeight": 600, + "maxWidth": 1024, + "minHeight": 600, + "minWidth": 1024, + "mode": "HUB", + "shape": "RECTANGLE" + }, + { + "maxHeight": 800, + "maxWidth": 1280, + "minHeight": 800, + "minWidth": 1280, + "mode": "HUB", + "shape": "RECTANGLE" + }, + { + "maxHeight": 540, + "maxWidth": 960, + "minHeight": 540, + "minWidth": 960, + "mode": "TV", + "shape": "RECTANGLE" + } + ], + "type": "ALEXA_PRESENTATION_APL" + } + ], + "regions": { + "NA": { + "endpoint": { + "uri": "arn:aws:lambda:us-west-2:267006587462:function:ramansatTestFunction" + } + }, + "EU": { + "endpoint": { + "uri": "arn:aws:lambda:us-west-2:267006587462:function:ramansatTestFunction" + } + }, + "FE": { + "endpoint": { + "uri": "arn:aws:lambda:us-west-2:267006587462:function:ramansatTestFunction" + } + } + } + } + }, + "manifestVersion": "1.0", + "publishingInformation": { + "category": "KNOWLEDGE_AND_TRIVIA", + "distributionCountries": [], + "isAvailableWorldwide": true, + "locales": { + "en-US": { + "description": "Sample Full Description", + "examplePhrases": [ + "Alexa open hello world", + "hello", + "help" + ], + "name": "engineering test skill two_five", + "summary": "Sample Short Description" + } + }, + "testingInstructions": "Sample Testing Instructions." + } + } +} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-6/.ask/ask-states.json b/test/unit/fixture/dialog-evaluate/test-project-6/.ask/ask-states.json new file mode 100644 index 00000000..4c00bb5e --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-6/.ask/ask-states.json @@ -0,0 +1,8 @@ +{ + "askcliStatesVersion": "2020-03-31", + "profiles": { + "default": { + "skillId": "amzn1.ask.skill.e63c21c3-bc74-4503-bbe1-fabad41816bc" + } + } +} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-6/ask-resources.json b/test/unit/fixture/dialog-evaluate/test-project-6/ask-resources.json new file mode 100644 index 00000000..be9cb8d1 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-6/ask-resources.json @@ -0,0 +1,10 @@ +{ + "askcliResourcesVersion": "2020-03-31", + "profiles": { + "default": { + "skillMetadata": { + "src": "./skill-package" + } + } + } +} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/conversations/ALexaPrize.acdl b/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/conversations/ALexaPrize.acdl new file mode 100644 index 00000000..3083986a --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/conversations/ALexaPrize.acdl @@ -0,0 +1,213 @@ +namespace com.alexaprize + +import com.amazon.alexa.ask.conversations.Affirm +import com.amazon.alexa.ask.conversations.Deny +import com.amazon.alexa.ask.conversations.Invoke +import com.amazon.alexa.ask.conversations.Notify +import com.amazon.alexa.ask.conversations.Offer +import com.amazon.alexa.ask.conversations.expect +import com.amazon.alexa.ask.conversations.response +import com.amazon.alexa.ask.conversations.utterances +import com.amazon.alexa.schema.Boolean +import com.amazon.alexa.schema.Nothing +import com.amazon.alexa.schema.String +import com.amazon.ask.types.builtins.AMAZON.NUMBER +import prompts.alexa_prize_preconditions_apla +import slotTypes.TopicType + +type ConversationDetails { + optional TopicType Topic +} + +letsChatEvent = utterances( + [ + "let's chat", + "i want to chat", + "chat", + "talk", + "let's chat about {Topic}", + "i want to talk about {Topic}", + "can we talk about {Topic}" + ] +) + +affirmEvent = utterances( + [ + "yes", + "yup", + "yeah", + "sure", + "alright" + ] +) + +denyEvent = utterances( + [ + "no", + "nope", + "not really", + "not", + "naah" + ] +) + +type AlexaPrizePreconditions { + NUMBER isLocaleSupported + NUMBER isDeviceSupported + NUMBER isFalseWake + NUMBER isSocialBotAvailable + NUMBER isAlexaPrizeEnabled + NUMBER isTopicBanned + String handoffPromptOverride +} + +type AlexaPrizePreconditionsPayload { + AlexaPrizePreconditions result +} + +type HandoffResults { + String handoffPromptOverride +} + +type HandoffResultsPayload { + HandoffResults result +} + +action AlexaPrizePreconditions checkPreconditionsAndHandoff(TopicType Topic = nothing) + +action HandoffResults intentConfirmedHandoff() + +action HandoffResults intentDeniedHandoff() + +dialog Nothing AlexaPrizeDialog() { + sample { + preconditionsResult = checkPrecondition() + isHandoffPossible = (((preconditionsResult.isDeviceSupported == 1 && preconditionsResult.isLocaleSupported == 1) && preconditionsResult.isSocialBotAvailable == 1) && preconditionsResult.isAlexaPrizeEnabled == 1) + if (isHandoffPossible) { + isConfirmationNeeded = (preconditionsResult.isFalseWake == 1 || preconditionsResult.isTopicBanned == 1) + responses( + isConfirmationNeeded = isConfirmationNeeded, + preconditionsResult = preconditionsResult + ) + } else { + response( + alexa_prize_preconditions_apla, + Notify { + actionName = checkPreconditionsAndHandoff, + success = false + }, + nothing, + AlexaPrizePreconditionsPayload { + result = preconditionsResult + }, + nothing + ) + } + } +} + +dialog AlexaPrizePreconditions checkPrecondition() { + sample { + chatRequest = expect( + Invoke, + letsChatEvent + ) + checkPreconditionsAndHandoff( + chatRequest.Topic + ) + } + sample { + expect( + Invoke, + letsChatEvent + ) + preconditionsResult = checkPreconditionsAndHandoff() + } +} + +dialog Nothing responses(Boolean isConfirmationNeeded, AlexaPrizePreconditions preconditionsResult) { + sample { + if (isConfirmationNeeded) { + handoffResult( + preconditionsResult = preconditionsResult + ) + } else { + response( + alexa_prize_preconditions_apla, + Notify { + actionName = checkPreconditionsAndHandoff + }, + nothing, + AlexaPrizePreconditionsPayload { + result = preconditionsResult + }, + nothing + ) + } + } +} + +dialog Nothing handoffResult(AlexaPrizePreconditions preconditionsResult) { + sample { + response( + alexa_prize_preconditions_apla, + Notify { + actionName = checkPreconditionsAndHandoff + }, + Offer { + actionName = intentConfirmedHandoff + }, + AlexaPrizePreconditionsPayload { + result = preconditionsResult + }, + nothing + ) + expect( + Affirm, + affirmEvent + ) + handoffResults = intentConfirmedHandoff() + response( + alexa_prize_preconditions_apla, + Notify { + actionName = intentConfirmedHandoff + }, + nothing, + HandoffResultsPayload { + result = handoffResults + }, + nothing + ) + } + sample { + response( + alexa_prize_preconditions_apla, + Notify { + actionName = checkPreconditionsAndHandoff + }, + Offer { + actionName = intentDeniedHandoff + }, + AlexaPrizePreconditionsPayload { + result = preconditionsResult + }, + nothing + ) + expect( + Deny, + denyEvent + ) + handoffResults = intentDeniedHandoff() + response( + alexa_prize_preconditions_apla, + Notify { + actionName = intentDeniedHandoff + }, + nothing, + HandoffResultsPayload { + result = handoffResults + }, + nothing + ) + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/conversations/Dialog_NonDeployable.acdl b/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/conversations/Dialog_NonDeployable.acdl new file mode 100644 index 00000000..346dd841 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/conversations/Dialog_NonDeployable.acdl @@ -0,0 +1,90 @@ +namespace dialogs_non_deployable + +import apis.getEmployeeDetails +import com.amazon.alexa.ask.conversations.Inform +import com.amazon.alexa.ask.conversations.Request +import com.amazon.alexa.ask.conversations.expect +import com.amazon.alexa.ask.conversations.response +import com.amazon.ask.types.builtins.AMAZON.DATE +import com.amazon.ask.types.builtins.AMAZON.NUMBER +import prompts.request_dob_getDate_apla +import prompts.request_getEmploeeID_apla +import prompts.request_name_apla +import slotTypes.complexNames +import types.complexResult +import utteracesets.informComplexNameEvent +import utteracesets.informDOBEvent +import utteracesets.informEmployeeIDEvent + +dialog complexNames getName() { + sample { + response( + request_name_apla, + Request { + arguments = [ + getEmployeeDetails.arguments.name1 + ] + }, + nothing, + nothing, + nothing + ) + complexNamesReturn = expect( + Inform, + informComplexNameEvent + ) + complexNamesReturn.name + } +} + +dialog NUMBER getEmploeeID() { + sample { + response( + request_getEmploeeID_apla, + Request { + arguments = [ + getEmployeeDetails.arguments.emplyee1id + ] + }, + nothing, + nothing, + nothing + ) + empID = expect( + Inform, + informEmployeeIDEvent + ) + empID.emplyee1id + } +} + +dialog DATE getDate() { + sample { + response( + request_dob_getDate_apla, + Request { + arguments = [ + getEmployeeDetails.arguments.a_dateOfBirth + ] + }, + nothing, + nothing, + nothing + ) + dobEvent = expect( + Inform, + informDOBEvent + ) + dobEvent.a_dateOfBirth + } +} + +dialog complexResult a_getEmployeeDetails(complexNames name1, NUMBER emplyee1id, DATE a_dateOfBirth) { + sample { + complexResultEvent = getEmployeeDetails( + name1, + emplyee1id, + a_dateOfBirth + ) + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/conversations/Dialogs_reusableDialogsUsage_NonDeployableDialogs.acdl b/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/conversations/Dialogs_reusableDialogsUsage_NonDeployableDialogs.acdl new file mode 100644 index 00000000..cdcf0553 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/conversations/Dialogs_reusableDialogsUsage_NonDeployableDialogs.acdl @@ -0,0 +1,47 @@ +namespace reusableDialogs.NonDeployableDialogs + +import apis.getEmployeeDetails +import com.amazon.alexa.ask.conversations.Invoke +import com.amazon.alexa.ask.conversations.Notify +import com.amazon.alexa.ask.conversations.expect +import com.amazon.alexa.ask.conversations.response +import com.amazon.alexa.schema.Nothing +import dialogs_non_deployable.a_getEmployeeDetails +import dialogs_non_deployable.getDate +import dialogs_non_deployable.getEmploeeID +import dialogs_non_deployable.getName +import prompts.getEmployeePosition_success_apla +import types.complexResult +import utteracesets.who_are_you + +type PayLoadresult { + complexResult result +} + +dialog Nothing dilaog_getEmployeePosition() { + sample { + expect( + Invoke, + who_are_you + ) + complexNamesEvent = getName() + NUMBEREvent = getEmploeeID() + DATEEvent = getDate() + resultOne = a_getEmployeeDetails( + name1 = complexNamesEvent, + emplyee1id = NUMBEREvent, + a_dateOfBirth = DATEEvent + ) + response( + getEmployeePosition_success_apla, + Notify { + actionName = getEmployeeDetails + }, + nothing, + PayLoadresult { + result = resultOne + }, + nothing + ) + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/conversations/Weather.acdl b/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/conversations/Weather.acdl new file mode 100644 index 00000000..6b9b9935 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/conversations/Weather.acdl @@ -0,0 +1,139 @@ +namespace com.weatherbot + +import com.amazon.alexa.ask.conversations.Invoke +import com.amazon.alexa.ask.conversations.Notify +import com.amazon.alexa.ask.conversations.RequestArguments +import com.amazon.alexa.ask.conversations.ensure +import com.amazon.alexa.ask.conversations.expect +import com.amazon.alexa.ask.conversations.response +import com.amazon.alexa.ask.conversations.utterances +import com.amazon.alexa.schema.Nothing +import com.amazon.alexa.schema.Thing +import com.amazon.ask.types.builtins.AMAZON.DATE +import com.amazon.ask.types.builtins.AMAZON.NUMBER +import com.amazon.ask.types.builtins.AMAZON.US_CITY +import prompts.request_city_apla +import prompts.request_date_apla +import prompts.weather_apla +import slotTypes.myCustomCities + +type CityAndDate { + optional myCustomCities cityNameChanged + optional US_CITY cityName + optional DATE date +} + +getWeatherEvent = utterances( + [ + "What's the weather {date} in {cityNameChanged}", + "What's the weather {date} in {cityName}", + "what is the weather {date}", + "how is weather" + ] +) + +type WeatherResult { + optional myCustomCities cityNameChanged + optional US_CITY cityName + NUMBER highTemp + NUMBER lowTemp +} + +type ResponsePayload { + WeatherResult weatherResult +} + +action WeatherResult getWeather(DATE date, US_CITY cityName = nothing, myCustomCities cityNameChanged = nothing) + +dialog Nothing Weather() { + sample { + weatherRequest = expect( + Invoke, + getWeatherEvent + ) + ensure( + RequestArguments { + arguments = [ + getWeather.arguments.cityNameChanged + ], + response = request_city_apla + }, + RequestArguments { + arguments = [ + getWeather.arguments.cityName + ], + response = request_city_apla + }, + RequestArguments { + arguments = [ + getWeather.arguments.date + ], + response = request_date_apla + } + ) + weatherResult = getWeather( + weatherRequest.date, + weatherRequest.cityName, + nothing + ) + response( + weather_apla, + Notify { + actionName = getWeather + }, + nothing, + ResponsePayload { + weatherResult = weatherResult + }, + nothing + ) + } + sample { + weatherRequest = expect( + Invoke, + getWeatherEvent + ) + ensure( + RequestArguments { + arguments = [ + getWeather.arguments.cityNameChanged + ], + response = request_city_apla + }, + RequestArguments { + arguments = [ + getWeather.arguments.cityName + ], + response = request_city_apla + }, + RequestArguments { + arguments = [ + getWeather.arguments.date + ], + response = request_date_apla + } + ) + weatherResult = getWeather( + weatherRequest.date, + nothing, + weatherRequest.cityNameChanged + ) + response( + weather_apla, + Notify { + actionName = getWeather + }, + nothing, + ResponsePayload { + weatherResult = weatherResult + }, + nothing + ) + } +} + +dialog Nothing ComplexTest() { + sample { + Weather() + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/conversations/apisNamepaceLambda.acdl b/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/conversations/apisNamepaceLambda.acdl new file mode 100644 index 00000000..553a40c5 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/conversations/apisNamepaceLambda.acdl @@ -0,0 +1,22 @@ +namespace com.weatherbot.apis + +import com.amazon.ask.types.builtins.AMAZON.Food +import com.amazon.ask.types.builtins.AMAZON.NUMBER +import slotTypes.myColors + +type result { + Food fruitName + NUMBER price +} + +type payloadgetFruitPriceEvent { + result result +} + +action result fruitNameAPI(Food fruitName) + +action resultthree colorFruitName(myColors colorName) + +type resultthree { + Food fruitName +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/conversations/apis_mine.acdl b/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/conversations/apis_mine.acdl new file mode 100644 index 00000000..072d682e --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/conversations/apis_mine.acdl @@ -0,0 +1,15 @@ +namespace apis + +import com.amazon.alexa.schema.Nothing +import com.amazon.ask.types.builtins.AMAZON.DATE +import com.amazon.ask.types.builtins.AMAZON.NUMBER +import slotTypes.complexNames +import slotTypes.signs +import types.complexResult +import types.result_one + +action Nothing secondEarthAPI() + +action result_one favColorSign_Name(complexNames name, signs sign = nothing) + +action complexResult getEmployeeDetails(complexNames name1, NUMBER emplyee1id, DATE a_dateOfBirth = nothing) diff --git a/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/conversations/conversation_empty.acdl b/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/conversations/conversation_empty.acdl new file mode 100644 index 00000000..361e9d9b --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/conversations/conversation_empty.acdl @@ -0,0 +1,115 @@ +namespace com.numberbot + +import com.amazon.alexa.ask.conversations.APLA +import com.amazon.alexa.ask.conversations.Action +import com.amazon.alexa.ask.conversations.Bye +import com.amazon.alexa.ask.conversations.Invoke +import com.amazon.alexa.ask.conversations.Notify +import com.amazon.alexa.ask.conversations.Offer +import com.amazon.alexa.ask.conversations.RequestArguments +import com.amazon.alexa.ask.conversations.ensure +import com.amazon.alexa.ask.conversations.expect +import com.amazon.alexa.ask.conversations.response +import com.amazon.alexa.ask.conversations.utterances +import com.amazon.alexa.schema.Nothing +import com.amazon.alexa.schema.Number +import com.amazon.alexa.schema.Thing +import com.amazon.ask.types.builtins.AMAZON.NUMBER +import prompts.AlexaConversationsBye +import prompts.numericfeedback_apla +import prompts.rating_apla + +type NumPayload { + Number num +} + +type RatingRequest { + NUMBER rating +} + +InformRatingEvent = utterances( + [ + "my score is {rating}", + "that was a {rating} conversation", + "i rate you a {rating}", + "{rating}" + ] +) + +getStart = utterances( + [ + "give me a number please" + ] +) + +action Nothing saveRating(Number rating) + +action Number getNumber() + +dialog Nothing GetFeedback(APLA feedback_prompt, Number num, Action notifyAction) { + sample { + response( + feedback_prompt, + Notify { + actionName = notifyAction, + success = true + }, + Offer { + actionName = saveRating, + arguments = [ + saveRating.arguments.rating + ] + }, + NumPayload { + num = num + }, + nothing + ) + myRating = expect( + Invoke, + InformRatingEvent + ) + ensure( + RequestArguments { + arguments = [ + saveRating.arguments.rating + ], + response = rating_apla + } + ) + saveRating( + myRating.rating + ) + } +} + +dialog Number levelOne() { + sample { + expect( + Invoke, + getStart + ) + num = getNumber() + } +} + +dialog Nothing MainDialog() { + sample { + num = levelOne() + GetFeedback( + feedback_prompt = numericfeedback_apla, + num = num, + notifyAction = getNumber + ) + response( + AlexaConversationsBye, + Notify { + actionName = saveRating, + success = true + }, + Bye {}, + nothing, + nothing + ) + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/conversations/soaDialog.acdl b/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/conversations/soaDialog.acdl new file mode 100644 index 00000000..d44e9477 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/conversations/soaDialog.acdl @@ -0,0 +1,89 @@ +namespace soaACDl + +import com.amazon.alexa.ask.conversations.Inform +import com.amazon.alexa.ask.conversations.Invoke +import com.amazon.alexa.ask.conversations.Notify +import com.amazon.alexa.ask.conversations.Request +import com.amazon.alexa.ask.conversations.expect +import com.amazon.alexa.ask.conversations.response +import com.amazon.alexa.ask.conversations.utterances +import com.amazon.alexa.schema.Nothing +import com.weatherbot.apis.colorFruitName +import com.weatherbot.apis.resultthree +import prompts.request_colorName_multiple_apla +import prompts.success_colorFruitAPI_apla +import slotTypes.myColors + +type payloadMultipleDialogEvent { + resultthree result +} + +MultipleDialogEvent = utterances( + [ + "i want to buy a fruit" + ] +) + +affirmMultipleColorEvent = utterances( + [ + "do it" + ] +) + +type colorNameShell { + myColors colorName +} + +type payloadsOAConfirmArgs { + myColors colorName +} + +type colorEvent0 { + myColors colorName +} + +informColorMultipleEvent = utterances( + [ + "{colorName}", + "color is {colorName}", + "color {colorName}" + ] +) + +dialog Nothing testMe() { + sample { + expect( + Invoke, + MultipleDialogEvent + ) + response( + request_colorName_multiple_apla, + Request { + arguments = [ + colorFruitName.arguments.colorName + ] + }, + nothing, + nothing, + nothing + ) + colorEvent = expect( + Inform, + informColorMultipleEvent + ) + resultEvent = colorFruitName( + colorEvent.colorName + ) + response( + success_colorFruitAPI_apla, + Notify { + actionName = colorFruitName + }, + nothing, + payloadMultipleDialogEvent { + result = resultEvent + }, + nothing + ) + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/conversations/types_mine.acdl b/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/conversations/types_mine.acdl new file mode 100644 index 00000000..3cc656d2 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/conversations/types_mine.acdl @@ -0,0 +1,43 @@ +namespace types + +import com.amazon.ask.types.builtins.AMAZON.Color +import com.amazon.ask.types.builtins.AMAZON.DATE +import com.amazon.ask.types.builtins.AMAZON.Food +import com.amazon.ask.types.builtins.AMAZON.NUMBER +import slotTypes.complexNames +import slotTypes.myColors +import slotTypes.position +import slotTypes.signs + +type result_one { + Color colorName + complexNames name + signs sign +} + +type complexResult { + complexNames name1 + DATE a_dateOfBirth + NUMBER emplyee1id + position position +} + +type nameShell { + complexNames name +} + +type dobshell { + DATE a_dateOfBirth +} + +type employeeIDshell { + NUMBER emplyee1id +} + +type fruitNameShell { + Food fruitName +} + +type colorEvent0 { + myColors colorName +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/conversations/utteracesets_mine.acdl b/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/conversations/utteracesets_mine.acdl new file mode 100644 index 00000000..99c73e00 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/conversations/utteracesets_mine.acdl @@ -0,0 +1,82 @@ +namespace utteracesets + +import com.amazon.alexa.ask.conversations.utterances +import types.dobshell +import types.employeeIDshell +import types.fruitNameShell +import types.nameShell + +getFruitPriceEvent = utterances( + [ + "what is the price of the fruit", + "what is the price of fruit" + ] +) + +affirmFruitAPIEvent = utterances( + [ + "yeah" + ] +) + +informfruitNameEvent = utterances( + [ + "{fruitName}", + "fruit name is {fruitName}", + "fruit is {fruitName}" + ] +) + +delegateToSkill = utterances( + [ + "get me to paradise", + "take me to paradise" + ] +) + +getFavColorEvent = utterances( + [ + "what is my favourite color", + "tell my favourite color" + ] +) + +affirmFavColorEvent = utterances( + [ + "correct" + ] +) + +who_are_you = utterances( + [ + "who are you", + "who is that", + "find his designation" + ] +) + +informComplexNameEvent = utterances( + [ + "{name}", + "name is {name}", + "i am {name}" + ] +) + +informDOBEvent = utterances( + [ + "date of birth is {a_dateOfBirth}", + "birth date is {a_dateOfBirth}" + ] +) + +informEmployeeIDEvent = utterances( + [ + "employee i.d. is {emplyee1id}", + "employee identification is {emplyee1id}", + "identification is {emplyee1id}", + "employee id is {emplyee1id}", + "i.d. is {emplyee1id}", + "id is {emplyee1id}" + ] +) diff --git a/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/interactionModels/custom/en-US.json b/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/interactionModels/custom/en-US.json new file mode 100644 index 00000000..be0e8aff --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/interactionModels/custom/en-US.json @@ -0,0 +1,923 @@ +{ + "interactionModel": { + "languageModel": { + "invocationName": "model feedback test skill four", + "intents": [ + { + "name": "AMAZON.CancelIntent", + "samples": [] + }, + { + "name": "AMAZON.HelpIntent", + "samples": [] + }, + { + "name": "AMAZON.StopIntent", + "samples": [] + }, + { + "name": "GetWeatherIntent", + "samples": [ + "what is the weather", + "how is the weather", + "tell me the weather" + ] + }, + { + "name": "AMAZON.NavigateHomeIntent", + "samples": [] + }, + { + "name": "AMAZON.FallbackIntent", + "samples": [] + } + ], + "types": [ + { + "values": [ + { + "id": "movies", + "name": { + "value": "movies", + "synonyms": [] + } + }, + { + "id": "politics", + "name": { + "value": "politics", + "synonyms": [] + } + }, + { + "id": "sports", + "name": { + "value": "sports", + "synonyms": [] + } + }, + { + "id": "hobbies", + "name": { + "value": "hobbies", + "synonyms": [] + } + }, + { + "id": "astronomy", + "name": { + "value": "astronomy", + "synonyms": [] + } + }, + { + "id": "physics", + "name": { + "value": "physics", + "synonyms": [] + } + }, + { + "id": "los_angeles_dodgers", + "name": { + "value": "los angeles dodgers" + } + }, + { + "id": "president_emmanuel_macron", + "name": { + "value": "president emmanuel macron" + } + }, + { + "id": "emmanuel_macron", + "name": { + "value": "emmanuel macron" + } + }, + { + "id": "tax_cuts", + "name": { + "value": "tax cuts" + } + }, + { + "id": "middle_class", + "name": { + "value": "middle class" + } + }, + { + "id": "inequality_divide", + "name": { + "value": "inequality divide" + } + }, + { + "id": "wealth_inequality", + "name": { + "value": "wealth inequality" + } + }, + { + "id": "n._p._r.", + "name": { + "value": "n. p. r." + } + }, + { + "id": "president_trump", + "name": { + "value": "president trump" + } + }, + { + "id": "fox", + "name": { + "value": "fox" + } + }, + { + "id": "police_officers", + "name": { + "value": "police officers" + } + }, + { + "id": "jerome_hall", + "name": { + "value": "jerome hall" + } + }, + { + "id": "diversity_training_program", + "name": { + "value": "diversity training program" + } + }, + { + "id": "read_preble", + "name": { + "value": "read preble" + } + }, + { + "id": "christopher_preble", + "name": { + "value": "christopher preble" + } + }, + { + "id": "pacific_rim", + "name": { + "value": "pacific rim" + } + }, + { + "id": "washington_nationals", + "name": { + "value": "washington nationals" + } + }, + { + "id": "michael_cohen", + "name": { + "value": "michael cohen" + } + }, + { + "id": "john_wall", + "name": { + "value": "john wall" + } + }, + { + "id": "united_states", + "name": { + "value": "united states" + } + }, + { + "id": "washington_wizards", + "name": { + "value": "washington wizards" + } + }, + { + "id": "bryce_harper", + "name": { + "value": "bryce harper" + } + }, + { + "id": "capitals_playoff_hockey_capitals", + "name": { + "value": "capitals playoff hockey capitals" + } + }, + { + "id": "james_b._comey", + "name": { + "value": "james b. comey" + } + }, + { + "id": "mike_pompeo", + "name": { + "value": "mike pompeo" + } + }, + { + "id": "tom_toles", + "name": { + "value": "tom toles" + } + }, + { + "id": "white_house", + "name": { + "value": "white house" + } + }, + { + "id": "manny_machado", + "name": { + "value": "manny machado" + } + }, + { + "id": "national_league_east", + "name": { + "value": "national league east" + } + }, + { + "id": "otto_porter_jr._now", + "name": { + "value": "otto porter jr. now" + } + }, + { + "id": "hillary_clinton", + "name": { + "value": "hillary clinton" + } + }, + { + "id": "trea_turner", + "name": { + "value": "trea turner" + } + }, + { + "id": "max_scherzer", + "name": { + "value": "max scherzer" + } + }, + { + "id": "donald_trump", + "name": { + "value": "donald trump" + } + }, + { + "id": "bryce_harper_nationals", + "name": { + "value": "bryce harper nationals" + } + }, + { + "id": "michael_a._taylor", + "name": { + "value": "michael a. taylor" + } + }, + { + "id": "news_media", + "name": { + "value": "news media" + } + }, + { + "id": "conservative_political_action_conference", + "name": { + "value": "conservative political action conference" + } + }, + { + "id": "mainstream_media", + "name": { + "value": "mainstream media" + } + }, + { + "id": "baltimore_orioles", + "name": { + "value": "baltimore orioles" + } + }, + { + "id": "sean_hannity", + "name": { + "value": "sean hannity" + } + }, + { + "id": "privilege", + "name": { + "value": "privilege" + } + }, + { + "id": "sarah_hart", + "name": { + "value": "sarah hart" + } + }, + { + "id": "matt_kemp", + "name": { + "value": "matt kemp" + } + }, + { + "id": "stephen_strasburg", + "name": { + "value": "stephen strasburg" + } + }, + { + "id": "police_misconduct", + "name": { + "value": "police misconduct" + } + }, + { + "id": "sarah_huckabee_sanders", + "name": { + "value": "sarah huckabee sanders" + } + }, + { + "id": "washington_wizards_april", + "name": { + "value": "washington wizards april" + } + }, + { + "id": "environmental_protection_agency_administrator_scott_pruitt", + "name": { + "value": "environmental protection agency administrator scott pruitt" + } + }, + { + "id": "dodger_stadium", + "name": { + "value": "dodger stadium" + } + }, + { + "id": "environmental_protection_agency", + "name": { + "value": "environmental protection agency" + } + }, + { + "id": "barbara_bush", + "name": { + "value": "barbara bush" + } + }, + { + "id": "lewis_\"scooter\"_libby", + "name": { + "value": "lewis \"scooter\" libby" + } + }, + { + "id": "lewis_scooter_libby", + "name": { + "value": "lewis scooter libby" + } + }, + { + "id": "game_3._lowry", + "name": { + "value": "game 3. lowry" + } + }, + { + "id": "columbus_blue_jackets", + "name": { + "value": "columbus blue jackets" + } + }, + { + "id": "john_tortorella", + "name": { + "value": "john tortorella" + } + }, + { + "id": "george_w._bush", + "name": { + "value": "george w. bush" + } + }, + { + "id": "george_h.w._bush", + "name": { + "value": "george h.w. bush" + } + }, + { + "id": "jarrett_hurd", + "name": { + "value": "jarrett hurd" + } + }, + { + "id": "said_fred_hurd_sr.", + "name": { + "value": "said fred hurd sr." + } + }, + { + "id": "fred_hurd_sr.", + "name": { + "value": "fred hurd sr." + } + }, + { + "id": "san_antonio", + "name": { + "value": "san antonio" + } + }, + { + "id": "san_antonio_spurs", + "name": { + "value": "san antonio spurs" + } + }, + { + "id": "gregg_popovich", + "name": { + "value": "gregg popovich" + } + }, + { + "id": "kawhi_leonard", + "name": { + "value": "kawhi leonard" + } + }, + { + "id": "tim_bontemps_seth_jones", + "name": { + "value": "tim bontemps seth jones" + } + }, + { + "id": "consumer_sentiment_index", + "name": { + "value": "consumer sentiment index" + } + }, + { + "id": "pew_research_center", + "name": { + "value": "pew research center" + } + }, + { + "id": "conference_board_consumer_confidence_survey", + "name": { + "value": "conference board consumer confidence survey" + } + }, + { + "id": "speech_rights", + "name": { + "value": "speech rights" + } + }, + { + "id": "first_amendment", + "name": { + "value": "first amendment" + } + }, + { + "id": "golden_state", + "name": { + "value": "golden state" + } + }, + { + "id": "north_korea", + "name": { + "value": "north korea" + } + }, + { + "id": "woman_pilot", + "name": { + "value": "woman pilot" + } + }, + { + "id": "airline_pilot_population", + "name": { + "value": "airline pilot population" + } + }, + { + "id": "air_transport_pilot", + "name": { + "value": "air transport pilot" + } + }, + { + "id": "southwest_airlines", + "name": { + "value": "southwest airlines" + } + }, + { + "id": "democratic_national_committee", + "name": { + "value": "democratic national committee" + } + }, + { + "id": "senate_foreign_relations_committee", + "name": { + "value": "senate foreign relations committee" + } + }, + { + "id": "cia_director_mike_pompeo", + "name": { + "value": "cia director mike pompeo" + } + }, + { + "id": "playoff_overtime_games", + "name": { + "value": "playoff overtime games" + } + }, + { + "id": "lord_jesus", + "name": { + "value": "lord jesus" + } + }, + { + "id": "lgbtq_community", + "name": { + "value": "lgbtq community" + } + }, + { + "id": "health_and_human_services_department", + "name": { + "value": "health and human services department" + } + }, + { + "id": "group_prayer", + "name": { + "value": "group prayer" + } + }, + { + "id": "princess_charlotte_elizabeth_diana", + "name": { + "value": "princess charlotte elizabeth diana" + } + }, + { + "id": "term_war_economy", + "name": { + "value": "term war economy" + } + }, + { + "id": "melissa_kirk", + "name": { + "value": "melissa kirk" + } + }, + { + "id": "captain_america", + "name": { + "value": "captain america" + } + }, + { + "id": "draft_position", + "name": { + "value": "draft position" + } + }, + { + "id": "elysee_mbem-bosse", + "name": { + "value": "elysee mbem-bosse" + } + }, + { + "id": "water_crisis", + "name": { + "value": "water crisis" + } + }, + { + "id": "nationals_pitchers", + "name": { + "value": "nationals pitchers" + } + }, + { + "id": "sen._jennifer_t._wexton", + "name": { + "value": "sen. jennifer t. wexton" + } + }, + { + "id": "interest_rates", + "name": { + "value": "interest rates" + } + }, + { + "id": "town_crier", + "name": { + "value": "town crier" + } + }, + { + "id": "nancy_goes_millennial", + "name": { + "value": "nancy goes millennial" + } + }, + { + "id": "steve_rogers", + "name": { + "value": "steve rogers" + } + }, + { + "id": "game_3._lebron_james", + "name": { + "value": "game 3. lebron james" + } + }, + { + "id": "anthony_rendon", + "name": { + "value": "anthony rendon" + } + }, + { + "id": "buckingham_palace", + "name": { + "value": "buckingham palace" + } + }, + { + "id": "travis_reinking_suspected", + "name": { + "value": "travis reinking suspected" + } + }, + { + "id": "detroit_free_press", + "name": { + "value": "detroit free press" + } + }, + { + "id": "national_rifle_association", + "name": { + "value": "national rifle association" + } + }, + { + "id": "ed_harris", + "name": { + "value": "ed harris" + } + }, + { + "id": "overtime_playoff_games", + "name": { + "value": "overtime playoff games" + } + }, + { + "id": "republican_sen._bob_corker", + "name": { + "value": "republican sen. bob corker" + } + }, + { + "id": "electricity_sector_reforms", + "name": { + "value": "electricity sector reforms" + } + }, + { + "id": "baltimore_manager_buck_showalter", + "name": { + "value": "baltimore manager buck showalter" + } + }, + { + "id": "sen._joe_manchin_iii", + "name": { + "value": "sen. joe manchin iii" + } + }, + { + "id": "car_seat_belts", + "name": { + "value": "car seat belts" + } + }, + { + "id": "andrews_mcmeel.", + "name": { + "value": "andrews mcmeel." + } + }, + { + "id": "north_africa_program", + "name": { + "value": "north africa program" + } + }, + { + "id": "state_prosecutor_lobby", + "name": { + "value": "state prosecutor lobby" + } + }, + { + "id": "cape_town", + "name": { + "value": "cape town" + } + }, + { + "id": "data_privacy_law", + "name": { + "value": "data privacy law" + } + }, + { + "id": "president_trump_down", + "name": { + "value": "president trump down" + } + }, + { + "id": "christian_kirk", + "name": { + "value": "christian kirk" + } + }, + { + "id": "mitch_mcconnell", + "name": { + "value": "mitch mcconnell" + } + }, + { + "id": "federal_reserve", + "name": { + "value": "federal reserve" + } + } + ], + "name": "TopicType" + }, + { + "values": [ + { + "name": { + "value": "cancer" + } + }, + { + "name": { + "value": "scorpio" + } + }, + { + "name": { + "value": "scorpion" + } + } + ], + "name": "signs" + }, + { + "values": [ + { + "name": { + "value": "satheesh" + } + }, + { + "name": { + "value": "raman" + } + }, + { + "name": { + "value": "yadhu" + } + } + ], + "name": "complexNames" + }, + { + "values": [ + { + "name": { + "value": "tester" + } + }, + { + "name": { + "value": "engineer" + } + }, + { + "name": { + "value": "manager" + } + } + ], + "name": "position" + }, + { + "values": [ + { + "name": { + "value": "blue" + } + }, + { + "name": { + "value": "red" + } + }, + { + "name": { + "value": "rocket" + } + } + ], + "name": "myColors" + }, + { + "values": [ + { + "name": { + "value": "flower city" + } + }, + { + "name": { + "value": "temple city" + } + }, + { + "name": { + "value": "ramapuram" + } + }, + { + "name": { + "value": "guindy" + } + }, + { + "name": { + "value": "porur" + } + } + ], + "name": "myCustomCities" + } + ] + } + }, + "version": "9" +} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/display/confirm_city_apl_display/document.json b/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/display/confirm_city_apl_display/document.json new file mode 100644 index 00000000..741e1a5f --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/display/confirm_city_apl_display/document.json @@ -0,0 +1,358 @@ +{ + "type": "APL", + "version": "1.1", + "settings": {}, + "theme": "dark", + "import": [ + { + "name": "alexa-layouts", + "version": "1.0.0" + } + ], + "resources": [ + { + "description": "Stock color for the light theme", + "colors": { + "colorTextPrimary": "#151920" + } + }, + { + "description": "Stock color for the dark theme", + "when": "${viewport.theme == 'dark'}", + "colors": { + "colorTextPrimary": "#f0f1ef" + } + }, + { + "description": "Standard font sizes", + "dimensions": { + "textSizeBody": 48, + "textSizePrimary": 27, + "textSizeSecondary": 23, + "textSizeDetails": 20, + "textSizeSecondaryHint": 25 + } + }, + { + "description": "Common spacing values", + "dimensions": { + "spacingThin": 6, + "spacingSmall": 12, + "spacingMedium": 24, + "spacingLarge": 48, + "spacingExtraLarge": 72 + } + }, + { + "description": "Common margins and padding", + "dimensions": { + "marginTop": 40, + "marginLeft": 60, + "marginRight": 60, + "marginBottom": 40 + } + } + ], + "styles": { + "textStyleBase": { + "description": "Base font description; set color", + "values": [ + { + "color": "@colorTextPrimary" + } + ] + }, + "textStyleBase0": { + "description": "Thin version of basic font", + "extend": "textStyleBase", + "values": { + "fontWeight": "100" + } + }, + "textStyleBase1": { + "description": "Light version of basic font", + "extend": "textStyleBase", + "values": { + "fontWeight": "300" + } + }, + "textStyleBase2": { + "description": "Regular version of basic font", + "extend": "textStyleBase", + "values": { + "fontWeight": "500" + } + }, + "mixinBody": { + "values": { + "fontSize": "@textSizeBody" + } + }, + "mixinPrimary": { + "values": { + "fontSize": "@textSizePrimary" + } + }, + "mixinDetails": { + "values": { + "fontSize": "@textSizeDetails" + } + }, + "mixinSecondary": { + "values": { + "fontSize": "@textSizeSecondary" + } + }, + "textStylePrimary": { + "extend": [ + "textStyleBase1", + "mixinPrimary" + ] + }, + "textStyleSecondary": { + "extend": [ + "textStyleBase0", + "mixinSecondary" + ] + }, + "textStyleBody": { + "extend": [ + "textStyleBase1", + "mixinBody" + ] + }, + "textStyleSecondaryHint": { + "values": { + "fontFamily": "Bookerly", + "fontStyle": "italic", + "fontSize": "@textSizeSecondaryHint", + "color": "@colorTextPrimary" + } + }, + "textStyleDetails": { + "extend": [ + "textStyleBase2", + "mixinDetails" + ] + } + }, + "onMount": [], + "graphics": {}, + "commands": {}, + "layouts": { + "ListTemplate1": { + "parameters": [ + "backgroundImage", + "title", + "logo", + "hintText", + "listData" + ], + "item": [ + { + "type": "Container", + "width": "100vw", + "height": "100vh", + "direction": "column", + "items": [ + { + "type": "Image", + "source": "${backgroundImage}", + "scale": "best-fill", + "width": "100vw", + "height": "100vh", + "position": "absolute" + }, + { + "type": "AlexaHeader", + "headerTitle": "${title}", + "headerAttributionImage": "${logo}" + }, + { + "type": "Sequence", + "grow": 1, + "height": "80vh", + "scrollDirection": "vertical", + "paddingLeft": "@marginLeft", + "paddingRight": "@marginRight", + "data": "${listData}", + "numbered": true, + "items": [ + { + "type": "VerticalListItem", + "image": "${data.image.sources[0].url}", + "primaryText": "${data.textContent.primaryText.text}", + "secondaryText": "${data.textContent.secondaryText.text}", + "tertiaryText": "${data.textContent.tertiaryText.text}" + } + ] + } + ] + } + ] + }, + "VerticalListItem": { + "parameters": [ + "primaryText", + "secondaryText", + "tertiaryText", + "image" + ], + "item": [ + { + "when": "${viewport.shape == 'round'}", + "type": "Container", + "direction": "row", + "height": 200, + "width": 500, + "alignItems": "center", + "items": [ + { + "type": "Text", + "text": "${ordinal}", + "paddingBottom": "20dp", + "color": "white", + "spacing": "5dp" + }, + { + "type": "Image", + "when": "${image}", + "source": "${image}", + "height": 150, + "width": 150, + "spacing": 15, + "scale": "best-fit", + "align": "top" + }, + { + "type": "Container", + "direction": "column", + "spacing": 25, + "items": [ + { + "type": "Text", + "text": "${primaryText}", + "style": "textStyleDetail", + "grow": 1, + "shrink": 1, + "fontWeight": "300", + "maxLines": 1 + }, + { + "type": "Text", + "text": "${secondaryText}", + "style": "textStyleCaption", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + }, + { + "type": "Text", + "text": "${tertiaryText}", + "style": "textStyleDetails", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + } + ] + } + ] + }, + { + "type": "Container", + "direction": "row", + "height": 125, + "width": 800, + "alignItems": "center", + "items": [ + { + "type": "Text", + "text": "${ordinal}", + "paddingBottom": "20dp", + "color": "white", + "spacing": "5dp" + }, + { + "type": "Image", + "when": "${image}", + "source": "${image}", + "height": 100, + "width": 100, + "align": "top", + "spacing": 50, + "scale": "best-fit" + }, + { + "type": "Container", + "spacing": 30, + "direction": "column", + "items": [ + { + "type": "Text", + "text": "${primaryText}", + "style": "textStyleBody", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + }, + { + "type": "Text", + "text": "${secondaryText}", + "style": "textStyleDetails", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + } + ] + }, + { + "type": "Text", + "text": "${tertiaryText}", + "style": "textStyleBody", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "textAlign": "right", + "maxLines": 1 + } + ] + } + ] + } + }, + "mainTemplate": { + "parameters": [ + "payload" + ], + "item": [ + { + "type": "Container", + "id": "BookCabSimpleDialogAPL", + "items": [ + { + "type": "TouchWrapper", + "onPress": { + "type": "SendEvent", + "arguments": [ + "delegateToColtraneOld" + ] + }, + "item": { + "type": "Text", + "id": "BookCabSimpleDialogAPL", + "paddingTop": "100", + "paddingLeft": "100", + "color": "green", + "size": 50, + "text": "which city ?" + } + } + ] + } + ] + } +} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/display/confirm_date_apl_display/document.json b/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/display/confirm_date_apl_display/document.json new file mode 100644 index 00000000..9ff71e5c --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/display/confirm_date_apl_display/document.json @@ -0,0 +1,358 @@ +{ + "type": "APL", + "version": "1.1", + "settings": {}, + "theme": "dark", + "import": [ + { + "name": "alexa-layouts", + "version": "1.0.0" + } + ], + "resources": [ + { + "description": "Stock color for the light theme", + "colors": { + "colorTextPrimary": "#151920" + } + }, + { + "description": "Stock color for the dark theme", + "when": "${viewport.theme == 'dark'}", + "colors": { + "colorTextPrimary": "#f0f1ef" + } + }, + { + "description": "Standard font sizes", + "dimensions": { + "textSizeBody": 48, + "textSizePrimary": 27, + "textSizeSecondary": 23, + "textSizeDetails": 20, + "textSizeSecondaryHint": 25 + } + }, + { + "description": "Common spacing values", + "dimensions": { + "spacingThin": 6, + "spacingSmall": 12, + "spacingMedium": 24, + "spacingLarge": 48, + "spacingExtraLarge": 72 + } + }, + { + "description": "Common margins and padding", + "dimensions": { + "marginTop": 40, + "marginLeft": 60, + "marginRight": 60, + "marginBottom": 40 + } + } + ], + "styles": { + "textStyleBase": { + "description": "Base font description; set color", + "values": [ + { + "color": "@colorTextPrimary" + } + ] + }, + "textStyleBase0": { + "description": "Thin version of basic font", + "extend": "textStyleBase", + "values": { + "fontWeight": "100" + } + }, + "textStyleBase1": { + "description": "Light version of basic font", + "extend": "textStyleBase", + "values": { + "fontWeight": "300" + } + }, + "textStyleBase2": { + "description": "Regular version of basic font", + "extend": "textStyleBase", + "values": { + "fontWeight": "500" + } + }, + "mixinBody": { + "values": { + "fontSize": "@textSizeBody" + } + }, + "mixinPrimary": { + "values": { + "fontSize": "@textSizePrimary" + } + }, + "mixinDetails": { + "values": { + "fontSize": "@textSizeDetails" + } + }, + "mixinSecondary": { + "values": { + "fontSize": "@textSizeSecondary" + } + }, + "textStylePrimary": { + "extend": [ + "textStyleBase1", + "mixinPrimary" + ] + }, + "textStyleSecondary": { + "extend": [ + "textStyleBase0", + "mixinSecondary" + ] + }, + "textStyleBody": { + "extend": [ + "textStyleBase1", + "mixinBody" + ] + }, + "textStyleSecondaryHint": { + "values": { + "fontFamily": "Bookerly", + "fontStyle": "italic", + "fontSize": "@textSizeSecondaryHint", + "color": "@colorTextPrimary" + } + }, + "textStyleDetails": { + "extend": [ + "textStyleBase2", + "mixinDetails" + ] + } + }, + "onMount": [], + "graphics": {}, + "commands": {}, + "layouts": { + "ListTemplate1": { + "parameters": [ + "backgroundImage", + "title", + "logo", + "hintText", + "listData" + ], + "item": [ + { + "type": "Container", + "width": "100vw", + "height": "100vh", + "direction": "column", + "items": [ + { + "type": "Image", + "source": "${backgroundImage}", + "scale": "best-fill", + "width": "100vw", + "height": "100vh", + "position": "absolute" + }, + { + "type": "AlexaHeader", + "headerTitle": "${title}", + "headerAttributionImage": "${logo}" + }, + { + "type": "Sequence", + "grow": 1, + "height": "80vh", + "scrollDirection": "vertical", + "paddingLeft": "@marginLeft", + "paddingRight": "@marginRight", + "data": "${listData}", + "numbered": true, + "items": [ + { + "type": "VerticalListItem", + "image": "${data.image.sources[0].url}", + "primaryText": "${data.textContent.primaryText.text}", + "secondaryText": "${data.textContent.secondaryText.text}", + "tertiaryText": "${data.textContent.tertiaryText.text}" + } + ] + } + ] + } + ] + }, + "VerticalListItem": { + "parameters": [ + "primaryText", + "secondaryText", + "tertiaryText", + "image" + ], + "item": [ + { + "when": "${viewport.shape == 'round'}", + "type": "Container", + "direction": "row", + "height": 200, + "width": 500, + "alignItems": "center", + "items": [ + { + "type": "Text", + "text": "${ordinal}", + "paddingBottom": "20dp", + "color": "white", + "spacing": "5dp" + }, + { + "type": "Image", + "when": "${image}", + "source": "${image}", + "height": 150, + "width": 150, + "spacing": 15, + "scale": "best-fit", + "align": "top" + }, + { + "type": "Container", + "direction": "column", + "spacing": 25, + "items": [ + { + "type": "Text", + "text": "${primaryText}", + "style": "textStyleDetail", + "grow": 1, + "shrink": 1, + "fontWeight": "300", + "maxLines": 1 + }, + { + "type": "Text", + "text": "${secondaryText}", + "style": "textStyleCaption", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + }, + { + "type": "Text", + "text": "${tertiaryText}", + "style": "textStyleDetails", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + } + ] + } + ] + }, + { + "type": "Container", + "direction": "row", + "height": 125, + "width": 800, + "alignItems": "center", + "items": [ + { + "type": "Text", + "text": "${ordinal}", + "paddingBottom": "20dp", + "color": "white", + "spacing": "5dp" + }, + { + "type": "Image", + "when": "${image}", + "source": "${image}", + "height": 100, + "width": 100, + "align": "top", + "spacing": 50, + "scale": "best-fit" + }, + { + "type": "Container", + "spacing": 30, + "direction": "column", + "items": [ + { + "type": "Text", + "text": "${primaryText}", + "style": "textStyleBody", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + }, + { + "type": "Text", + "text": "${secondaryText}", + "style": "textStyleDetails", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + } + ] + }, + { + "type": "Text", + "text": "${tertiaryText}", + "style": "textStyleBody", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "textAlign": "right", + "maxLines": 1 + } + ] + } + ] + } + }, + "mainTemplate": { + "parameters": [ + "payload" + ], + "item": [ + { + "type": "Container", + "id": "BookCabSimpleDialogAPL", + "items": [ + { + "type": "TouchWrapper", + "onPress": { + "type": "SendEvent", + "arguments": [ + "delegateToColtraneOld" + ] + }, + "item": { + "type": "Text", + "id": "BookCabSimpleDialogAPL", + "paddingTop": "100", + "paddingLeft": "100", + "color": "green", + "size": 50, + "text": "which date ?" + } + } + ] + } + ] + } + } \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/display/confirm_weather_apla_display/document.json b/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/display/confirm_weather_apla_display/document.json new file mode 100644 index 00000000..1974945a --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/display/confirm_weather_apla_display/document.json @@ -0,0 +1,412 @@ +{ + "type": "APL", + "version": "1.1", + "settings": {}, + "theme": "dark", + "import": [ + { + "name": "alexa-layouts", + "version": "1.0.0" + } + ], + "resources": [ + { + "description": "Stock color for the light theme", + "colors": { + "colorTextPrimary": "#151920" + } + }, + { + "description": "Stock color for the dark theme", + "when": "${viewport.theme == 'dark'}", + "colors": { + "colorTextPrimary": "#f0f1ef" + } + }, + { + "description": "Standard font sizes", + "dimensions": { + "textSizeBody": 48, + "textSizePrimary": 27, + "textSizeSecondary": 23, + "textSizeDetails": 20, + "textSizeSecondaryHint": 25 + } + }, + { + "description": "Common spacing values", + "dimensions": { + "spacingThin": 6, + "spacingSmall": 12, + "spacingMedium": 24, + "spacingLarge": 48, + "spacingExtraLarge": 72 + } + }, + { + "description": "Common margins and padding", + "dimensions": { + "marginTop": 40, + "marginLeft": 60, + "marginRight": 60, + "marginBottom": 40 + } + } + ], + "styles": { + "textStyleBase": { + "description": "Base font description; set color", + "values": [ + { + "color": "@colorTextPrimary" + } + ] + }, + "textStyleBase0": { + "description": "Thin version of basic font", + "extend": "textStyleBase", + "values": { + "fontWeight": "100" + } + }, + "textStyleBase1": { + "description": "Light version of basic font", + "extend": "textStyleBase", + "values": { + "fontWeight": "300" + } + }, + "textStyleBase2": { + "description": "Regular version of basic font", + "extend": "textStyleBase", + "values": { + "fontWeight": "500" + } + }, + "mixinBody": { + "values": { + "fontSize": "@textSizeBody" + } + }, + "mixinPrimary": { + "values": { + "fontSize": "@textSizePrimary" + } + }, + "mixinDetails": { + "values": { + "fontSize": "@textSizeDetails" + } + }, + "mixinSecondary": { + "values": { + "fontSize": "@textSizeSecondary" + } + }, + "textStylePrimary": { + "extend": [ + "textStyleBase1", + "mixinPrimary" + ] + }, + "textStyleSecondary": { + "extend": [ + "textStyleBase0", + "mixinSecondary" + ] + }, + "textStyleBody": { + "extend": [ + "textStyleBase1", + "mixinBody" + ] + }, + "textStyleSecondaryHint": { + "values": { + "fontFamily": "Bookerly", + "fontStyle": "italic", + "fontSize": "@textSizeSecondaryHint", + "color": "@colorTextPrimary" + } + }, + "textStyleDetails": { + "extend": [ + "textStyleBase2", + "mixinDetails" + ] + } + }, + "onMount": [], + "graphics": {}, + "commands": {}, + "layouts": { + "ListTemplate1": { + "parameters": [ + "backgroundImage", + "title", + "logo", + "hintText", + "listData" + ], + "item": [ + { + "type": "Container", + "width": "100vw", + "height": "100vh", + "direction": "column", + "items": [ + { + "type": "Image", + "source": "${backgroundImage}", + "scale": "best-fill", + "width": "100vw", + "height": "100vh", + "position": "absolute" + }, + { + "type": "AlexaHeader", + "headerTitle": "${title}", + "headerAttributionImage": "${logo}" + }, + { + "type": "Sequence", + "grow": 1, + "height": "80vh", + "scrollDirection": "vertical", + "paddingLeft": "@marginLeft", + "paddingRight": "@marginRight", + "data": "${listData}", + "numbered": true, + "items": [ + { + "type": "VerticalListItem", + "image": "${data.image.sources[0].url}", + "primaryText": "${data.textContent.primaryText.text}", + "secondaryText": "${data.textContent.secondaryText.text}", + "tertiaryText": "${data.textContent.tertiaryText.text}" + } + ] + } + ] + } + ] + }, + "VerticalListItem": { + "parameters": [ + "primaryText", + "secondaryText", + "tertiaryText", + "image" + ], + "item": [ + { + "when": "${viewport.shape == 'round'}", + "type": "Container", + "direction": "row", + "height": 200, + "width": 500, + "alignItems": "center", + "items": [ + { + "type": "Text", + "text": "${ordinal}", + "paddingBottom": "20dp", + "color": "white", + "spacing": "5dp" + }, + { + "type": "Image", + "when": "${image}", + "source": "${image}", + "height": 150, + "width": 150, + "spacing": 15, + "scale": "best-fit", + "align": "top" + }, + { + "type": "Container", + "direction": "column", + "spacing": 25, + "items": [ + { + "type": "Text", + "text": "${primaryText}", + "style": "textStyleDetail", + "grow": 1, + "shrink": 1, + "fontWeight": "300", + "maxLines": 1 + }, + { + "type": "Text", + "text": "${secondaryText}", + "style": "textStyleCaption", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + }, + { + "type": "Text", + "text": "${tertiaryText}", + "style": "textStyleDetails", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + } + ] + } + ] + }, + { + "type": "Container", + "direction": "row", + "height": 125, + "width": 800, + "alignItems": "center", + "items": [ + { + "type": "Text", + "text": "${ordinal}", + "paddingBottom": "20dp", + "color": "white", + "spacing": "5dp" + }, + { + "type": "Image", + "when": "${image}", + "source": "${image}", + "height": 100, + "width": 100, + "align": "top", + "spacing": 50, + "scale": "best-fit" + }, + { + "type": "Container", + "spacing": 30, + "direction": "column", + "items": [ + { + "type": "Text", + "text": "${primaryText}", + "style": "textStyleBody", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + }, + { + "type": "Text", + "text": "${secondaryText}", + "style": "textStyleDetails", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + } + ] + }, + { + "type": "Text", + "text": "${tertiaryText}", + "style": "textStyleBody", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "textAlign": "right", + "maxLines": 1 + } + ] + } + ] + } + }, + "mainTemplate": { + "parameters": [ + "payload" + ], + "item": [ + { + "type": "Container", + "id": "BookCabSimpleDialogAPL", + "items": [ + { + "type": "TouchWrapper", + "onPress": { + "type": "SendEvent", + "arguments": [ + "delegateToSkillNew" + ] + }, + "item": { + "type": "Text", + "id": "BookCabSimpleDialogAPL", + "paddingTop": "100", + "paddingLeft": "100", + "color": "green", + "size": 50, + "text": "delegateToSkillNew" + } + }, + { + "type": "TouchWrapper", + "onPress": { + "type": "SendEvent", + "arguments": [ + "delegateToSkillOld" + ] + }, + "item": { + "type": "Text", + "id": "BookCabSimpleDialogAPL", + "paddingTop": "100", + "paddingLeft": "100", + "color": "green", + "size": 50, + "text": "delegateToSkillOld" + } + }, + { + "type": "TouchWrapper", + "onPress": { + "type": "SendEvent", + "arguments": [ + "delegateToColtraneNew" + ] + }, + "item": { + "type": "Text", + "id": "BookCabSimpleDialogAPL", + "paddingTop": "100", + "paddingLeft": "100", + "color": "green", + "size": 50, + "text": "delegateToColtraneNew" + } + }, + { + "type": "TouchWrapper", + "onPress": { + "type": "SendEvent", + "arguments": [ + "delegateToColtraneOld" + ] + }, + "item": { + "type": "Text", + "id": "BookCabSimpleDialogAPL", + "paddingTop": "100", + "paddingLeft": "100", + "color": "green", + "size": 50, + "text": "delegateToColtraneOld" + } + } + ] + } + ] + } +} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/display/request_city_apl_display/document.json b/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/display/request_city_apl_display/document.json new file mode 100644 index 00000000..741e1a5f --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/display/request_city_apl_display/document.json @@ -0,0 +1,358 @@ +{ + "type": "APL", + "version": "1.1", + "settings": {}, + "theme": "dark", + "import": [ + { + "name": "alexa-layouts", + "version": "1.0.0" + } + ], + "resources": [ + { + "description": "Stock color for the light theme", + "colors": { + "colorTextPrimary": "#151920" + } + }, + { + "description": "Stock color for the dark theme", + "when": "${viewport.theme == 'dark'}", + "colors": { + "colorTextPrimary": "#f0f1ef" + } + }, + { + "description": "Standard font sizes", + "dimensions": { + "textSizeBody": 48, + "textSizePrimary": 27, + "textSizeSecondary": 23, + "textSizeDetails": 20, + "textSizeSecondaryHint": 25 + } + }, + { + "description": "Common spacing values", + "dimensions": { + "spacingThin": 6, + "spacingSmall": 12, + "spacingMedium": 24, + "spacingLarge": 48, + "spacingExtraLarge": 72 + } + }, + { + "description": "Common margins and padding", + "dimensions": { + "marginTop": 40, + "marginLeft": 60, + "marginRight": 60, + "marginBottom": 40 + } + } + ], + "styles": { + "textStyleBase": { + "description": "Base font description; set color", + "values": [ + { + "color": "@colorTextPrimary" + } + ] + }, + "textStyleBase0": { + "description": "Thin version of basic font", + "extend": "textStyleBase", + "values": { + "fontWeight": "100" + } + }, + "textStyleBase1": { + "description": "Light version of basic font", + "extend": "textStyleBase", + "values": { + "fontWeight": "300" + } + }, + "textStyleBase2": { + "description": "Regular version of basic font", + "extend": "textStyleBase", + "values": { + "fontWeight": "500" + } + }, + "mixinBody": { + "values": { + "fontSize": "@textSizeBody" + } + }, + "mixinPrimary": { + "values": { + "fontSize": "@textSizePrimary" + } + }, + "mixinDetails": { + "values": { + "fontSize": "@textSizeDetails" + } + }, + "mixinSecondary": { + "values": { + "fontSize": "@textSizeSecondary" + } + }, + "textStylePrimary": { + "extend": [ + "textStyleBase1", + "mixinPrimary" + ] + }, + "textStyleSecondary": { + "extend": [ + "textStyleBase0", + "mixinSecondary" + ] + }, + "textStyleBody": { + "extend": [ + "textStyleBase1", + "mixinBody" + ] + }, + "textStyleSecondaryHint": { + "values": { + "fontFamily": "Bookerly", + "fontStyle": "italic", + "fontSize": "@textSizeSecondaryHint", + "color": "@colorTextPrimary" + } + }, + "textStyleDetails": { + "extend": [ + "textStyleBase2", + "mixinDetails" + ] + } + }, + "onMount": [], + "graphics": {}, + "commands": {}, + "layouts": { + "ListTemplate1": { + "parameters": [ + "backgroundImage", + "title", + "logo", + "hintText", + "listData" + ], + "item": [ + { + "type": "Container", + "width": "100vw", + "height": "100vh", + "direction": "column", + "items": [ + { + "type": "Image", + "source": "${backgroundImage}", + "scale": "best-fill", + "width": "100vw", + "height": "100vh", + "position": "absolute" + }, + { + "type": "AlexaHeader", + "headerTitle": "${title}", + "headerAttributionImage": "${logo}" + }, + { + "type": "Sequence", + "grow": 1, + "height": "80vh", + "scrollDirection": "vertical", + "paddingLeft": "@marginLeft", + "paddingRight": "@marginRight", + "data": "${listData}", + "numbered": true, + "items": [ + { + "type": "VerticalListItem", + "image": "${data.image.sources[0].url}", + "primaryText": "${data.textContent.primaryText.text}", + "secondaryText": "${data.textContent.secondaryText.text}", + "tertiaryText": "${data.textContent.tertiaryText.text}" + } + ] + } + ] + } + ] + }, + "VerticalListItem": { + "parameters": [ + "primaryText", + "secondaryText", + "tertiaryText", + "image" + ], + "item": [ + { + "when": "${viewport.shape == 'round'}", + "type": "Container", + "direction": "row", + "height": 200, + "width": 500, + "alignItems": "center", + "items": [ + { + "type": "Text", + "text": "${ordinal}", + "paddingBottom": "20dp", + "color": "white", + "spacing": "5dp" + }, + { + "type": "Image", + "when": "${image}", + "source": "${image}", + "height": 150, + "width": 150, + "spacing": 15, + "scale": "best-fit", + "align": "top" + }, + { + "type": "Container", + "direction": "column", + "spacing": 25, + "items": [ + { + "type": "Text", + "text": "${primaryText}", + "style": "textStyleDetail", + "grow": 1, + "shrink": 1, + "fontWeight": "300", + "maxLines": 1 + }, + { + "type": "Text", + "text": "${secondaryText}", + "style": "textStyleCaption", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + }, + { + "type": "Text", + "text": "${tertiaryText}", + "style": "textStyleDetails", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + } + ] + } + ] + }, + { + "type": "Container", + "direction": "row", + "height": 125, + "width": 800, + "alignItems": "center", + "items": [ + { + "type": "Text", + "text": "${ordinal}", + "paddingBottom": "20dp", + "color": "white", + "spacing": "5dp" + }, + { + "type": "Image", + "when": "${image}", + "source": "${image}", + "height": 100, + "width": 100, + "align": "top", + "spacing": 50, + "scale": "best-fit" + }, + { + "type": "Container", + "spacing": 30, + "direction": "column", + "items": [ + { + "type": "Text", + "text": "${primaryText}", + "style": "textStyleBody", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + }, + { + "type": "Text", + "text": "${secondaryText}", + "style": "textStyleDetails", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + } + ] + }, + { + "type": "Text", + "text": "${tertiaryText}", + "style": "textStyleBody", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "textAlign": "right", + "maxLines": 1 + } + ] + } + ] + } + }, + "mainTemplate": { + "parameters": [ + "payload" + ], + "item": [ + { + "type": "Container", + "id": "BookCabSimpleDialogAPL", + "items": [ + { + "type": "TouchWrapper", + "onPress": { + "type": "SendEvent", + "arguments": [ + "delegateToColtraneOld" + ] + }, + "item": { + "type": "Text", + "id": "BookCabSimpleDialogAPL", + "paddingTop": "100", + "paddingLeft": "100", + "color": "green", + "size": 50, + "text": "which city ?" + } + } + ] + } + ] + } +} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/display/request_date_apl_display/document.json b/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/display/request_date_apl_display/document.json new file mode 100644 index 00000000..9ff71e5c --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/display/request_date_apl_display/document.json @@ -0,0 +1,358 @@ +{ + "type": "APL", + "version": "1.1", + "settings": {}, + "theme": "dark", + "import": [ + { + "name": "alexa-layouts", + "version": "1.0.0" + } + ], + "resources": [ + { + "description": "Stock color for the light theme", + "colors": { + "colorTextPrimary": "#151920" + } + }, + { + "description": "Stock color for the dark theme", + "when": "${viewport.theme == 'dark'}", + "colors": { + "colorTextPrimary": "#f0f1ef" + } + }, + { + "description": "Standard font sizes", + "dimensions": { + "textSizeBody": 48, + "textSizePrimary": 27, + "textSizeSecondary": 23, + "textSizeDetails": 20, + "textSizeSecondaryHint": 25 + } + }, + { + "description": "Common spacing values", + "dimensions": { + "spacingThin": 6, + "spacingSmall": 12, + "spacingMedium": 24, + "spacingLarge": 48, + "spacingExtraLarge": 72 + } + }, + { + "description": "Common margins and padding", + "dimensions": { + "marginTop": 40, + "marginLeft": 60, + "marginRight": 60, + "marginBottom": 40 + } + } + ], + "styles": { + "textStyleBase": { + "description": "Base font description; set color", + "values": [ + { + "color": "@colorTextPrimary" + } + ] + }, + "textStyleBase0": { + "description": "Thin version of basic font", + "extend": "textStyleBase", + "values": { + "fontWeight": "100" + } + }, + "textStyleBase1": { + "description": "Light version of basic font", + "extend": "textStyleBase", + "values": { + "fontWeight": "300" + } + }, + "textStyleBase2": { + "description": "Regular version of basic font", + "extend": "textStyleBase", + "values": { + "fontWeight": "500" + } + }, + "mixinBody": { + "values": { + "fontSize": "@textSizeBody" + } + }, + "mixinPrimary": { + "values": { + "fontSize": "@textSizePrimary" + } + }, + "mixinDetails": { + "values": { + "fontSize": "@textSizeDetails" + } + }, + "mixinSecondary": { + "values": { + "fontSize": "@textSizeSecondary" + } + }, + "textStylePrimary": { + "extend": [ + "textStyleBase1", + "mixinPrimary" + ] + }, + "textStyleSecondary": { + "extend": [ + "textStyleBase0", + "mixinSecondary" + ] + }, + "textStyleBody": { + "extend": [ + "textStyleBase1", + "mixinBody" + ] + }, + "textStyleSecondaryHint": { + "values": { + "fontFamily": "Bookerly", + "fontStyle": "italic", + "fontSize": "@textSizeSecondaryHint", + "color": "@colorTextPrimary" + } + }, + "textStyleDetails": { + "extend": [ + "textStyleBase2", + "mixinDetails" + ] + } + }, + "onMount": [], + "graphics": {}, + "commands": {}, + "layouts": { + "ListTemplate1": { + "parameters": [ + "backgroundImage", + "title", + "logo", + "hintText", + "listData" + ], + "item": [ + { + "type": "Container", + "width": "100vw", + "height": "100vh", + "direction": "column", + "items": [ + { + "type": "Image", + "source": "${backgroundImage}", + "scale": "best-fill", + "width": "100vw", + "height": "100vh", + "position": "absolute" + }, + { + "type": "AlexaHeader", + "headerTitle": "${title}", + "headerAttributionImage": "${logo}" + }, + { + "type": "Sequence", + "grow": 1, + "height": "80vh", + "scrollDirection": "vertical", + "paddingLeft": "@marginLeft", + "paddingRight": "@marginRight", + "data": "${listData}", + "numbered": true, + "items": [ + { + "type": "VerticalListItem", + "image": "${data.image.sources[0].url}", + "primaryText": "${data.textContent.primaryText.text}", + "secondaryText": "${data.textContent.secondaryText.text}", + "tertiaryText": "${data.textContent.tertiaryText.text}" + } + ] + } + ] + } + ] + }, + "VerticalListItem": { + "parameters": [ + "primaryText", + "secondaryText", + "tertiaryText", + "image" + ], + "item": [ + { + "when": "${viewport.shape == 'round'}", + "type": "Container", + "direction": "row", + "height": 200, + "width": 500, + "alignItems": "center", + "items": [ + { + "type": "Text", + "text": "${ordinal}", + "paddingBottom": "20dp", + "color": "white", + "spacing": "5dp" + }, + { + "type": "Image", + "when": "${image}", + "source": "${image}", + "height": 150, + "width": 150, + "spacing": 15, + "scale": "best-fit", + "align": "top" + }, + { + "type": "Container", + "direction": "column", + "spacing": 25, + "items": [ + { + "type": "Text", + "text": "${primaryText}", + "style": "textStyleDetail", + "grow": 1, + "shrink": 1, + "fontWeight": "300", + "maxLines": 1 + }, + { + "type": "Text", + "text": "${secondaryText}", + "style": "textStyleCaption", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + }, + { + "type": "Text", + "text": "${tertiaryText}", + "style": "textStyleDetails", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + } + ] + } + ] + }, + { + "type": "Container", + "direction": "row", + "height": 125, + "width": 800, + "alignItems": "center", + "items": [ + { + "type": "Text", + "text": "${ordinal}", + "paddingBottom": "20dp", + "color": "white", + "spacing": "5dp" + }, + { + "type": "Image", + "when": "${image}", + "source": "${image}", + "height": 100, + "width": 100, + "align": "top", + "spacing": 50, + "scale": "best-fit" + }, + { + "type": "Container", + "spacing": 30, + "direction": "column", + "items": [ + { + "type": "Text", + "text": "${primaryText}", + "style": "textStyleBody", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + }, + { + "type": "Text", + "text": "${secondaryText}", + "style": "textStyleDetails", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + } + ] + }, + { + "type": "Text", + "text": "${tertiaryText}", + "style": "textStyleBody", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "textAlign": "right", + "maxLines": 1 + } + ] + } + ] + } + }, + "mainTemplate": { + "parameters": [ + "payload" + ], + "item": [ + { + "type": "Container", + "id": "BookCabSimpleDialogAPL", + "items": [ + { + "type": "TouchWrapper", + "onPress": { + "type": "SendEvent", + "arguments": [ + "delegateToColtraneOld" + ] + }, + "item": { + "type": "Text", + "id": "BookCabSimpleDialogAPL", + "paddingTop": "100", + "paddingLeft": "100", + "color": "green", + "size": 50, + "text": "which date ?" + } + } + ] + } + ] + } + } \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/display/weather_success_apl_display/document.json b/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/display/weather_success_apl_display/document.json new file mode 100644 index 00000000..1974945a --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/display/weather_success_apl_display/document.json @@ -0,0 +1,412 @@ +{ + "type": "APL", + "version": "1.1", + "settings": {}, + "theme": "dark", + "import": [ + { + "name": "alexa-layouts", + "version": "1.0.0" + } + ], + "resources": [ + { + "description": "Stock color for the light theme", + "colors": { + "colorTextPrimary": "#151920" + } + }, + { + "description": "Stock color for the dark theme", + "when": "${viewport.theme == 'dark'}", + "colors": { + "colorTextPrimary": "#f0f1ef" + } + }, + { + "description": "Standard font sizes", + "dimensions": { + "textSizeBody": 48, + "textSizePrimary": 27, + "textSizeSecondary": 23, + "textSizeDetails": 20, + "textSizeSecondaryHint": 25 + } + }, + { + "description": "Common spacing values", + "dimensions": { + "spacingThin": 6, + "spacingSmall": 12, + "spacingMedium": 24, + "spacingLarge": 48, + "spacingExtraLarge": 72 + } + }, + { + "description": "Common margins and padding", + "dimensions": { + "marginTop": 40, + "marginLeft": 60, + "marginRight": 60, + "marginBottom": 40 + } + } + ], + "styles": { + "textStyleBase": { + "description": "Base font description; set color", + "values": [ + { + "color": "@colorTextPrimary" + } + ] + }, + "textStyleBase0": { + "description": "Thin version of basic font", + "extend": "textStyleBase", + "values": { + "fontWeight": "100" + } + }, + "textStyleBase1": { + "description": "Light version of basic font", + "extend": "textStyleBase", + "values": { + "fontWeight": "300" + } + }, + "textStyleBase2": { + "description": "Regular version of basic font", + "extend": "textStyleBase", + "values": { + "fontWeight": "500" + } + }, + "mixinBody": { + "values": { + "fontSize": "@textSizeBody" + } + }, + "mixinPrimary": { + "values": { + "fontSize": "@textSizePrimary" + } + }, + "mixinDetails": { + "values": { + "fontSize": "@textSizeDetails" + } + }, + "mixinSecondary": { + "values": { + "fontSize": "@textSizeSecondary" + } + }, + "textStylePrimary": { + "extend": [ + "textStyleBase1", + "mixinPrimary" + ] + }, + "textStyleSecondary": { + "extend": [ + "textStyleBase0", + "mixinSecondary" + ] + }, + "textStyleBody": { + "extend": [ + "textStyleBase1", + "mixinBody" + ] + }, + "textStyleSecondaryHint": { + "values": { + "fontFamily": "Bookerly", + "fontStyle": "italic", + "fontSize": "@textSizeSecondaryHint", + "color": "@colorTextPrimary" + } + }, + "textStyleDetails": { + "extend": [ + "textStyleBase2", + "mixinDetails" + ] + } + }, + "onMount": [], + "graphics": {}, + "commands": {}, + "layouts": { + "ListTemplate1": { + "parameters": [ + "backgroundImage", + "title", + "logo", + "hintText", + "listData" + ], + "item": [ + { + "type": "Container", + "width": "100vw", + "height": "100vh", + "direction": "column", + "items": [ + { + "type": "Image", + "source": "${backgroundImage}", + "scale": "best-fill", + "width": "100vw", + "height": "100vh", + "position": "absolute" + }, + { + "type": "AlexaHeader", + "headerTitle": "${title}", + "headerAttributionImage": "${logo}" + }, + { + "type": "Sequence", + "grow": 1, + "height": "80vh", + "scrollDirection": "vertical", + "paddingLeft": "@marginLeft", + "paddingRight": "@marginRight", + "data": "${listData}", + "numbered": true, + "items": [ + { + "type": "VerticalListItem", + "image": "${data.image.sources[0].url}", + "primaryText": "${data.textContent.primaryText.text}", + "secondaryText": "${data.textContent.secondaryText.text}", + "tertiaryText": "${data.textContent.tertiaryText.text}" + } + ] + } + ] + } + ] + }, + "VerticalListItem": { + "parameters": [ + "primaryText", + "secondaryText", + "tertiaryText", + "image" + ], + "item": [ + { + "when": "${viewport.shape == 'round'}", + "type": "Container", + "direction": "row", + "height": 200, + "width": 500, + "alignItems": "center", + "items": [ + { + "type": "Text", + "text": "${ordinal}", + "paddingBottom": "20dp", + "color": "white", + "spacing": "5dp" + }, + { + "type": "Image", + "when": "${image}", + "source": "${image}", + "height": 150, + "width": 150, + "spacing": 15, + "scale": "best-fit", + "align": "top" + }, + { + "type": "Container", + "direction": "column", + "spacing": 25, + "items": [ + { + "type": "Text", + "text": "${primaryText}", + "style": "textStyleDetail", + "grow": 1, + "shrink": 1, + "fontWeight": "300", + "maxLines": 1 + }, + { + "type": "Text", + "text": "${secondaryText}", + "style": "textStyleCaption", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + }, + { + "type": "Text", + "text": "${tertiaryText}", + "style": "textStyleDetails", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + } + ] + } + ] + }, + { + "type": "Container", + "direction": "row", + "height": 125, + "width": 800, + "alignItems": "center", + "items": [ + { + "type": "Text", + "text": "${ordinal}", + "paddingBottom": "20dp", + "color": "white", + "spacing": "5dp" + }, + { + "type": "Image", + "when": "${image}", + "source": "${image}", + "height": 100, + "width": 100, + "align": "top", + "spacing": 50, + "scale": "best-fit" + }, + { + "type": "Container", + "spacing": 30, + "direction": "column", + "items": [ + { + "type": "Text", + "text": "${primaryText}", + "style": "textStyleBody", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + }, + { + "type": "Text", + "text": "${secondaryText}", + "style": "textStyleDetails", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + } + ] + }, + { + "type": "Text", + "text": "${tertiaryText}", + "style": "textStyleBody", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "textAlign": "right", + "maxLines": 1 + } + ] + } + ] + } + }, + "mainTemplate": { + "parameters": [ + "payload" + ], + "item": [ + { + "type": "Container", + "id": "BookCabSimpleDialogAPL", + "items": [ + { + "type": "TouchWrapper", + "onPress": { + "type": "SendEvent", + "arguments": [ + "delegateToSkillNew" + ] + }, + "item": { + "type": "Text", + "id": "BookCabSimpleDialogAPL", + "paddingTop": "100", + "paddingLeft": "100", + "color": "green", + "size": 50, + "text": "delegateToSkillNew" + } + }, + { + "type": "TouchWrapper", + "onPress": { + "type": "SendEvent", + "arguments": [ + "delegateToSkillOld" + ] + }, + "item": { + "type": "Text", + "id": "BookCabSimpleDialogAPL", + "paddingTop": "100", + "paddingLeft": "100", + "color": "green", + "size": 50, + "text": "delegateToSkillOld" + } + }, + { + "type": "TouchWrapper", + "onPress": { + "type": "SendEvent", + "arguments": [ + "delegateToColtraneNew" + ] + }, + "item": { + "type": "Text", + "id": "BookCabSimpleDialogAPL", + "paddingTop": "100", + "paddingLeft": "100", + "color": "green", + "size": 50, + "text": "delegateToColtraneNew" + } + }, + { + "type": "TouchWrapper", + "onPress": { + "type": "SendEvent", + "arguments": [ + "delegateToColtraneOld" + ] + }, + "item": { + "type": "Text", + "id": "BookCabSimpleDialogAPL", + "paddingTop": "100", + "paddingLeft": "100", + "color": "green", + "size": 50, + "text": "delegateToColtraneOld" + } + } + ] + } + ] + } +} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/AlexaConversationsBye/document.json b/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/AlexaConversationsBye/document.json new file mode 100644 index 00000000..bde5ee56 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/AlexaConversationsBye/document.json @@ -0,0 +1,21 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": [ + "payload" + ], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "Bye.", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/AlexaConversationsNotifyFailure/document.json b/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/AlexaConversationsNotifyFailure/document.json new file mode 100644 index 00000000..c31fe279 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/AlexaConversationsNotifyFailure/document.json @@ -0,0 +1,21 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": [ + "payload" + ], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "Sorry, there was an error in the request.", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/AlexaConversationsOutOfDomain/document.json b/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/AlexaConversationsOutOfDomain/document.json new file mode 100644 index 00000000..3796d4d5 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/AlexaConversationsOutOfDomain/document.json @@ -0,0 +1,21 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": [ + "payload" + ], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "Sorry, I don't understand.", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/AlexaConversationsProvideHelp/document.json b/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/AlexaConversationsProvideHelp/document.json new file mode 100644 index 00000000..13b27c11 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/AlexaConversationsProvideHelp/document.json @@ -0,0 +1,21 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": [ + "payload" + ], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "I can give you the weather report. Just say \"what's the weather\" to start.", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/AlexaConversationsRequestMore/document.json b/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/AlexaConversationsRequestMore/document.json new file mode 100644 index 00000000..fb3e56ae --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/AlexaConversationsRequestMore/document.json @@ -0,0 +1,21 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": [ + "payload" + ], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "What do you want to do.", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/AlexaConversationsThankYou/document.json b/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/AlexaConversationsThankYou/document.json new file mode 100644 index 00000000..2112f02e --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/AlexaConversationsThankYou/document.json @@ -0,0 +1,21 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": [ + "payload" + ], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "Thank you.", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/AlexaConversationsWelcome/document.json b/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/AlexaConversationsWelcome/document.json new file mode 100644 index 00000000..aeacaae2 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/AlexaConversationsWelcome/document.json @@ -0,0 +1,21 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": [ + "payload" + ], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "Welcome to the weather bot, I can give you the weather report. Just say \"what's the weather\" to start.", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/AlexaConversationsYouAreWelcome/document.json b/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/AlexaConversationsYouAreWelcome/document.json new file mode 100644 index 00000000..7ade07ba --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/AlexaConversationsYouAreWelcome/document.json @@ -0,0 +1,21 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": [ + "payload" + ], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "You are welcome.", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/alexa_prize_preconditions_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/alexa_prize_preconditions_apla/document.json new file mode 100644 index 00000000..e50c4e94 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/alexa_prize_preconditions_apla/document.json @@ -0,0 +1,91 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": [ + "payload" + ], + "item": { + "type": "Selector", + "description": "Selects the speech response to render when device/locale is not supported", + "items": [ + { + "when": "${payload.result.isDeviceSupported == 0}", + "type": "Speech", + "contentType": "text", + "content": "Sorry, Alexa Prize is not available on this device.", + "description": "" + }, + { + "when": "${payload.result.isLocaleSupported == 0}", + "type": "Speech", + "contentType": "text", + "content": "Sorry, Alexa Prize is not available in your locale.", + "description": "" + }, + { + "when": "${payload.result.isSocialBotAvailable == 0}", + "type": "Speech", + "contentType": "text", + "content": "Right now the Alexa Prize socialbots are busy. Please try again soon and help the university students in their competition to advance conversational A I.", + "description": "" + }, + { + "when": "${payload.result.isAlexaPrizeEnabled == 0}", + "type": "Speech", + "contentType": "text", + "content": "Alexa Prize is currently disabled for this account. Please visit the skill store in the Alexa App to re-enable it.", + "description": "" + }, + { + "when": "${payload.result.isTopicBanned == 1}", + "type": "Speech", + "contentType": "text", + "content": "I’d rather not talk about that, but there’s lots of other things to chat about. Do you still wanna chat?", + "description": "The topic that user wants to talk about is banned, ask if they still want to chat about something else" + }, + { + "when": "${payload.result.isFalseWake == 1}", + "type": "Speech", + "contentType": "text", + "content": "Would you like to chat with an Alexa Prize socialbot?", + "description": "" + }, + { + "when": "${payload.result.handoffPromptOverride == 'HandOffConversationForFilming'}", + "type": "Speech", + "contentType": "text", + "content": "Welcome to the Finals of the Alexa Prize Socialbot Grand Challenge 3, a university competition to advance AI. I’ll get you a socialbot now.", + "description": "" + }, + { + "when": "${payload.result.handoffPromptOverride == 'HandOffConversationForFinals'}", + "type": "Speech", + "contentType": "text", + "content": "Welcome to the Alexa Prize Socialbot Grand Challenge 3: Grand Finale. Here’s one of the finalists.", + "description": "" + }, + { + "when": "${payload.result.handoffPromptOverride == 'HandOffConversationForRepeatUser'}", + "type": "Speech", + "contentType": "text", + "content": "Welcome to the Alexa Prize, a university competition to advance AI. It’s quarterfinals for these socialbots and your ratings help determine who makes it to the semifinals. I’ll get you a socialbot now. When you’re done, say stop, and I’ll ask you for your rating. Your conversation and feedback will be shared with the university to help the socialbots improve.", + "description": "" + }, + { + "when": "${payload.result.handoffPromptOverride == 'CancelHandoff'}", + "type": "Speech", + "contentType": "text", + "content": "Okay", + "description": "" + }, + { + "type": "Speech", + "contentType": "text", + "content": "Welcome to the Alexa Prize, a university competition to advance AI. It’s quarterfinals for these socialbots and your ratings help determine who makes it to the semifinals. I’ll get you a socialbot now. When you’re done, say stop, and I’ll ask you for your rating. Your conversation and feedback will be shared with the university to help the socialbots improve.", + "description": "This is the current default handoff prompt" + } + ] + } + } +} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/confirm_color_for_fruit_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/confirm_color_for_fruit_apla/document.json new file mode 100644 index 00000000..835d7a8e --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/confirm_color_for_fruit_apla/document.json @@ -0,0 +1,21 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": [ + "payload" + ], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "confirm color is ${payload.colorName} ? ", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/confirm_fruitName_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/confirm_fruitName_apla/document.json new file mode 100644 index 00000000..42d63adc --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/confirm_fruitName_apla/document.json @@ -0,0 +1,21 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": [ + "payload" + ], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "confirm fruit ${payload.fruitName} ? ", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/getEmployeePosition_success_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/getEmployeePosition_success_apla/document.json new file mode 100644 index 00000000..4f5794c0 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/getEmployeePosition_success_apla/document.json @@ -0,0 +1,21 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": [ + "payload" + ], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "${payload.result.name1} born on ${payload.result.a_dateOfBirth} with employee id ${payload.result.emplyee1id} , is an ${payload.result.position} ", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/no_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/no_apla/document.json new file mode 100644 index 00000000..76610fcc --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/no_apla/document.json @@ -0,0 +1,21 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": [ + "payload" + ], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "I'm sorry you didn't like it", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/nothing2_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/nothing2_apla/document.json new file mode 100644 index 00000000..98f7ebef --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/nothing2_apla/document.json @@ -0,0 +1,21 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": [ + "payload" + ], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "The number you gave us was not 3.", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/nothing_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/nothing_apla/document.json new file mode 100644 index 00000000..5272f2a9 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/nothing_apla/document.json @@ -0,0 +1,21 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": [ + "payload" + ], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "The number you gave us was 3.", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/numericfeedback_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/numericfeedback_apla/document.json new file mode 100644 index 00000000..5278049b --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/numericfeedback_apla/document.json @@ -0,0 +1,19 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": [ + "payload" + ], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [{ + "type": "Speech", + "contentType": "text", + "content": "Your random number was ${payload.num}. How did we do? Please give this interaction a rating between 1-5, where 5 is the highest rating", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + }] + } + } +} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/rating_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/rating_apla/document.json new file mode 100644 index 00000000..7d50a649 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/rating_apla/document.json @@ -0,0 +1,21 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": [ + "payload" + ], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "rating please?", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/requestArgs_request_fruitName_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/requestArgs_request_fruitName_apla/document.json new file mode 100644 index 00000000..a27a7d1e --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/requestArgs_request_fruitName_apla/document.json @@ -0,0 +1,27 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": [ + "payload" + ], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "tell me the fruit name ?", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + }, + { + "type": "Speech", + "contentType": "text", + "content": "random slection tell me the fruit name ?", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/request_city_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/request_city_apla/document.json new file mode 100644 index 00000000..65c28562 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/request_city_apla/document.json @@ -0,0 +1,21 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": [ + "payload" + ], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "Which city?", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/request_city_date_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/request_city_date_apla/document.json new file mode 100644 index 00000000..f685b93e --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/request_city_date_apla/document.json @@ -0,0 +1,21 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": [ + "payload" + ], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "Which city and for which date?", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/request_colorName_multiple_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/request_colorName_multiple_apla/document.json new file mode 100644 index 00000000..62911ca4 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/request_colorName_multiple_apla/document.json @@ -0,0 +1,21 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": [ + "payload" + ], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "which color?", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/request_date_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/request_date_apla/document.json new file mode 100644 index 00000000..3beebe7b --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/request_date_apla/document.json @@ -0,0 +1,21 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": [ + "payload" + ], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "Which date?", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/request_dob_getDate_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/request_dob_getDate_apla/document.json new file mode 100644 index 00000000..cabe7441 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/request_dob_getDate_apla/document.json @@ -0,0 +1,21 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": [ + "payload" + ], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "SSML", + "content": "provide date?", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/request_getEmploeeID_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/request_getEmploeeID_apla/document.json new file mode 100644 index 00000000..7649453f --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/request_getEmploeeID_apla/document.json @@ -0,0 +1,21 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": [ + "payload" + ], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "SSML", + "content": "provide employee id?", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/request_name_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/request_name_apla/document.json new file mode 100644 index 00000000..8afc80bf --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/request_name_apla/document.json @@ -0,0 +1,21 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": [ + "payload" + ], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "SSML", + "content": "what is your cool name?", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/success_colorFruitAPI_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/success_colorFruitAPI_apla/document.json new file mode 100644 index 00000000..873e2711 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/success_colorFruitAPI_apla/document.json @@ -0,0 +1,21 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": [ + "payload" + ], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "price of an ${payload.result.fruitName} is free bucks ", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/success_fruitPriceAPI_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/success_fruitPriceAPI_apla/document.json new file mode 100644 index 00000000..b4a7272b --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/success_fruitPriceAPI_apla/document.json @@ -0,0 +1,21 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": [ + "payload" + ], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "price of an ${payload.result.fruitName} is ${payload.result.price} bucks ", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/weather_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/weather_apla/document.json new file mode 100644 index 00000000..4c5d2883 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/weather_apla/document.json @@ -0,0 +1,29 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": [ + "payload" + ], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "when": "${payload.weatherResult != null && payload.weatherResult.cityName != null && payload.weatherResult.highTemp != null && payload.weatherResult.lowTemp != null}", + "type": "Speech", + "contentType": "text", + "content": "In ${payload.weatherResult.cityName}, it's a high of ${payload.weatherResult.highTemp} degrees and a low of ${payload.weatherResult.lowTemp} degrees.", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + }, + { + "when": "${payload.weatherResult != null && payload.weatherResult.cityNameChanged != null && payload.weatherResult.highTemp != null && payload.weatherResult.lowTemp != null}", + "type": "Speech", + "contentType": "text", + "content": "In ${payload.weatherResult.cityName}, it's a high of ${payload.weatherResult.highTemp} degrees and a low of ${payload.weatherResult.lowTemp} degrees.", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/yes_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/yes_apla/document.json new file mode 100644 index 00000000..021dec67 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/yes_apla/document.json @@ -0,0 +1,21 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": [ + "payload" + ], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "Nice! Glad you like it", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/yesnofeedback_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/yesnofeedback_apla/document.json new file mode 100644 index 00000000..f0242d89 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/yesnofeedback_apla/document.json @@ -0,0 +1,21 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": [ + "payload" + ], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "Your number was ${payload.num}. Is this a good number, yes or no?", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/skill.json b/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/skill.json new file mode 100644 index 00000000..122472ef --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/skill.json @@ -0,0 +1,97 @@ +{ + "manifest": { + "apis": { + "custom": { + "dialogManagement": { + "dialogManagers": [ + { + "type": "AMAZON.Conversations" + } + ], + "sessionStartDelegationStrategy": { + "target": "AMAZON.Conversations" + } + }, + "endpoint": { + "uri": "arn:aws:lambda:us-west-2:267006587462:function:ramansatTestFunction" + }, + "interfaces": [ + { + "supportedViewports": [ + { + "maxHeight": 480, + "maxWidth": 480, + "minHeight": 480, + "minWidth": 480, + "mode": "HUB", + "shape": "ROUND" + }, + { + "maxHeight": 600, + "maxWidth": 1024, + "minHeight": 600, + "minWidth": 1024, + "mode": "HUB", + "shape": "RECTANGLE" + }, + { + "maxHeight": 800, + "maxWidth": 1280, + "minHeight": 800, + "minWidth": 1280, + "mode": "HUB", + "shape": "RECTANGLE" + }, + { + "maxHeight": 540, + "maxWidth": 960, + "minHeight": 540, + "minWidth": 960, + "mode": "TV", + "shape": "RECTANGLE" + } + ], + "type": "ALEXA_PRESENTATION_APL" + } + ], + "regions": { + "NA": { + "endpoint": { + "uri": "arn:aws:lambda:us-west-2:267006587462:function:ramansatTestFunction" + } + }, + "EU": { + "endpoint": { + "uri": "arn:aws:lambda:us-west-2:267006587462:function:ramansatTestFunction" + } + }, + "FE": { + "endpoint": { + "uri": "arn:aws:lambda:us-west-2:267006587462:function:ramansatTestFunction" + } + } + } + } + }, + "manifestVersion": "1.0", + "publishingInformation": { + "category": "KNOWLEDGE_AND_TRIVIA", + "distributionCountries": [], + "isAvailableWorldwide": true, + "locales": { + "en-US": { + "description": "Sample Full Description", + "examplePhrases": [ + "Alexa open hello world", + "hello", + "help" + ], + "keywords": [], + "name": "engineering test skill one_four", + "summary": "Sample Short Description" + } + }, + "testingInstructions": "Sample Testing Instructions." + } + } +} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-7/.ask/ask-states.json b/test/unit/fixture/dialog-evaluate/test-project-7/.ask/ask-states.json new file mode 100644 index 00000000..04b60573 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-7/.ask/ask-states.json @@ -0,0 +1,8 @@ +{ + "askcliStatesVersion": "2020-03-31", + "profiles": { + "default": { + "skillId": "amzn1.ask.skill.a39d8c76-9c33-4e1a-8d1f-7e99ba199551" + } + } +} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-7/ask-resources.json b/test/unit/fixture/dialog-evaluate/test-project-7/ask-resources.json new file mode 100644 index 00000000..be9cb8d1 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-7/ask-resources.json @@ -0,0 +1,10 @@ +{ + "askcliResourcesVersion": "2020-03-31", + "profiles": { + "default": { + "skillMetadata": { + "src": "./skill-package" + } + } + } +} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/TestDataACDLi18n/deBye/document.json b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/TestDataACDLi18n/deBye/document.json new file mode 100644 index 00000000..5a2fc317 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/TestDataACDLi18n/deBye/document.json @@ -0,0 +1,20 @@ +{ + "type": "APLA", + "version": "0.8", + "mainTemplate": { + "parameters": [ + "payload" + ], + "item": { + "type": "Selector", + "strategy": "randomItem", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "Tschüss satheesh" + } + ] + } + } +} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/TestDataACDLi18n/deHelp/document.json b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/TestDataACDLi18n/deHelp/document.json new file mode 100644 index 00000000..bacc0deb --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/TestDataACDLi18n/deHelp/document.json @@ -0,0 +1,21 @@ +{ + "type": "APLA", + "version": "0.8", + "mainTemplate": { + "parameters": [ + "payload" + ], + "item": { + "type": "Selector", + "strategy": "randomItem", + "description": "Change \u0027type\u0027 above to try different Selector Component Types like Sequencer", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "Hilfe leisten satheesh" + } + ] + } + } +} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/TestDataACDLi18n/deOutOfDomain/datasources/default.json b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/TestDataACDLi18n/deOutOfDomain/datasources/default.json new file mode 100644 index 00000000..9e26dfee --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/TestDataACDLi18n/deOutOfDomain/datasources/default.json @@ -0,0 +1 @@ +{} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/TestDataACDLi18n/deOutOfDomain/document.json b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/TestDataACDLi18n/deOutOfDomain/document.json new file mode 100644 index 00000000..6bd6148f --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/TestDataACDLi18n/deOutOfDomain/document.json @@ -0,0 +1,20 @@ +{ + "type": "APLA", + "version": "0.8", + "mainTemplate": { + "parameters": [ + "payload" + ], + "item": { + "type": "Selector", + "strategy": "randomItem", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "Entschuldigung, ich verstehe Satheesh nicht" + } + ] + } + } +} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/TestDataACDLi18n/deRequireMore/document.json b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/TestDataACDLi18n/deRequireMore/document.json new file mode 100644 index 00000000..248b8172 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/TestDataACDLi18n/deRequireMore/document.json @@ -0,0 +1,21 @@ +{ + "type": "APLA", + "version": "0.8", + "mainTemplate": { + "parameters": [ + "payload" + ], + "item": { + "type": "Selector", + "strategy": "randomItem", + "items": [ + { + "description": "This template is emitted after we deny an API. Since we only have one, this is functionally equivalent to needing to request the city again.", + "type": "Speech", + "contentType": "text", + "content": "mehr benötigen satheesh" + } + ] + } + } +} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/TestDataACDLi18n/deWelcome/document.json b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/TestDataACDLi18n/deWelcome/document.json new file mode 100644 index 00000000..6bd7db86 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/TestDataACDLi18n/deWelcome/document.json @@ -0,0 +1,20 @@ +{ + "type": "APLA", + "version": "0.8", + "mainTemplate": { + "parameters": [ + "payload" + ], + "item": { + "type": "Selector", + "strategy": "randomItem", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "Willkommen meinen König Satheesh" + } + ] + } + } +} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/conversations/ALexaPrize.acdl b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/conversations/ALexaPrize.acdl new file mode 100644 index 00000000..086efb02 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/conversations/ALexaPrize.acdl @@ -0,0 +1,203 @@ +namespace com.alexaprize + +import com.amazon.alexa.ask.conversations.Affirm +import com.amazon.alexa.ask.conversations.Deny +import com.amazon.alexa.ask.conversations.Invoke +import com.amazon.alexa.ask.conversations.Notify +import com.amazon.alexa.ask.conversations.Offer +import com.amazon.alexa.ask.conversations.expect +import com.amazon.alexa.ask.conversations.response +import com.amazon.alexa.ask.conversations.utterances +import com.amazon.alexa.schema.Boolean +import com.amazon.alexa.schema.Nothing +import com.amazon.alexa.schema.String +import com.amazon.ask.types.builtins.AMAZON.NUMBER +import prompts.alexa_prize_preconditions_apla +import slotTypes.TopicType + +type ConversationDetails { + optional TopicType Topic +} + +letsChatEvent = utterances( + samples = [ + "let's chat", + "i want to chat", + "chat", + "talk", + "let's chat about {Topic}", + "i want to talk about {Topic}", + "can we talk about {Topic}" + ] +) + +affirmEvent = utterances( + samples = [ + "yes", + "yup", + "yeah", + "sure", + "alright" + ] +) + +denyEvent = utterances( + samples = [ + "no", + "nope", + "not really", + "not", + "naah" + ] +) + +type AlexaPrizePreconditions { + NUMBER isLocaleSupported + NUMBER isDeviceSupported + NUMBER isFalseWake + NUMBER isSocialBotAvailable + NUMBER isAlexaPrizeEnabled + NUMBER isTopicBanned + String handoffPromptOverride +} + +type AlexaPrizePreconditionsPayload { + AlexaPrizePreconditions result +} + +type HandoffResults { + String handoffPromptOverride +} + +type HandoffResultsPayload { + HandoffResults result +} + +action AlexaPrizePreconditions checkPreconditionsAndHandoff(TopicType Topic = nothing) + +action HandoffResults intentConfirmedHandoff() + +action HandoffResults intentDeniedHandoff() + +dialog Nothing AlexaPrizeDialog() { + sample { + preconditionsResult = checkPrecondition() + isHandoffPossible = (((preconditionsResult.isDeviceSupported == 1 && preconditionsResult.isLocaleSupported == 1) && preconditionsResult.isSocialBotAvailable == 1) && preconditionsResult.isAlexaPrizeEnabled == 1) + if (isHandoffPossible) { + isConfirmationNeeded = (preconditionsResult.isFalseWake == 1 || preconditionsResult.isTopicBanned == 1) + responses( + isConfirmationNeeded = isConfirmationNeeded, + preconditionsResult = preconditionsResult + ) + } else { + response( + response = alexa_prize_preconditions_apla, + act = Notify { + actionName = checkPreconditionsAndHandoff, + success = false + }, + payload = AlexaPrizePreconditionsPayload { + result = preconditionsResult + } + ) + } + } +} + +dialog AlexaPrizePreconditions checkPrecondition() { + sample { + chatRequest = expect( + act = Invoke, + event = letsChatEvent + ) + checkPreconditionsAndHandoff( + Topic = chatRequest.Topic + ) + } + sample { + expect( + act = Invoke, + event = letsChatEvent + ) + preconditionsResult = checkPreconditionsAndHandoff() + } +} + +dialog Nothing responses(Boolean isConfirmationNeeded, AlexaPrizePreconditions preconditionsResult) { + sample { + if (isConfirmationNeeded) { + handoffResult( + preconditionsResult = preconditionsResult + ) + } else { + response( + response = alexa_prize_preconditions_apla, + act = Notify { + actionName = checkPreconditionsAndHandoff + }, + payload = AlexaPrizePreconditionsPayload { + result = preconditionsResult + } + ) + } + } +} + +dialog Nothing handoffResult(AlexaPrizePreconditions preconditionsResult) { + sample { + response( + response = alexa_prize_preconditions_apla, + act = Notify { + actionName = checkPreconditionsAndHandoff + }, + nextAct = Offer { + actionName = intentConfirmedHandoff + }, + payload = AlexaPrizePreconditionsPayload { + result = preconditionsResult + } + ) + expect( + act = Affirm, + event = affirmEvent + ) + handoffResults = intentConfirmedHandoff() + response( + response = alexa_prize_preconditions_apla, + act = Notify { + actionName = intentConfirmedHandoff + }, + payload = HandoffResultsPayload { + result = handoffResults + } + ) + } + sample { + response( + response = alexa_prize_preconditions_apla, + act = Notify { + actionName = checkPreconditionsAndHandoff + }, + nextAct = Offer { + actionName = intentDeniedHandoff + }, + payload = AlexaPrizePreconditionsPayload { + result = preconditionsResult + } + ) + expect( + act = Deny, + event = denyEvent + ) + handoffResults = intentDeniedHandoff() + response( + response = alexa_prize_preconditions_apla, + act = Notify { + actionName = intentDeniedHandoff + }, + payload = HandoffResultsPayload { + result = handoffResults + } + ) + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/conversations/Dialog_NonDeployable.acdl b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/conversations/Dialog_NonDeployable.acdl new file mode 100644 index 00000000..90637c08 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/conversations/Dialog_NonDeployable.acdl @@ -0,0 +1,79 @@ +namespace dialogs_non_deployable + +import com.weatherbot.apis.* +import com.amazon.alexa.ask.conversations.Inform +import com.amazon.alexa.ask.conversations.Request +import com.amazon.alexa.ask.conversations.expect +import com.amazon.alexa.ask.conversations.response +import com.amazon.ask.types.builtins.AMAZON.DATE +import com.amazon.ask.types.builtins.AMAZON.NUMBER +import prompts.request_dob_getDate_apla +import prompts.request_getEmploeeID_apla +import prompts.request_name_apla +import slotTypes.complexNames +import types.complexResult +import com.weatherbot.utteracesets.* + +dialog complexNames getName() { + sample { + response( + response = request_name_apla, + act = Request { + arguments = [ + getEmployeeDetails.arguments.name1 + ] + } + ) + complexNamesReturn = expect( + act = Inform, + event = informComplexNameEvent + ) + complexNamesReturn.name + } +} + +dialog NUMBER getEmploeeID() { + sample { + response( + response = request_getEmploeeID_apla, + act = Request { + arguments = [ + getEmployeeDetails.arguments.emplyee1id + ] + } + ) + empID = expect( + act = Inform, + event = informEmployeeIDEvent + ) + empID.emplyee1id + } +} + +dialog DATE getDate() { + sample { + response( + response = request_dob_getDate_apla, + act = Request { + arguments = [ + getEmployeeDetails.arguments.a_dateOfBirth + ] + } + ) + dobEvent = expect( + act = Inform, + event = informDOBEvent + ) + dobEvent.a_dateOfBirth + } +} + +dialog complexResult a_getEmployeeDetails(complexNames name1, NUMBER emplyee1id, DATE a_dateOfBirth) { + sample { + complexResultEvent = getEmployeeDetails( + name1 = name1, + emplyee1id = emplyee1id, + a_dateOfBirth = a_dateOfBirth + ) + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/conversations/Dialogs_reusableDialogsUsage_NonDeployableDialogs.acdl b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/conversations/Dialogs_reusableDialogsUsage_NonDeployableDialogs.acdl new file mode 100644 index 00000000..c1ffb111 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/conversations/Dialogs_reusableDialogsUsage_NonDeployableDialogs.acdl @@ -0,0 +1,50 @@ +namespace reusableDialogs.NonDeployableDialogs + +import com.weatherbot.apis.* +import com.amazon.alexa.ask.conversations.Invoke +import com.amazon.alexa.ask.conversations.Notify +import com.amazon.alexa.ask.conversations.expect +import com.amazon.alexa.ask.conversations.response +import com.amazon.alexa.schema.Nothing +import dialogs_non_deployable.a_getEmployeeDetails +import dialogs_non_deployable.getDate +import dialogs_non_deployable.getEmploeeID +import dialogs_non_deployable.getName +import prompts.getEmployeePosition_success_apla +import types.complexResult +import com.weatherbot.utteracesets.* +import slotTypes.* +import prompts.* +import displays.* +import com.amazon.ask.types.builtins.AMAZON.* +import com.amazon.alexa.schema.* +import com.amazon.alexa.ask.conversations.* +type PayLoadresult { + complexResult result +} + +dialog Nothing dilaog_getEmployeePosition() { + sample { + expect( + act = Invoke, + event = who_are_you + ) + complexNamesEvent = getName() + NUMBEREvent = getEmploeeID() + DATEEvent = getDate() + resultOne = a_getEmployeeDetails( + name1 = complexNamesEvent, + emplyee1id = NUMBEREvent, + a_dateOfBirth = DATEEvent + ) + response( + response = getEmployeePosition_success_apla, + act = Notify { + actionName = getEmployeeDetails + }, + payload = PayLoadresult { + result = resultOne + } + ) + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/conversations/MoreDialogs.acdl b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/conversations/MoreDialogs.acdl new file mode 100644 index 00000000..1661ff46 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/conversations/MoreDialogs.acdl @@ -0,0 +1,174 @@ +namespace testSatheesh +import prompts.* +import displays.* +import com.amazon.alexa.ask.conversations.* +import com.amazon.alexa.schema.* +import com.weatherbot.apis.* +import slotTypes.* +import com.weatherbot.utteracesets.* + +type PAYLOAD_TYPE5 { + resultthree result + } + + +type PAYLOAD_TYPE3 { + customColor colorName + } + + type PAYLOAD_TYPE4 { + customColor colorName + } + + type payloadgetFruitPriceEvent { + result result + } + +@locale(Locale.en_US, Locale.en_GB) +affirmMultipleColorEvent_enUSenGB = utterances( + samples = [ + "do it" + ] +) + +@locale(Locale.de_DE) +affirmMultipleColorEvent_deDE = utterances( + samples = [ + "tu es" + ] +) +affirmMultipleColorEvent = variations(affirmMultipleColorEvent_enUSenGB, affirmMultipleColorEvent_deDE) + + +@locale(Locale.de_DE) +whoAmiExpectInvoke_german = utterances( + samples = [ + "Wer bin ich", + "sag mir wer ich bin", + "sag wer das ist" + ] +) + +@locale(Locale.en_US, Locale.en_GB) +whoAmiExpectInvoke_englisg = utterances( + samples = [ + "who am i", + "tell me who i am", + "tell who is this" + ] + ) + + whoAmiExpectInvoke = variations(whoAmiExpectInvoke_englisg,whoAmiExpectInvoke_german ) + + type thyisIsenGB { + enGBUSCommon enGBUSName + } + + type informColorMultipleEventRequestType { + customColor colorName + } + @locale(Locale.en_US, Locale.en_GB) + informWhopAi_enGBenUS = utterances( + samples = [ + "this is {enGBUSName}", + "{enGBUSName} is this" + ] + ) + + @locale(Locale.de_DE) + informWhopAi_german = utterances( + samples = [ + "das ist {enGBUSName}", + "{enGBUSName} ist das" + ] +) + + +@locale(Locale.en_US, Locale.en_GB) +MultipleDialogEvent_enUSenGB = utterances( + samples = [ + "i want to buy a fruit" + ] +) + +@locale(Locale.en_US, Locale.en_GB) +informColorMultipleEvent_enUSenGB = utterances( + samples = [ + "color {colorName}", + "color is {colorName}", + "{colorName}" + ] +) + + + +@locale(Locale.de_DE) +informColorMultipleEvent_deDE = utterances( + samples = [ + "farbe {colorName}", + "farbe ist {colorName}", + "{colorName}" + ] +) + + +informColorMultipleEvent = variations(informColorMultipleEvent_enUSenGB, informColorMultipleEvent_deDE) + + +@locale(Locale.de_DE) +MultipleDialogEvent_deDE= utterances( + samples = [ + "ich möchte eine frucht kaufen" + ] +) + +MultipleDialogEvent = variations(MultipleDialogEvent_enUSenGB, MultipleDialogEvent_deDE) + + + informWhopAi = variations(informWhopAi_enGBenUS, informWhopAi_german) + + + + +@locale(Locale.en_US, Locale.de_DE, Locale.en_GB) +dialog Nothing WhoAmi { + sample { + expect(act = Invoke,event = whoAmiExpectInvoke) + response(act = Request { arguments = [ whoAmi.arguments.enGBUSName ]},response = MultiModalResponse { apla = request_name_apla}) + informWhopAiRequest = expect(act = Inform,event = informWhopAi) + resultthree0 = whoAmi(enGBUSName = informWhopAiRequest.enGBUSName) + response(act = Notify { success = true, actionName = whoAmi},response = MultiModalResponse { apla = whoAmiSuccess}) + } +} + + +dialog Nothing dialogName_MultipleDialogEvent() { + sample { + expect(act = Invoke,event = MultipleDialogEvent) + response(act = Request { arguments = [ colorFruitName.arguments.colorName ]},response = MultiModalResponse { apla = request_colorName_multiple_apla}) + informColorMultipleEventRequest = expect(act = Inform,event = informColorMultipleEvent) + response(act = ConfirmArgs { arguments = [ colorFruitName.arguments.colorName ]},payload = PAYLOAD_TYPE3 { colorName = informColorMultipleEventRequest.colorName},response = MultiModalResponse { apla = confirm_color_for_fruit_apla}) + expect(act = Affirm,event = affirmMultipleColorEvent) + response(act = ConfirmAction { actionName = colorFruitName},payload = PAYLOAD_TYPE4 { colorName = informColorMultipleEventRequest.colorName},response = MultiModalResponse { apla = response0Prompt16}) + expect(act = Affirm,event = affirmMultipleColorEvent) + result0 = fruitNameAPI(color = informColorMultipleEventRequest.colorName) + ensure(requestArgs = [ RequestArguments { response = MultiModalResponse { apla = request_colorName_multiple_apla }, arguments = [ fruitNameAPI.arguments.color ] }]) + resultthree0 = colorFruitName(colorName = informColorMultipleEventRequest.colorName) + response(act = Notify { success = true, actionName = colorFruitName},payload = PAYLOAD_TYPE5 { result = resultthree0},response = MultiModalResponse { apla = success_fruitPriceAPI_apla, apl = dummyLastScreen}) + } + + sample { + // "content": "what is the price of the fruit" + expect(act = Invoke,event = getFruitPriceEvent) + response(response = requestArgs_request_fruitName_apla,act = Request { arguments = [ fruitNameAPI.arguments.fruitName ]}) + // "content": "fruit name is apple" + fruitNameEvent = expect(act = Inform,event = informfruitNameEvent) + //response(response = confirm_fruitName_apla, act = ConfirmArgs { arguments = [fruitNameAPI.arguments.fruitName]},payload = paylaodCompleFruit { fruitName = fruitNameEvent.fruitName}) + + // expect(act = Affirm,event = affirmFruitAPIEvent) + resultOne = fruitNameAPI(fruitName = fruitNameEvent.fruitName) + // resposne1() + response(response = success_fruitPriceAPI_apla,act = Notify { actionName = fruitNameAPI},payload = payloadgetFruitPriceEvent { result = resultOne}) + + } + } \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/conversations/Weather.acdl b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/conversations/Weather.acdl new file mode 100644 index 00000000..ce7abb8c --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/conversations/Weather.acdl @@ -0,0 +1,154 @@ +namespace com.weatherbot + +import com.amazon.alexa.ask.conversations.Invoke +import com.amazon.alexa.ask.conversations.Notify +import com.amazon.alexa.ask.conversations.RequestArguments +import com.amazon.alexa.ask.conversations.ensure +import com.amazon.alexa.ask.conversations.expect +import com.amazon.alexa.ask.conversations.response +import com.amazon.alexa.ask.conversations.utterances +import com.amazon.alexa.schema.Nothing +import com.amazon.alexa.schema.Thing +import com.amazon.ask.types.builtins.AMAZON.DATE +import com.amazon.ask.types.builtins.AMAZON.NUMBER +import com.amazon.ask.types.builtins.AMAZON.US_CITY +import prompts.request_city_apla +import prompts.request_date_apla + +import slotTypes.* +import prompts.* +import displays.* +import com.amazon.ask.types.builtins.AMAZON.* +import com.amazon.alexa.schema.* +import com.amazon.alexa.ask.conversations.* + +type CityAndDate { + optional myCustomCities cityNameChanged + optional US_CITY cityName + optional DATE date +} + + +@locale(Locale.en_US, Locale.en_GB) +getWeatherEvent_enUS = utterances( + samples = [ + "What's the weather {date} in {cityNameChanged}", + "What's the weather {date} in {cityName}", + "What is the weather {date} in {cityName}", + "what is the weather {date}", + "how is weather" + ] +) + + +@locale(Locale.de_DE) +getWeatherEvent_deDE = utterances( + samples = [ + "Wie ist das wetter {date} in {cityNameChanged}", + "wie ist das wetter {date} in {cityName}", + "wie ist das wetter {date}", + "wie ist das wetter" + ] +) + +getWeatherEvent = variations(getWeatherEvent_enUS,getWeatherEvent_deDE) + +@locale(Locale.en_US, Locale.en_GB) +weather_apla_en = apla("../../skill-package/response/prompts/weather_apla") + +@locale(Locale.de_DE) +weather_apla_de = apla("../../skill-package/response/prompts/weather_apla_de_apla") + +weather_apla_apla_apla = variations(weather_apla_en,weather_apla_de) + + +type cityNameshell{ + US_CITY cityName +} + +@locale(Locale.en_US, Locale.en_GB) +weather_apl_visual_en = apl("../../skill-package/response/display/confirm_weather_apla_display") + +@locale(Locale.de_DE) +weather_apl_visual_de = apl ("../../skill-package/response/display/display_de_apl") + +weather_apl_visual = variations(weather_apl_visual_en, weather_apl_visual_de) + +weather_apla_var = MultiModalResponse (apla = weather_apla_apla_apla, apl = weather_apl_visual) + +/* +what's the weather today in seattle +what is the weather today in madurai +what's the weather today in chennai +what's the weather today in speaker + +*/ + + + +type WeatherResult { + optional myCustomCities cityNameChanged + optional US_CITY cityName + NUMBER highTemp + NUMBER lowTemp +} + +type ResponsePayload { + WeatherResult weatherResult +} + +action WeatherResult getWeather(DATE date, US_CITY cityName = nothing, myCustomCities cityNameChanged = nothing) + + + +dialog Nothing Weather() { + sample { + weatherRequest = expect(act = Invoke,event = getWeatherEvent) + ensure( +requestArgs = [ + RequestArguments {arguments = [ getWeather.arguments.cityNameChanged],response = request_city_apla}, + RequestArguments {arguments = [ getWeather.arguments.cityName],response = request_city_apla}, + RequestArguments { arguments = [getWeather.arguments.date],response = request_date_apla} + ] + ) + weatherResult = getWeather(date = weatherRequest.date, cityName = weatherRequest.cityName) + response( + response = weather_apla_var, + act = Notify {actionName = getWeather}, + payload = ResponsePayload { weatherResult = weatherResult} + ) + } + + sample { + weatherRequest = expect(act = Invoke,event = getWeatherEvent) + ensure( +requestArgs = [ + RequestArguments {arguments = [ getWeather.arguments.cityNameChanged],response = request_city_apla}, + RequestArguments {arguments = [ getWeather.arguments.cityName],response = request_city_apla}, + RequestArguments { arguments = [getWeather.arguments.date],response = request_date_apla} + ] + ) + weatherResult = getWeather(date = weatherRequest.date, cityNameChanged = weatherRequest.cityNameChanged) + response( + response = weather_apla_var, + act = Notify {actionName = getWeather}, + payload = ResponsePayload { weatherResult = weatherResult} + ) + } +} + +dialog Nothing ComplexTest() { + sample { + Weather() + } +} + + + +type weatherRequestEvent0 { + optional myCustomCities cityNameChanged + optional US_CITY cityName + DATE date +} + + diff --git a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/conversations/apis.acdl b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/conversations/apis.acdl new file mode 100644 index 00000000..9cce7d36 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/conversations/apis.acdl @@ -0,0 +1,36 @@ +namespace com.weatherbot.apis + +import com.amazon.alexa.schema.Nothing +import com.amazon.ask.types.builtins.AMAZON.DATE +import com.amazon.ask.types.builtins.AMAZON.NUMBER +import slotTypes.complexNames +import slotTypes.signs +import slotTypes.* +import types.complexResult +import types.result_one +import com.amazon.ask.types.builtins.AMAZON.* + +action NUMBER whoAmi(enGBUSCommon enGBUSName) + +action NUMBER secondEarthAPI() + +action result_one favColorSign_Name(complexNames name, signs sign = nothing) + +action resultthree colorFruitName(customColor colorName) +action resultthree colorFruitNameA(myColors colorName) + + +action result fruitNameAPI(customColor color = nothing, Food fruitName = nothing) + +type result { + NUMBER price + Food fruitName + } + +action complexResult getEmployeeDetails(complexNames name1, NUMBER emplyee1id, DATE a_dateOfBirth = nothing) + +type resultthree { + Color colorName + Food fruitName + } + \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/conversations/apisNamepaceLambda b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/conversations/apisNamepaceLambda new file mode 100644 index 00000000..5fcdf369 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/conversations/apisNamepaceLambda @@ -0,0 +1,23 @@ +namespace com.weatherbot.apis + +import com.amazon.ask.types.builtins.AMAZON.Color +import com.amazon.ask.types.builtins.AMAZON.Food +import com.amazon.ask.types.builtins.AMAZON.NUMBER +import slotTypes.* + +type result { + Food fruitName + NUMBER price +} + +type payloadgetFruitPriceEvent { + result result +} + +action result fruitNameAPI(Food fruitName) + +action resultthree colorFruitName(myColors colorName) + +type resultthree { + Food fruitName +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/conversations/conversation_empty.acdl b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/conversations/conversation_empty.acdl new file mode 100644 index 00000000..4189bdda --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/conversations/conversation_empty.acdl @@ -0,0 +1,114 @@ +namespace com.numberbot + +import com.amazon.alexa.ask.conversations.APLA +import com.amazon.alexa.ask.conversations.Action +import com.amazon.alexa.ask.conversations.Bye +import com.amazon.alexa.ask.conversations.Invoke +import com.amazon.alexa.ask.conversations.Notify +import com.amazon.alexa.ask.conversations.Offer +import com.amazon.alexa.ask.conversations.RequestArguments +import com.amazon.alexa.ask.conversations.ensure +import com.amazon.alexa.ask.conversations.expect +import com.amazon.alexa.ask.conversations.response +import com.amazon.alexa.ask.conversations.utterances +import com.amazon.alexa.schema.Nothing +import com.amazon.alexa.schema.Number +import com.amazon.alexa.schema.Thing +import com.amazon.ask.types.builtins.AMAZON.NUMBER +import prompts.AlexaConversationsBye +import prompts.numericfeedback_apla +import prompts.rating_apla + +type NumPayload { + Number num +} + +type RatingRequest { + NUMBER rating +} + +InformRatingEvent = utterances( + samples = [ + "my score is {rating}", + "that was a {rating} conversation", + "i rate you a {rating}", + "{rating}" + ] +) + +getStart = utterances( + samples = [ + "give me a number please" + ] +) + +action Nothing saveRating(Number rating) + +action Number getNumber() + +dialog Nothing GetFeedback(APLA feedback_prompt, Number num, Action notifyAction) { + sample { + response( + response = feedback_prompt, + act = Notify { + actionName = notifyAction, + success = true + }, + nextAct = Offer { + actionName = saveRating, + arguments = [ + saveRating.arguments.rating + ] + }, + payload = NumPayload { + num = num + } + ) + myRating = expect( + act = Invoke, + event = InformRatingEvent + ) + ensure( + requestArgs = [ + RequestArguments { + arguments = [ + saveRating.arguments.rating + ], + response = rating_apla + } + ] + ) + saveRating( + rating = myRating.rating + ) + } +} + +dialog Number levelOne() { + sample { + expect( + act = Invoke, + event = getStart + ) + num = getNumber() + } +} + +dialog Nothing MainDialog() { + sample { + num = levelOne() + GetFeedback( + feedback_prompt = numericfeedback_apla, + num = num, + notifyAction = getNumber + ) + response( + response = AlexaConversationsBye, + act = Notify { + actionName = saveRating, + success = true + }, + nextAct = Bye {} + ) + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/conversations/delegateToSkill.acdl b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/conversations/delegateToSkill.acdl new file mode 100644 index 00000000..5a2ae76e --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/conversations/delegateToSkill.acdl @@ -0,0 +1,33 @@ +namespace delegateToSkill + +import com.amazon.alexa.ask.conversations.Invoke +import com.amazon.alexa.ask.conversations.Notify +import com.amazon.alexa.ask.conversations.expect +import com.amazon.alexa.ask.conversations.response +import com.amazon.alexa.schema.Nothing +import com.weatherbot.apis.secondEarthAPI +import com.weatherbot.utteracesets.delegateToSkill +import prompts.secondEarthAPI_apla +import slotTypes.* +import prompts.* +import displays.* +import com.weatherbot.utteracesets.* +import com.amazon.alexa.ask.conversations.* +import com.amazon.alexa.schema.* +import types.* +dialog Nothing testTwo() { + sample { + expect( + act = Invoke, + event = delegateToSkill + ) + secondEarthAPI() + response( + response = secondEarthAPI_apla, + act = Notify { + actionName = secondEarthAPI + }, + nextAct = nothing + ) + } +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/conversations/fruitNameApi.acdl b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/conversations/fruitNameApi.acdl new file mode 100644 index 00000000..4664f2f2 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/conversations/fruitNameApi.acdl @@ -0,0 +1,34 @@ +namespace test + +import com.amazon.alexa.ask.conversations.utterances +import com.amazon.ask.types.builtins.AMAZON.Food + +type fruitNameShell { + Food fruitName +} + +type paylaodCompleFruit { + Food fruitName +} + +getFruitPriceEvent = utterances( + samples = [ + "what is the price of the fruit", + "what is the price of fruit" + ] +) + +informfruitNameEvent = utterances( + samples = [ + "{fruitName}", + "fruit name is {fruitName}", + "fruit is {fruitName}" + ] +) + +affirmFruitAPIEvent = utterances( + samples = [ + "uh huh", + "yup" + ] +) diff --git a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/conversations/separateConfig.acdl b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/conversations/separateConfig.acdl new file mode 100644 index 00000000..514c4309 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/conversations/separateConfig.acdl @@ -0,0 +1,83 @@ +namespace configSkill + +import com.amazon.alexa.ask.conversations.skill +import com.amazon.alexa.ask.conversations.variations + +import com.amazon.alexa.ask.conversations.apla +import com.amazon.alexa.ask.conversations.apl +import com.amazon.alexa.ask.conversations.MultiModalResponse +import com.amazon.alexa.ask.conversations.Locale +import com.amazon.alexa.ask.conversations.locale +import com.amazon.alexa.ask.conversations.SkillLevelResponses +import com.amazon.alexa.ask.conversations.InvocationName + +import com.weatherbot.Weather +import soaACDl.sOA + +@locale(Locale.de_DE) +welcome_de = apla("../../skill-package/TestDataACDLi18n/deWelcome") + +@locale(Locale.en_US, Locale.en_GB, Locale.de_DE) +welcome_en_apl_tap = apl("../../skill-package/response/display/confirm_city_apl_display") + +welcome_apl = variations(welcome_en_apl_tap) + +@locale(Locale.en_US, Locale.en_GB) +welcome_en = apla("../../skill-package/response/prompts/AlexaConversationsWelcome") +combo_apla_welcome = variations( welcome_en , welcome_de) + + +@locale(Locale.en_US, Locale.en_GB) +out_of_domain_en = apla("../../skill-package/response/prompts/AlexaConversationsOutOfDomain") +@locale(Locale.en_US, Locale.en_GB) +bye_en = apla("../../skill-package/response/prompts/AlexaConversationsBye") +@locale(Locale.en_US, Locale.en_GB) +reqmore_en = apla("../../skill-package/response/prompts/AlexaConversationsRequestMore") +@locale(Locale.en_US, Locale.en_GB) +provide_help_en = apla("../../skill-package/response/prompts/AlexaConversationsProvideHelp") + +/* +@locale(Locale.es_US) +welcome_es_US = apla("../../skill-package/response/prompts/AlexaConversationsWelcome") +@locale(Locale.es_US) +out_of_domain_es_US = apla("../../skill-package/response/prompts/AlexaConversationsOutOfDomain") +@locale(Locale.es_US) +bye_es_US = apla("../../skill-package/response/prompts/AlexaConversationsBye") +@locale(Locale.es_US) +reqmore_es_US = apla("../../skill-package/response/prompts/AlexaConversationsRequestMore") +@locale(Locale.es_US) +provide_help_es_US = apla("../../skill-package/response/prompts/AlexaConversationsProvideHelp") +*/ + + +@locale(Locale.de_DE) +out_of_domain_de = apla("../../skill-package/TestDataACDLi18n/deOutOfDomain") +out_of_domainResponse = variations(out_of_domain_en, out_of_domain_de) + +@locale(Locale.de_DE) +bye_de = apla("../../skill-package/TestDataACDLi18n/deBye") +byeResponse = variations(bye_en, bye_de) + +@locale(Locale.de_DE) +reqmore_de = apla("../../skill-package/TestDataACDLi18n/deRequireMore") +reqmoreResponse = variations(reqmore_en, reqmore_de) + +@locale(Locale.de_DE) +provide_help_de = apla("../../skill-package/TestDataACDLi18n/deHelp") +provide_helpResponse = variations(provide_help_en, provide_help_de ) + + +combo = MultiModalResponse {apla = combo_apla_welcome, apl = welcome_apl} + +a = skill( + locales = [Locale.en_US, Locale.en_GB, Locale.de_DE], + skillLevelResponses = SkillLevelResponses + { + welcome = combo + ,out_of_domain = out_of_domainResponse + ,bye = byeResponse + ,reqmore = reqmoreResponse + ,provide_help = provide_helpResponse + } +) + diff --git a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/conversations/soaDialog.acdl b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/conversations/soaDialog.acdl new file mode 100644 index 00000000..1aaa772d --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/conversations/soaDialog.acdl @@ -0,0 +1,132 @@ +namespace soaACDl + +import com.amazon.alexa.ask.conversations.Affirm +import com.amazon.alexa.ask.conversations.ConfirmArgs +import com.amazon.alexa.ask.conversations.ConfirmAction +import com.weatherbot.apis.* +import com.amazon.alexa.ask.conversations.Invoke +import com.amazon.alexa.ask.conversations.Notify +import com.amazon.alexa.ask.conversations.Request +import com.amazon.alexa.ask.conversations.expect +//import com.amazon.alexa.ask.conversations.received +import com.amazon.alexa.ask.conversations.response +import com.amazon.alexa.ask.conversations.utterances +import types.* +import com.amazon.alexa.schema.String + +import com.weatherbot.apis.colorFruitName +import com.weatherbot.apis.fruitNameAPI +import com.weatherbot.apis.result +import prompts.confirm_color_for_fruit_apla +import prompts.request_colorName_multiple_apla +import prompts.success_fruitPriceAPI_apla +import prompts.request_city_apla +import slotTypes.* +import prompts.* +import displays.* +import com.amazon.ask.types.builtins.AMAZON.* +import com.amazon.alexa.schema.* +import com.amazon.alexa.ask.conversations.* + + + +type payloadMultipleDialogEvent { + resultthree result +} + +@locale(Locale.en_US,Locale.en_GB ) +MultipleDialogEvent_enUS = utterances( + samples = [ + "i want to buy a fruit" + ] +) +TRYTHI = MultipleDialogEvent_enUS + +@locale(Locale.de_DE) +MultipleDialogEvent_deDE = utterances( + samples = [ + "ich möchte eine frucht kaufen" + ] +) + +MultipleDialogEvent_temp = variations(TRYTHI) + +MultipleDialogEvent = variations(MultipleDialogEvent_temp, MultipleDialogEvent_deDE) + +@locale(Locale.en_US, Locale.en_GB) +informColorMultipleEvent_enUS = utterances( + samples = [ + "{colorName}", + "color is {colorName}", + "color {colorName}" + ] +) +@locale(Locale.de_DE) +informColorMultipleEvent_deDE = utterances( + samples = [ + "{colorName}", + "farbe ist {colorName}", + "farbe {colorName}" + ] +) + + +informColorMultipleEvent = variations(informColorMultipleEvent_enUS, informColorMultipleEvent_deDE) + +affirmMultipleColorEvent = utterances( + samples = [ + "do it" + ] +) + + +type colorNameShell { + myColors colorName +} + + +type payloadsOAConfirmArgs { + myColors colorName +} + + + + +/* + +informColorMultipleEvent = utterances( + samples = [ + "{colorName}", + "color is {colorName}", + "color {colorName}" + ] +) + +dialog Nothing stagingAreaOne() { + sample { + expect(act = Invoke,event = MultipleDialogEvent) + response(response = request_colorName_multiple_apla,act = Request {arguments = [colorFruitName.arguments.colorName]}) + } +} + + +*/ + +//com.amazon.alexa.ask.conversations.response(response = request_colorName_multiple_apla, act = com.amazon.alexa.ask.conversations.Request {arguments = [colorFruitName.arguments.colorName]}) + +@locale(Locale.de_DE, Locale.en_US, Locale.en_GB) +dialog Nothing sOA() { + //@locale(Locale.en_US) + sample { + expect(act = Invoke,event = MultipleDialogEvent) + response(response = request_colorName_multiple_apla,act = Request {arguments = [colorFruitNameA.arguments.colorName]}) + + colorEvent = expect(act = Inform,event = informColorMultipleEvent) + + resultEvent = colorFruitNameA(colorName = colorEvent.colorName) + response( response = success_colorFruitAPI_apla, act = Notify { actionName = colorFruitNameA}, + payload = payloadMultipleDialogEvent {result = resultEvent} + ) + } + +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/conversations/test b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/conversations/test new file mode 100644 index 00000000..fcf67bdb --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/conversations/test @@ -0,0 +1,4 @@ +namespace testOne +import com.amazon.ask.types.builtins.AMAZON.* + +action asdasss asdas(Color asd, Food test = nothing ) \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/conversations/types.acdl b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/conversations/types.acdl new file mode 100644 index 00000000..439e8934 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/conversations/types.acdl @@ -0,0 +1,43 @@ +namespace types + +import com.amazon.ask.types.builtins.AMAZON.Color +import com.amazon.ask.types.builtins.AMAZON.DATE +import com.amazon.ask.types.builtins.AMAZON.Food +import com.amazon.ask.types.builtins.AMAZON.NUMBER +import slotTypes.complexNames +import slotTypes.position +import slotTypes.signs +import slotTypes.* + +type result_one { + Color colorName + complexNames name + signs sign +} + +type complexResult { + complexNames name1 + DATE a_dateOfBirth + NUMBER emplyee1id + position position +} + +type nameShell { + complexNames name +} + +type dobshell { + DATE a_dateOfBirth +} + +type employeeIDshell { + NUMBER emplyee1id +} + +type fruitNameShell { + Food fruitName +} +/ +type colorEvent0 { + myColors colorName +} diff --git a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/conversations/utteracesets.acdl b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/conversations/utteracesets.acdl new file mode 100644 index 00000000..e994b216 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/conversations/utteracesets.acdl @@ -0,0 +1,82 @@ +namespace com.weatherbot.utteracesets + +import com.amazon.alexa.ask.conversations.utterances +import types.dobshell +import types.employeeIDshell +import types.fruitNameShell +import types.nameShell + +getFruitPriceEvent = utterances( + samples = [ + "what is the price of the fruit", + "what is the price of fruit" + ] +) + +affirmFruitAPIEvent = utterances( + samples = [ + "yeah" + ] +) + +informfruitNameEvent = utterances( + samples = [ + "{fruitName}", + "fruit name is {fruitName}", + "fruit is {fruitName}" + ] +) + +delegateToSkill = utterances( + samples = [ + "get me to paradise", + "take me to paradise" + ] +) + +getFavColorEvent = utterances( + samples = [ + "what is my favourite color", + "tell my favourite color" + ] +) + +affirmFavColorEvent = utterances( + samples = [ + "correct" + ] +) + +who_are_you = utterances( + samples = [ + "who are you", + "who is that", + "find his designation" + ] +) + +informComplexNameEvent = utterances( + samples = [ + "{name}", + "name is {name}", + "i am {name}" + ] +) + +informDOBEvent = utterances( + samples = [ + "date of birth is {a_dateOfBirth}", + "birth date is {a_dateOfBirth}" + ] +) + +informEmployeeIDEvent = utterances( + samples = [ + "employee i.d. is {emplyee1id}", + "employee identification is {emplyee1id}", + "identification is {emplyee1id}", + "employee id is {emplyee1id}", + "i.d. is {emplyee1id}", + "id is {emplyee1id}" + ] +) diff --git a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/interactionModels/custom/de-DE.json b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/interactionModels/custom/de-DE.json new file mode 100644 index 00000000..5f130508 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/interactionModels/custom/de-DE.json @@ -0,0 +1,963 @@ +{ + "interactionModel": { + "languageModel": { + "invocationName": "model feedback test skill six", + "intents": [{ + "name": "AMAZON.CancelIntent", + "samples": [] + }, + { + "name": "AMAZON.HelpIntent", + "samples": [] + }, + { + "name": "AMAZON.StopIntent", + "samples": [] + }, + { + "name": "GetWeatherIntent", + "samples": [ + "what is the weather", + "how is the weather", + "tell me the weather" + ] + }, + { + "name": "AMAZON.NavigateHomeIntent", + "samples": [] + }, + { + "name": "AMAZON.FallbackIntent", + "samples": [] + } + ], + "types": [{ + "values": [{ + "id": "movies", + "name": { + "value": "movies", + "synonyms": [] + } + }, + { + "id": "politics", + "name": { + "value": "politics", + "synonyms": [] + } + }, + { + "id": "sports", + "name": { + "value": "sports", + "synonyms": [] + } + }, + { + "id": "hobbies", + "name": { + "value": "hobbies", + "synonyms": [] + } + }, + { + "id": "astronomy", + "name": { + "value": "astronomy", + "synonyms": [] + } + }, + { + "id": "physics", + "name": { + "value": "physics", + "synonyms": [] + } + }, + { + "id": "los_angeles_dodgers", + "name": { + "value": "los angeles dodgers" + } + }, + { + "id": "president_emmanuel_macron", + "name": { + "value": "president emmanuel macron" + } + }, + { + "id": "emmanuel_macron", + "name": { + "value": "emmanuel macron" + } + }, + { + "id": "tax_cuts", + "name": { + "value": "tax cuts" + } + }, + { + "id": "middle_class", + "name": { + "value": "middle class" + } + }, + { + "id": "inequality_divide", + "name": { + "value": "inequality divide" + } + }, + { + "id": "wealth_inequality", + "name": { + "value": "wealth inequality" + } + }, + { + "id": "n._p._r.", + "name": { + "value": "n. p. r." + } + }, + { + "id": "president_trump", + "name": { + "value": "president trump" + } + }, + { + "id": "fox", + "name": { + "value": "fox" + } + }, + { + "id": "police_officers", + "name": { + "value": "police officers" + } + }, + { + "id": "jerome_hall", + "name": { + "value": "jerome hall" + } + }, + { + "id": "diversity_training_program", + "name": { + "value": "diversity training program" + } + }, + { + "id": "read_preble", + "name": { + "value": "read preble" + } + }, + { + "id": "christopher_preble", + "name": { + "value": "christopher preble" + } + }, + { + "id": "pacific_rim", + "name": { + "value": "pacific rim" + } + }, + { + "id": "washington_nationals", + "name": { + "value": "washington nationals" + } + }, + { + "id": "michael_cohen", + "name": { + "value": "michael cohen" + } + }, + { + "id": "john_wall", + "name": { + "value": "john wall" + } + }, + { + "id": "united_states", + "name": { + "value": "united states" + } + }, + { + "id": "washington_wizards", + "name": { + "value": "washington wizards" + } + }, + { + "id": "bryce_harper", + "name": { + "value": "bryce harper" + } + }, + { + "id": "capitals_playoff_hockey_capitals", + "name": { + "value": "capitals playoff hockey capitals" + } + }, + { + "id": "james_b._comey", + "name": { + "value": "james b. comey" + } + }, + { + "id": "mike_pompeo", + "name": { + "value": "mike pompeo" + } + }, + { + "id": "tom_toles", + "name": { + "value": "tom toles" + } + }, + { + "id": "white_house", + "name": { + "value": "white house" + } + }, + { + "id": "manny_machado", + "name": { + "value": "manny machado" + } + }, + { + "id": "national_league_east", + "name": { + "value": "national league east" + } + }, + { + "id": "otto_porter_jr._now", + "name": { + "value": "otto porter jr. now" + } + }, + { + "id": "hillary_clinton", + "name": { + "value": "hillary clinton" + } + }, + { + "id": "trea_turner", + "name": { + "value": "trea turner" + } + }, + { + "id": "max_scherzer", + "name": { + "value": "max scherzer" + } + }, + { + "id": "donald_trump", + "name": { + "value": "donald trump" + } + }, + { + "id": "bryce_harper_nationals", + "name": { + "value": "bryce harper nationals" + } + }, + { + "id": "michael_a._taylor", + "name": { + "value": "michael a. taylor" + } + }, + { + "id": "news_media", + "name": { + "value": "news media" + } + }, + { + "id": "conservative_political_action_conference", + "name": { + "value": "conservative political action conference" + } + }, + { + "id": "mainstream_media", + "name": { + "value": "mainstream media" + } + }, + { + "id": "baltimore_orioles", + "name": { + "value": "baltimore orioles" + } + }, + { + "id": "sean_hannity", + "name": { + "value": "sean hannity" + } + }, + { + "id": "privilege", + "name": { + "value": "privilege" + } + }, + { + "id": "sarah_hart", + "name": { + "value": "sarah hart" + } + }, + { + "id": "matt_kemp", + "name": { + "value": "matt kemp" + } + }, + { + "id": "stephen_strasburg", + "name": { + "value": "stephen strasburg" + } + }, + { + "id": "police_misconduct", + "name": { + "value": "police misconduct" + } + }, + { + "id": "sarah_huckabee_sanders", + "name": { + "value": "sarah huckabee sanders" + } + }, + { + "id": "washington_wizards_april", + "name": { + "value": "washington wizards april" + } + }, + { + "id": "environmental_protection_agency_administrator_scott_pruitt", + "name": { + "value": "environmental protection agency administrator scott pruitt" + } + }, + { + "id": "dodger_stadium", + "name": { + "value": "dodger stadium" + } + }, + { + "id": "environmental_protection_agency", + "name": { + "value": "environmental protection agency" + } + }, + { + "id": "barbara_bush", + "name": { + "value": "barbara bush" + } + }, + { + "id": "lewis_\"scooter\"_libby", + "name": { + "value": "lewis \"scooter\" libby" + } + }, + { + "id": "lewis_scooter_libby", + "name": { + "value": "lewis scooter libby" + } + }, + { + "id": "game_3._lowry", + "name": { + "value": "game 3. lowry" + } + }, + { + "id": "columbus_blue_jackets", + "name": { + "value": "columbus blue jackets" + } + }, + { + "id": "john_tortorella", + "name": { + "value": "john tortorella" + } + }, + { + "id": "george_w._bush", + "name": { + "value": "george w. bush" + } + }, + { + "id": "george_h.w._bush", + "name": { + "value": "george h.w. bush" + } + }, + { + "id": "jarrett_hurd", + "name": { + "value": "jarrett hurd" + } + }, + { + "id": "said_fred_hurd_sr.", + "name": { + "value": "said fred hurd sr." + } + }, + { + "id": "fred_hurd_sr.", + "name": { + "value": "fred hurd sr." + } + }, + { + "id": "san_antonio", + "name": { + "value": "san antonio" + } + }, + { + "id": "san_antonio_spurs", + "name": { + "value": "san antonio spurs" + } + }, + { + "id": "gregg_popovich", + "name": { + "value": "gregg popovich" + } + }, + { + "id": "kawhi_leonard", + "name": { + "value": "kawhi leonard" + } + }, + { + "id": "tim_bontemps_seth_jones", + "name": { + "value": "tim bontemps seth jones" + } + }, + { + "id": "consumer_sentiment_index", + "name": { + "value": "consumer sentiment index" + } + }, + { + "id": "pew_research_center", + "name": { + "value": "pew research center" + } + }, + { + "id": "conference_board_consumer_confidence_survey", + "name": { + "value": "conference board consumer confidence survey" + } + }, + { + "id": "speech_rights", + "name": { + "value": "speech rights" + } + }, + { + "id": "first_amendment", + "name": { + "value": "first amendment" + } + }, + { + "id": "golden_state", + "name": { + "value": "golden state" + } + }, + { + "id": "north_korea", + "name": { + "value": "north korea" + } + }, + { + "id": "woman_pilot", + "name": { + "value": "woman pilot" + } + }, + { + "id": "airline_pilot_population", + "name": { + "value": "airline pilot population" + } + }, + { + "id": "air_transport_pilot", + "name": { + "value": "air transport pilot" + } + }, + { + "id": "southwest_airlines", + "name": { + "value": "southwest airlines" + } + }, + { + "id": "democratic_national_committee", + "name": { + "value": "democratic national committee" + } + }, + { + "id": "senate_foreign_relations_committee", + "name": { + "value": "senate foreign relations committee" + } + }, + { + "id": "cia_director_mike_pompeo", + "name": { + "value": "cia director mike pompeo" + } + }, + { + "id": "playoff_overtime_games", + "name": { + "value": "playoff overtime games" + } + }, + { + "id": "lord_jesus", + "name": { + "value": "lord jesus" + } + }, + { + "id": "lgbtq_community", + "name": { + "value": "lgbtq community" + } + }, + { + "id": "health_and_human_services_department", + "name": { + "value": "health and human services department" + } + }, + { + "id": "group_prayer", + "name": { + "value": "group prayer" + } + }, + { + "id": "princess_charlotte_elizabeth_diana", + "name": { + "value": "princess charlotte elizabeth diana" + } + }, + { + "id": "term_war_economy", + "name": { + "value": "term war economy" + } + }, + { + "id": "melissa_kirk", + "name": { + "value": "melissa kirk" + } + }, + { + "id": "captain_america", + "name": { + "value": "captain america" + } + }, + { + "id": "draft_position", + "name": { + "value": "draft position" + } + }, + { + "id": "elysee_mbem-bosse", + "name": { + "value": "elysee mbem-bosse" + } + }, + { + "id": "water_crisis", + "name": { + "value": "water crisis" + } + }, + { + "id": "nationals_pitchers", + "name": { + "value": "nationals pitchers" + } + }, + { + "id": "sen._jennifer_t._wexton", + "name": { + "value": "sen. jennifer t. wexton" + } + }, + { + "id": "interest_rates", + "name": { + "value": "interest rates" + } + }, + { + "id": "town_crier", + "name": { + "value": "town crier" + } + }, + { + "id": "nancy_goes_millennial", + "name": { + "value": "nancy goes millennial" + } + }, + { + "id": "steve_rogers", + "name": { + "value": "steve rogers" + } + }, + { + "id": "game_3._lebron_james", + "name": { + "value": "game 3. lebron james" + } + }, + { + "id": "anthony_rendon", + "name": { + "value": "anthony rendon" + } + }, + { + "id": "buckingham_palace", + "name": { + "value": "buckingham palace" + } + }, + { + "id": "travis_reinking_suspected", + "name": { + "value": "travis reinking suspected" + } + }, + { + "id": "detroit_free_press", + "name": { + "value": "detroit free press" + } + }, + { + "id": "national_rifle_association", + "name": { + "value": "national rifle association" + } + }, + { + "id": "ed_harris", + "name": { + "value": "ed harris" + } + }, + { + "id": "overtime_playoff_games", + "name": { + "value": "overtime playoff games" + } + }, + { + "id": "republican_sen._bob_corker", + "name": { + "value": "republican sen. bob corker" + } + }, + { + "id": "electricity_sector_reforms", + "name": { + "value": "electricity sector reforms" + } + }, + { + "id": "baltimore_manager_buck_showalter", + "name": { + "value": "baltimore manager buck showalter" + } + }, + { + "id": "sen._joe_manchin_iii", + "name": { + "value": "sen. joe manchin iii" + } + }, + { + "id": "car_seat_belts", + "name": { + "value": "car seat belts" + } + }, + { + "id": "andrews_mcmeel.", + "name": { + "value": "andrews mcmeel." + } + }, + { + "id": "north_africa_program", + "name": { + "value": "north africa program" + } + }, + { + "id": "state_prosecutor_lobby", + "name": { + "value": "state prosecutor lobby" + } + }, + { + "id": "cape_town", + "name": { + "value": "cape town" + } + }, + { + "id": "data_privacy_law", + "name": { + "value": "data privacy law" + } + }, + { + "id": "president_trump_down", + "name": { + "value": "president trump down" + } + }, + { + "id": "christian_kirk", + "name": { + "value": "christian kirk" + } + }, + { + "id": "mitch_mcconnell", + "name": { + "value": "mitch mcconnell" + } + }, + { + "id": "federal_reserve", + "name": { + "value": "federal reserve" + } + } + ], + "name": "TopicType" + }, + { + "values": [{ + "name": { + "value": "cancer" + } + }, + { + "name": { + "value": "scorpio" + } + }, + { + "name": { + "value": "scorpion" + } + } + ], + "name": "signs" + }, + { + "values": [{ + "name": { + "value": "satheesh" + } + }, + { + "name": { + "value": "raman" + } + }, + { + "name": { + "value": "yadhu" + } + } + ], + "name": "complexNames" + }, + { + "values": [{ + "name": { + "value": "tester" + } + }, + { + "name": { + "value": "engineer" + } + }, + { + "name": { + "value": "manager" + } + } + ], + "name": "position" + }, + { + "values": [{ + "name": { + "value": "blue" + } + }, + { + "name": { + "value": "red" + } + }, + { + "name": { + "value": "rocket" + } + } + ], + "name": "myColors" + }, + { + "values": [{ + "name": { + "value": "flower city" + } + }, + { + "name": { + "value": "temple city" + } + }, + { + "name": { + "value": "ramapuram" + } + }, + { + "name": { + "value": "guindy" + } + }, + { + "name": { + "value": "porur" + } + } + ], + "name": "myCustomCities" + }, + { + "values": [{ + "name": { + "value": "flower city" + } + }, + { + "name": { + "value": "temple city" + } + }, + { + "name": { + "value": "ramapuram" + } + }, + { + "name": { + "value": "guindy" + } + }, + { + "name": { + "value": "porur" + } + } + ], + "name": "enGBUSCommon" + }, + { + "values": [{ + "name": { + "value": "blue" + } + }, + { + "name": { + "value": "red" + } + }, + { + "name": { + "value": "rocket" + } + } + ], + "name": "customColor" + } + ] + } + }, + "version": "18" +} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/interactionModels/custom/en-GB.json b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/interactionModels/custom/en-GB.json new file mode 100644 index 00000000..4ac624d8 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/interactionModels/custom/en-GB.json @@ -0,0 +1,963 @@ +{ + "interactionModel": { + "languageModel": { + "invocationName": "model feedback test skill six", + "intents": [{ + "name": "AMAZON.CancelIntent", + "samples": [] + }, + { + "name": "AMAZON.HelpIntent", + "samples": [] + }, + { + "name": "AMAZON.StopIntent", + "samples": [] + }, + { + "name": "GetWeatherIntent", + "samples": [ + "what is the weather", + "how is the weather", + "tell me the weather" + ] + }, + { + "name": "AMAZON.NavigateHomeIntent", + "samples": [] + }, + { + "name": "AMAZON.FallbackIntent", + "samples": [] + } + ], + "types": [{ + "values": [{ + "id": "movies", + "name": { + "value": "movies", + "synonyms": [] + } + }, + { + "id": "politics", + "name": { + "value": "politics", + "synonyms": [] + } + }, + { + "id": "sports", + "name": { + "value": "sports", + "synonyms": [] + } + }, + { + "id": "hobbies", + "name": { + "value": "hobbies", + "synonyms": [] + } + }, + { + "id": "astronomy", + "name": { + "value": "astronomy", + "synonyms": [] + } + }, + { + "id": "physics", + "name": { + "value": "physics", + "synonyms": [] + } + }, + { + "id": "los_angeles_dodgers", + "name": { + "value": "los angeles dodgers" + } + }, + { + "id": "president_emmanuel_macron", + "name": { + "value": "president emmanuel macron" + } + }, + { + "id": "emmanuel_macron", + "name": { + "value": "emmanuel macron" + } + }, + { + "id": "tax_cuts", + "name": { + "value": "tax cuts" + } + }, + { + "id": "middle_class", + "name": { + "value": "middle class" + } + }, + { + "id": "inequality_divide", + "name": { + "value": "inequality divide" + } + }, + { + "id": "wealth_inequality", + "name": { + "value": "wealth inequality" + } + }, + { + "id": "n._p._r.", + "name": { + "value": "n. p. r." + } + }, + { + "id": "president_trump", + "name": { + "value": "president trump" + } + }, + { + "id": "fox", + "name": { + "value": "fox" + } + }, + { + "id": "police_officers", + "name": { + "value": "police officers" + } + }, + { + "id": "jerome_hall", + "name": { + "value": "jerome hall" + } + }, + { + "id": "diversity_training_program", + "name": { + "value": "diversity training program" + } + }, + { + "id": "read_preble", + "name": { + "value": "read preble" + } + }, + { + "id": "christopher_preble", + "name": { + "value": "christopher preble" + } + }, + { + "id": "pacific_rim", + "name": { + "value": "pacific rim" + } + }, + { + "id": "washington_nationals", + "name": { + "value": "washington nationals" + } + }, + { + "id": "michael_cohen", + "name": { + "value": "michael cohen" + } + }, + { + "id": "john_wall", + "name": { + "value": "john wall" + } + }, + { + "id": "united_states", + "name": { + "value": "united states" + } + }, + { + "id": "washington_wizards", + "name": { + "value": "washington wizards" + } + }, + { + "id": "bryce_harper", + "name": { + "value": "bryce harper" + } + }, + { + "id": "capitals_playoff_hockey_capitals", + "name": { + "value": "capitals playoff hockey capitals" + } + }, + { + "id": "james_b._comey", + "name": { + "value": "james b. comey" + } + }, + { + "id": "mike_pompeo", + "name": { + "value": "mike pompeo" + } + }, + { + "id": "tom_toles", + "name": { + "value": "tom toles" + } + }, + { + "id": "white_house", + "name": { + "value": "white house" + } + }, + { + "id": "manny_machado", + "name": { + "value": "manny machado" + } + }, + { + "id": "national_league_east", + "name": { + "value": "national league east" + } + }, + { + "id": "otto_porter_jr._now", + "name": { + "value": "otto porter jr. now" + } + }, + { + "id": "hillary_clinton", + "name": { + "value": "hillary clinton" + } + }, + { + "id": "trea_turner", + "name": { + "value": "trea turner" + } + }, + { + "id": "max_scherzer", + "name": { + "value": "max scherzer" + } + }, + { + "id": "donald_trump", + "name": { + "value": "donald trump" + } + }, + { + "id": "bryce_harper_nationals", + "name": { + "value": "bryce harper nationals" + } + }, + { + "id": "michael_a._taylor", + "name": { + "value": "michael a. taylor" + } + }, + { + "id": "news_media", + "name": { + "value": "news media" + } + }, + { + "id": "conservative_political_action_conference", + "name": { + "value": "conservative political action conference" + } + }, + { + "id": "mainstream_media", + "name": { + "value": "mainstream media" + } + }, + { + "id": "baltimore_orioles", + "name": { + "value": "baltimore orioles" + } + }, + { + "id": "sean_hannity", + "name": { + "value": "sean hannity" + } + }, + { + "id": "privilege", + "name": { + "value": "privilege" + } + }, + { + "id": "sarah_hart", + "name": { + "value": "sarah hart" + } + }, + { + "id": "matt_kemp", + "name": { + "value": "matt kemp" + } + }, + { + "id": "stephen_strasburg", + "name": { + "value": "stephen strasburg" + } + }, + { + "id": "police_misconduct", + "name": { + "value": "police misconduct" + } + }, + { + "id": "sarah_huckabee_sanders", + "name": { + "value": "sarah huckabee sanders" + } + }, + { + "id": "washington_wizards_april", + "name": { + "value": "washington wizards april" + } + }, + { + "id": "environmental_protection_agency_administrator_scott_pruitt", + "name": { + "value": "environmental protection agency administrator scott pruitt" + } + }, + { + "id": "dodger_stadium", + "name": { + "value": "dodger stadium" + } + }, + { + "id": "environmental_protection_agency", + "name": { + "value": "environmental protection agency" + } + }, + { + "id": "barbara_bush", + "name": { + "value": "barbara bush" + } + }, + { + "id": "lewis_\"scooter\"_libby", + "name": { + "value": "lewis \"scooter\" libby" + } + }, + { + "id": "lewis_scooter_libby", + "name": { + "value": "lewis scooter libby" + } + }, + { + "id": "game_3._lowry", + "name": { + "value": "game 3. lowry" + } + }, + { + "id": "columbus_blue_jackets", + "name": { + "value": "columbus blue jackets" + } + }, + { + "id": "john_tortorella", + "name": { + "value": "john tortorella" + } + }, + { + "id": "george_w._bush", + "name": { + "value": "george w. bush" + } + }, + { + "id": "george_h.w._bush", + "name": { + "value": "george h.w. bush" + } + }, + { + "id": "jarrett_hurd", + "name": { + "value": "jarrett hurd" + } + }, + { + "id": "said_fred_hurd_sr.", + "name": { + "value": "said fred hurd sr." + } + }, + { + "id": "fred_hurd_sr.", + "name": { + "value": "fred hurd sr." + } + }, + { + "id": "san_antonio", + "name": { + "value": "san antonio" + } + }, + { + "id": "san_antonio_spurs", + "name": { + "value": "san antonio spurs" + } + }, + { + "id": "gregg_popovich", + "name": { + "value": "gregg popovich" + } + }, + { + "id": "kawhi_leonard", + "name": { + "value": "kawhi leonard" + } + }, + { + "id": "tim_bontemps_seth_jones", + "name": { + "value": "tim bontemps seth jones" + } + }, + { + "id": "consumer_sentiment_index", + "name": { + "value": "consumer sentiment index" + } + }, + { + "id": "pew_research_center", + "name": { + "value": "pew research center" + } + }, + { + "id": "conference_board_consumer_confidence_survey", + "name": { + "value": "conference board consumer confidence survey" + } + }, + { + "id": "speech_rights", + "name": { + "value": "speech rights" + } + }, + { + "id": "first_amendment", + "name": { + "value": "first amendment" + } + }, + { + "id": "golden_state", + "name": { + "value": "golden state" + } + }, + { + "id": "north_korea", + "name": { + "value": "north korea" + } + }, + { + "id": "woman_pilot", + "name": { + "value": "woman pilot" + } + }, + { + "id": "airline_pilot_population", + "name": { + "value": "airline pilot population" + } + }, + { + "id": "air_transport_pilot", + "name": { + "value": "air transport pilot" + } + }, + { + "id": "southwest_airlines", + "name": { + "value": "southwest airlines" + } + }, + { + "id": "democratic_national_committee", + "name": { + "value": "democratic national committee" + } + }, + { + "id": "senate_foreign_relations_committee", + "name": { + "value": "senate foreign relations committee" + } + }, + { + "id": "cia_director_mike_pompeo", + "name": { + "value": "cia director mike pompeo" + } + }, + { + "id": "playoff_overtime_games", + "name": { + "value": "playoff overtime games" + } + }, + { + "id": "lord_jesus", + "name": { + "value": "lord jesus" + } + }, + { + "id": "lgbtq_community", + "name": { + "value": "lgbtq community" + } + }, + { + "id": "health_and_human_services_department", + "name": { + "value": "health and human services department" + } + }, + { + "id": "group_prayer", + "name": { + "value": "group prayer" + } + }, + { + "id": "princess_charlotte_elizabeth_diana", + "name": { + "value": "princess charlotte elizabeth diana" + } + }, + { + "id": "term_war_economy", + "name": { + "value": "term war economy" + } + }, + { + "id": "melissa_kirk", + "name": { + "value": "melissa kirk" + } + }, + { + "id": "captain_america", + "name": { + "value": "captain america" + } + }, + { + "id": "draft_position", + "name": { + "value": "draft position" + } + }, + { + "id": "elysee_mbem-bosse", + "name": { + "value": "elysee mbem-bosse" + } + }, + { + "id": "water_crisis", + "name": { + "value": "water crisis" + } + }, + { + "id": "nationals_pitchers", + "name": { + "value": "nationals pitchers" + } + }, + { + "id": "sen._jennifer_t._wexton", + "name": { + "value": "sen. jennifer t. wexton" + } + }, + { + "id": "interest_rates", + "name": { + "value": "interest rates" + } + }, + { + "id": "town_crier", + "name": { + "value": "town crier" + } + }, + { + "id": "nancy_goes_millennial", + "name": { + "value": "nancy goes millennial" + } + }, + { + "id": "steve_rogers", + "name": { + "value": "steve rogers" + } + }, + { + "id": "game_3._lebron_james", + "name": { + "value": "game 3. lebron james" + } + }, + { + "id": "anthony_rendon", + "name": { + "value": "anthony rendon" + } + }, + { + "id": "buckingham_palace", + "name": { + "value": "buckingham palace" + } + }, + { + "id": "travis_reinking_suspected", + "name": { + "value": "travis reinking suspected" + } + }, + { + "id": "detroit_free_press", + "name": { + "value": "detroit free press" + } + }, + { + "id": "national_rifle_association", + "name": { + "value": "national rifle association" + } + }, + { + "id": "ed_harris", + "name": { + "value": "ed harris" + } + }, + { + "id": "overtime_playoff_games", + "name": { + "value": "overtime playoff games" + } + }, + { + "id": "republican_sen._bob_corker", + "name": { + "value": "republican sen. bob corker" + } + }, + { + "id": "electricity_sector_reforms", + "name": { + "value": "electricity sector reforms" + } + }, + { + "id": "baltimore_manager_buck_showalter", + "name": { + "value": "baltimore manager buck showalter" + } + }, + { + "id": "sen._joe_manchin_iii", + "name": { + "value": "sen. joe manchin iii" + } + }, + { + "id": "car_seat_belts", + "name": { + "value": "car seat belts" + } + }, + { + "id": "andrews_mcmeel.", + "name": { + "value": "andrews mcmeel." + } + }, + { + "id": "north_africa_program", + "name": { + "value": "north africa program" + } + }, + { + "id": "state_prosecutor_lobby", + "name": { + "value": "state prosecutor lobby" + } + }, + { + "id": "cape_town", + "name": { + "value": "cape town" + } + }, + { + "id": "data_privacy_law", + "name": { + "value": "data privacy law" + } + }, + { + "id": "president_trump_down", + "name": { + "value": "president trump down" + } + }, + { + "id": "christian_kirk", + "name": { + "value": "christian kirk" + } + }, + { + "id": "mitch_mcconnell", + "name": { + "value": "mitch mcconnell" + } + }, + { + "id": "federal_reserve", + "name": { + "value": "federal reserve" + } + } + ], + "name": "TopicType" + }, + { + "values": [{ + "name": { + "value": "cancer" + } + }, + { + "name": { + "value": "scorpio" + } + }, + { + "name": { + "value": "scorpion" + } + } + ], + "name": "signs" + }, + { + "values": [{ + "name": { + "value": "satheesh" + } + }, + { + "name": { + "value": "raman" + } + }, + { + "name": { + "value": "yadhu" + } + } + ], + "name": "complexNames" + }, + { + "values": [{ + "name": { + "value": "tester" + } + }, + { + "name": { + "value": "engineer" + } + }, + { + "name": { + "value": "manager" + } + } + ], + "name": "position" + }, + { + "values": [{ + "name": { + "value": "blue" + } + }, + { + "name": { + "value": "red" + } + }, + { + "name": { + "value": "rocket" + } + } + ], + "name": "myColors" + }, + { + "values": [{ + "name": { + "value": "blue" + } + }, + { + "name": { + "value": "red" + } + }, + { + "name": { + "value": "rocket" + } + } + ], + "name": "customColor" + }, + { + "values": [{ + "name": { + "value": "flower city" + } + }, + { + "name": { + "value": "temple city" + } + }, + { + "name": { + "value": "ramapuram" + } + }, + { + "name": { + "value": "guindy" + } + }, + { + "name": { + "value": "porur" + } + } + ], + "name": "myCustomCities" + }, + { + "values": [{ + "name": { + "value": "flower city" + } + }, + { + "name": { + "value": "temple city" + } + }, + { + "name": { + "value": "ramapuram" + } + }, + { + "name": { + "value": "guindy" + } + }, + { + "name": { + "value": "porur" + } + } + ], + "name": "enGBUSCommon" + } + ] + } + }, + "version": "18" +} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/interactionModels/custom/en-US.json b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/interactionModels/custom/en-US.json new file mode 100644 index 00000000..22e3efd3 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/interactionModels/custom/en-US.json @@ -0,0 +1,976 @@ +{ + "interactionModel": { + "languageModel": { + "invocationName": "model feedback test skill six", + "intents": [{ + "name": "AMAZON.CancelIntent", + "samples": [] + }, + { + "name": "AMAZON.HelpIntent", + "samples": [] + }, + { + "name": "AMAZON.StopIntent", + "samples": [] + }, + { + "name": "GetWeatherIntent", + "samples": [ + "what is the weather", + "how is the weather", + "tell me the weather" + ] + }, + { + "name": "SkillToColtrane", + "samples": [ + "switch to coltrane", + "hit coltrane", + "make coltrane DM" + ] + }, + { + "name": "NoDialog", + "samples": [ + "show me the wonders" + ] + }, { + "name": "AMAZON.NavigateHomeIntent", + "samples": [] + }, + { + "name": "AMAZON.FallbackIntent", + "samples": [] + } + ], + "types": [{ + "values": [{ + "id": "movies", + "name": { + "value": "movies", + "synonyms": [] + } + }, + { + "id": "politics", + "name": { + "value": "politics", + "synonyms": [] + } + }, + { + "id": "sports", + "name": { + "value": "sports", + "synonyms": [] + } + }, + { + "id": "hobbies", + "name": { + "value": "hobbies", + "synonyms": [] + } + }, + { + "id": "astronomy", + "name": { + "value": "astronomy", + "synonyms": [] + } + }, + { + "id": "physics", + "name": { + "value": "physics", + "synonyms": [] + } + }, + { + "id": "los_angeles_dodgers", + "name": { + "value": "los angeles dodgers" + } + }, + { + "id": "president_emmanuel_macron", + "name": { + "value": "president emmanuel macron" + } + }, + { + "id": "emmanuel_macron", + "name": { + "value": "emmanuel macron" + } + }, + { + "id": "tax_cuts", + "name": { + "value": "tax cuts" + } + }, + { + "id": "middle_class", + "name": { + "value": "middle class" + } + }, + { + "id": "inequality_divide", + "name": { + "value": "inequality divide" + } + }, + { + "id": "wealth_inequality", + "name": { + "value": "wealth inequality" + } + }, + { + "id": "n._p._r.", + "name": { + "value": "n. p. r." + } + }, + { + "id": "president_trump", + "name": { + "value": "president trump" + } + }, + { + "id": "fox", + "name": { + "value": "fox" + } + }, + { + "id": "police_officers", + "name": { + "value": "police officers" + } + }, + { + "id": "jerome_hall", + "name": { + "value": "jerome hall" + } + }, + { + "id": "diversity_training_program", + "name": { + "value": "diversity training program" + } + }, + { + "id": "read_preble", + "name": { + "value": "read preble" + } + }, + { + "id": "christopher_preble", + "name": { + "value": "christopher preble" + } + }, + { + "id": "pacific_rim", + "name": { + "value": "pacific rim" + } + }, + { + "id": "washington_nationals", + "name": { + "value": "washington nationals" + } + }, + { + "id": "michael_cohen", + "name": { + "value": "michael cohen" + } + }, + { + "id": "john_wall", + "name": { + "value": "john wall" + } + }, + { + "id": "united_states", + "name": { + "value": "united states" + } + }, + { + "id": "washington_wizards", + "name": { + "value": "washington wizards" + } + }, + { + "id": "bryce_harper", + "name": { + "value": "bryce harper" + } + }, + { + "id": "capitals_playoff_hockey_capitals", + "name": { + "value": "capitals playoff hockey capitals" + } + }, + { + "id": "james_b._comey", + "name": { + "value": "james b. comey" + } + }, + { + "id": "mike_pompeo", + "name": { + "value": "mike pompeo" + } + }, + { + "id": "tom_toles", + "name": { + "value": "tom toles" + } + }, + { + "id": "white_house", + "name": { + "value": "white house" + } + }, + { + "id": "manny_machado", + "name": { + "value": "manny machado" + } + }, + { + "id": "national_league_east", + "name": { + "value": "national league east" + } + }, + { + "id": "otto_porter_jr._now", + "name": { + "value": "otto porter jr. now" + } + }, + { + "id": "hillary_clinton", + "name": { + "value": "hillary clinton" + } + }, + { + "id": "trea_turner", + "name": { + "value": "trea turner" + } + }, + { + "id": "max_scherzer", + "name": { + "value": "max scherzer" + } + }, + { + "id": "donald_trump", + "name": { + "value": "donald trump" + } + }, + { + "id": "bryce_harper_nationals", + "name": { + "value": "bryce harper nationals" + } + }, + { + "id": "michael_a._taylor", + "name": { + "value": "michael a. taylor" + } + }, + { + "id": "news_media", + "name": { + "value": "news media" + } + }, + { + "id": "conservative_political_action_conference", + "name": { + "value": "conservative political action conference" + } + }, + { + "id": "mainstream_media", + "name": { + "value": "mainstream media" + } + }, + { + "id": "baltimore_orioles", + "name": { + "value": "baltimore orioles" + } + }, + { + "id": "sean_hannity", + "name": { + "value": "sean hannity" + } + }, + { + "id": "privilege", + "name": { + "value": "privilege" + } + }, + { + "id": "sarah_hart", + "name": { + "value": "sarah hart" + } + }, + { + "id": "matt_kemp", + "name": { + "value": "matt kemp" + } + }, + { + "id": "stephen_strasburg", + "name": { + "value": "stephen strasburg" + } + }, + { + "id": "police_misconduct", + "name": { + "value": "police misconduct" + } + }, + { + "id": "sarah_huckabee_sanders", + "name": { + "value": "sarah huckabee sanders" + } + }, + { + "id": "washington_wizards_april", + "name": { + "value": "washington wizards april" + } + }, + { + "id": "environmental_protection_agency_administrator_scott_pruitt", + "name": { + "value": "environmental protection agency administrator scott pruitt" + } + }, + { + "id": "dodger_stadium", + "name": { + "value": "dodger stadium" + } + }, + { + "id": "environmental_protection_agency", + "name": { + "value": "environmental protection agency" + } + }, + { + "id": "barbara_bush", + "name": { + "value": "barbara bush" + } + }, + { + "id": "lewis_\"scooter\"_libby", + "name": { + "value": "lewis \"scooter\" libby" + } + }, + { + "id": "lewis_scooter_libby", + "name": { + "value": "lewis scooter libby" + } + }, + { + "id": "game_3._lowry", + "name": { + "value": "game 3. lowry" + } + }, + { + "id": "columbus_blue_jackets", + "name": { + "value": "columbus blue jackets" + } + }, + { + "id": "john_tortorella", + "name": { + "value": "john tortorella" + } + }, + { + "id": "george_w._bush", + "name": { + "value": "george w. bush" + } + }, + { + "id": "george_h.w._bush", + "name": { + "value": "george h.w. bush" + } + }, + { + "id": "jarrett_hurd", + "name": { + "value": "jarrett hurd" + } + }, + { + "id": "said_fred_hurd_sr.", + "name": { + "value": "said fred hurd sr." + } + }, + { + "id": "fred_hurd_sr.", + "name": { + "value": "fred hurd sr." + } + }, + { + "id": "san_antonio", + "name": { + "value": "san antonio" + } + }, + { + "id": "san_antonio_spurs", + "name": { + "value": "san antonio spurs" + } + }, + { + "id": "gregg_popovich", + "name": { + "value": "gregg popovich" + } + }, + { + "id": "kawhi_leonard", + "name": { + "value": "kawhi leonard" + } + }, + { + "id": "tim_bontemps_seth_jones", + "name": { + "value": "tim bontemps seth jones" + } + }, + { + "id": "consumer_sentiment_index", + "name": { + "value": "consumer sentiment index" + } + }, + { + "id": "pew_research_center", + "name": { + "value": "pew research center" + } + }, + { + "id": "conference_board_consumer_confidence_survey", + "name": { + "value": "conference board consumer confidence survey" + } + }, + { + "id": "speech_rights", + "name": { + "value": "speech rights" + } + }, + { + "id": "first_amendment", + "name": { + "value": "first amendment" + } + }, + { + "id": "golden_state", + "name": { + "value": "golden state" + } + }, + { + "id": "north_korea", + "name": { + "value": "north korea" + } + }, + { + "id": "woman_pilot", + "name": { + "value": "woman pilot" + } + }, + { + "id": "airline_pilot_population", + "name": { + "value": "airline pilot population" + } + }, + { + "id": "air_transport_pilot", + "name": { + "value": "air transport pilot" + } + }, + { + "id": "southwest_airlines", + "name": { + "value": "southwest airlines" + } + }, + { + "id": "democratic_national_committee", + "name": { + "value": "democratic national committee" + } + }, + { + "id": "senate_foreign_relations_committee", + "name": { + "value": "senate foreign relations committee" + } + }, + { + "id": "cia_director_mike_pompeo", + "name": { + "value": "cia director mike pompeo" + } + }, + { + "id": "playoff_overtime_games", + "name": { + "value": "playoff overtime games" + } + }, + { + "id": "lord_jesus", + "name": { + "value": "lord jesus" + } + }, + { + "id": "lgbtq_community", + "name": { + "value": "lgbtq community" + } + }, + { + "id": "health_and_human_services_department", + "name": { + "value": "health and human services department" + } + }, + { + "id": "group_prayer", + "name": { + "value": "group prayer" + } + }, + { + "id": "princess_charlotte_elizabeth_diana", + "name": { + "value": "princess charlotte elizabeth diana" + } + }, + { + "id": "term_war_economy", + "name": { + "value": "term war economy" + } + }, + { + "id": "melissa_kirk", + "name": { + "value": "melissa kirk" + } + }, + { + "id": "captain_america", + "name": { + "value": "captain america" + } + }, + { + "id": "draft_position", + "name": { + "value": "draft position" + } + }, + { + "id": "elysee_mbem-bosse", + "name": { + "value": "elysee mbem-bosse" + } + }, + { + "id": "water_crisis", + "name": { + "value": "water crisis" + } + }, + { + "id": "nationals_pitchers", + "name": { + "value": "nationals pitchers" + } + }, + { + "id": "sen._jennifer_t._wexton", + "name": { + "value": "sen. jennifer t. wexton" + } + }, + { + "id": "interest_rates", + "name": { + "value": "interest rates" + } + }, + { + "id": "town_crier", + "name": { + "value": "town crier" + } + }, + { + "id": "nancy_goes_millennial", + "name": { + "value": "nancy goes millennial" + } + }, + { + "id": "steve_rogers", + "name": { + "value": "steve rogers" + } + }, + { + "id": "game_3._lebron_james", + "name": { + "value": "game 3. lebron james" + } + }, + { + "id": "anthony_rendon", + "name": { + "value": "anthony rendon" + } + }, + { + "id": "buckingham_palace", + "name": { + "value": "buckingham palace" + } + }, + { + "id": "travis_reinking_suspected", + "name": { + "value": "travis reinking suspected" + } + }, + { + "id": "detroit_free_press", + "name": { + "value": "detroit free press" + } + }, + { + "id": "national_rifle_association", + "name": { + "value": "national rifle association" + } + }, + { + "id": "ed_harris", + "name": { + "value": "ed harris" + } + }, + { + "id": "overtime_playoff_games", + "name": { + "value": "overtime playoff games" + } + }, + { + "id": "republican_sen._bob_corker", + "name": { + "value": "republican sen. bob corker" + } + }, + { + "id": "electricity_sector_reforms", + "name": { + "value": "electricity sector reforms" + } + }, + { + "id": "baltimore_manager_buck_showalter", + "name": { + "value": "baltimore manager buck showalter" + } + }, + { + "id": "sen._joe_manchin_iii", + "name": { + "value": "sen. joe manchin iii" + } + }, + { + "id": "car_seat_belts", + "name": { + "value": "car seat belts" + } + }, + { + "id": "andrews_mcmeel.", + "name": { + "value": "andrews mcmeel." + } + }, + { + "id": "north_africa_program", + "name": { + "value": "north africa program" + } + }, + { + "id": "state_prosecutor_lobby", + "name": { + "value": "state prosecutor lobby" + } + }, + { + "id": "cape_town", + "name": { + "value": "cape town" + } + }, + { + "id": "data_privacy_law", + "name": { + "value": "data privacy law" + } + }, + { + "id": "president_trump_down", + "name": { + "value": "president trump down" + } + }, + { + "id": "christian_kirk", + "name": { + "value": "christian kirk" + } + }, + { + "id": "mitch_mcconnell", + "name": { + "value": "mitch mcconnell" + } + }, + { + "id": "federal_reserve", + "name": { + "value": "federal reserve" + } + } + ], + "name": "TopicType" + }, + { + "values": [{ + "name": { + "value": "cancer" + } + }, + { + "name": { + "value": "scorpio" + } + }, + { + "name": { + "value": "scorpion" + } + } + ], + "name": "signs" + }, + { + "values": [{ + "name": { + "value": "satheesh" + } + }, + { + "name": { + "value": "raman" + } + }, + { + "name": { + "value": "yadhu" + } + } + ], + "name": "complexNames" + }, + { + "values": [{ + "name": { + "value": "tester" + } + }, + { + "name": { + "value": "engineer" + } + }, + { + "name": { + "value": "manager" + } + } + ], + "name": "position" + }, + { + "values": [{ + "name": { + "value": "blue" + } + }, + { + "name": { + "value": "red" + } + }, + { + "name": { + "value": "rocket" + } + } + ], + "name": "myColors" + }, + { + "values": [{ + "name": { + "value": "blue" + } + }, + { + "name": { + "value": "red" + } + }, + { + "name": { + "value": "rocket" + } + } + ], + "name": "customColor" + }, + { + "values": [{ + "name": { + "value": "flower city" + } + }, + { + "name": { + "value": "temple city" + } + }, + { + "name": { + "value": "ramapuram" + } + }, + { + "name": { + "value": "guindy" + } + }, + { + "name": { + "value": "porur" + } + } + ], + "name": "myCustomCities" + }, + { + "values": [{ + "name": { + "value": "flower city" + } + }, + { + "name": { + "value": "temple city" + } + }, + { + "name": { + "value": "ramapuram" + } + }, + { + "name": { + "value": "guindy" + } + }, + { + "name": { + "value": "porur" + } + } + ], + "name": "enGBUSCommon" + } + ] + } + }, + "version": "18" +} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/display/confirm_city_apl_display/document.json b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/display/confirm_city_apl_display/document.json new file mode 100644 index 00000000..741e1a5f --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/display/confirm_city_apl_display/document.json @@ -0,0 +1,358 @@ +{ + "type": "APL", + "version": "1.1", + "settings": {}, + "theme": "dark", + "import": [ + { + "name": "alexa-layouts", + "version": "1.0.0" + } + ], + "resources": [ + { + "description": "Stock color for the light theme", + "colors": { + "colorTextPrimary": "#151920" + } + }, + { + "description": "Stock color for the dark theme", + "when": "${viewport.theme == 'dark'}", + "colors": { + "colorTextPrimary": "#f0f1ef" + } + }, + { + "description": "Standard font sizes", + "dimensions": { + "textSizeBody": 48, + "textSizePrimary": 27, + "textSizeSecondary": 23, + "textSizeDetails": 20, + "textSizeSecondaryHint": 25 + } + }, + { + "description": "Common spacing values", + "dimensions": { + "spacingThin": 6, + "spacingSmall": 12, + "spacingMedium": 24, + "spacingLarge": 48, + "spacingExtraLarge": 72 + } + }, + { + "description": "Common margins and padding", + "dimensions": { + "marginTop": 40, + "marginLeft": 60, + "marginRight": 60, + "marginBottom": 40 + } + } + ], + "styles": { + "textStyleBase": { + "description": "Base font description; set color", + "values": [ + { + "color": "@colorTextPrimary" + } + ] + }, + "textStyleBase0": { + "description": "Thin version of basic font", + "extend": "textStyleBase", + "values": { + "fontWeight": "100" + } + }, + "textStyleBase1": { + "description": "Light version of basic font", + "extend": "textStyleBase", + "values": { + "fontWeight": "300" + } + }, + "textStyleBase2": { + "description": "Regular version of basic font", + "extend": "textStyleBase", + "values": { + "fontWeight": "500" + } + }, + "mixinBody": { + "values": { + "fontSize": "@textSizeBody" + } + }, + "mixinPrimary": { + "values": { + "fontSize": "@textSizePrimary" + } + }, + "mixinDetails": { + "values": { + "fontSize": "@textSizeDetails" + } + }, + "mixinSecondary": { + "values": { + "fontSize": "@textSizeSecondary" + } + }, + "textStylePrimary": { + "extend": [ + "textStyleBase1", + "mixinPrimary" + ] + }, + "textStyleSecondary": { + "extend": [ + "textStyleBase0", + "mixinSecondary" + ] + }, + "textStyleBody": { + "extend": [ + "textStyleBase1", + "mixinBody" + ] + }, + "textStyleSecondaryHint": { + "values": { + "fontFamily": "Bookerly", + "fontStyle": "italic", + "fontSize": "@textSizeSecondaryHint", + "color": "@colorTextPrimary" + } + }, + "textStyleDetails": { + "extend": [ + "textStyleBase2", + "mixinDetails" + ] + } + }, + "onMount": [], + "graphics": {}, + "commands": {}, + "layouts": { + "ListTemplate1": { + "parameters": [ + "backgroundImage", + "title", + "logo", + "hintText", + "listData" + ], + "item": [ + { + "type": "Container", + "width": "100vw", + "height": "100vh", + "direction": "column", + "items": [ + { + "type": "Image", + "source": "${backgroundImage}", + "scale": "best-fill", + "width": "100vw", + "height": "100vh", + "position": "absolute" + }, + { + "type": "AlexaHeader", + "headerTitle": "${title}", + "headerAttributionImage": "${logo}" + }, + { + "type": "Sequence", + "grow": 1, + "height": "80vh", + "scrollDirection": "vertical", + "paddingLeft": "@marginLeft", + "paddingRight": "@marginRight", + "data": "${listData}", + "numbered": true, + "items": [ + { + "type": "VerticalListItem", + "image": "${data.image.sources[0].url}", + "primaryText": "${data.textContent.primaryText.text}", + "secondaryText": "${data.textContent.secondaryText.text}", + "tertiaryText": "${data.textContent.tertiaryText.text}" + } + ] + } + ] + } + ] + }, + "VerticalListItem": { + "parameters": [ + "primaryText", + "secondaryText", + "tertiaryText", + "image" + ], + "item": [ + { + "when": "${viewport.shape == 'round'}", + "type": "Container", + "direction": "row", + "height": 200, + "width": 500, + "alignItems": "center", + "items": [ + { + "type": "Text", + "text": "${ordinal}", + "paddingBottom": "20dp", + "color": "white", + "spacing": "5dp" + }, + { + "type": "Image", + "when": "${image}", + "source": "${image}", + "height": 150, + "width": 150, + "spacing": 15, + "scale": "best-fit", + "align": "top" + }, + { + "type": "Container", + "direction": "column", + "spacing": 25, + "items": [ + { + "type": "Text", + "text": "${primaryText}", + "style": "textStyleDetail", + "grow": 1, + "shrink": 1, + "fontWeight": "300", + "maxLines": 1 + }, + { + "type": "Text", + "text": "${secondaryText}", + "style": "textStyleCaption", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + }, + { + "type": "Text", + "text": "${tertiaryText}", + "style": "textStyleDetails", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + } + ] + } + ] + }, + { + "type": "Container", + "direction": "row", + "height": 125, + "width": 800, + "alignItems": "center", + "items": [ + { + "type": "Text", + "text": "${ordinal}", + "paddingBottom": "20dp", + "color": "white", + "spacing": "5dp" + }, + { + "type": "Image", + "when": "${image}", + "source": "${image}", + "height": 100, + "width": 100, + "align": "top", + "spacing": 50, + "scale": "best-fit" + }, + { + "type": "Container", + "spacing": 30, + "direction": "column", + "items": [ + { + "type": "Text", + "text": "${primaryText}", + "style": "textStyleBody", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + }, + { + "type": "Text", + "text": "${secondaryText}", + "style": "textStyleDetails", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + } + ] + }, + { + "type": "Text", + "text": "${tertiaryText}", + "style": "textStyleBody", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "textAlign": "right", + "maxLines": 1 + } + ] + } + ] + } + }, + "mainTemplate": { + "parameters": [ + "payload" + ], + "item": [ + { + "type": "Container", + "id": "BookCabSimpleDialogAPL", + "items": [ + { + "type": "TouchWrapper", + "onPress": { + "type": "SendEvent", + "arguments": [ + "delegateToColtraneOld" + ] + }, + "item": { + "type": "Text", + "id": "BookCabSimpleDialogAPL", + "paddingTop": "100", + "paddingLeft": "100", + "color": "green", + "size": 50, + "text": "which city ?" + } + } + ] + } + ] + } +} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/display/confirm_date_apl_display/document.json b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/display/confirm_date_apl_display/document.json new file mode 100644 index 00000000..9ff71e5c --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/display/confirm_date_apl_display/document.json @@ -0,0 +1,358 @@ +{ + "type": "APL", + "version": "1.1", + "settings": {}, + "theme": "dark", + "import": [ + { + "name": "alexa-layouts", + "version": "1.0.0" + } + ], + "resources": [ + { + "description": "Stock color for the light theme", + "colors": { + "colorTextPrimary": "#151920" + } + }, + { + "description": "Stock color for the dark theme", + "when": "${viewport.theme == 'dark'}", + "colors": { + "colorTextPrimary": "#f0f1ef" + } + }, + { + "description": "Standard font sizes", + "dimensions": { + "textSizeBody": 48, + "textSizePrimary": 27, + "textSizeSecondary": 23, + "textSizeDetails": 20, + "textSizeSecondaryHint": 25 + } + }, + { + "description": "Common spacing values", + "dimensions": { + "spacingThin": 6, + "spacingSmall": 12, + "spacingMedium": 24, + "spacingLarge": 48, + "spacingExtraLarge": 72 + } + }, + { + "description": "Common margins and padding", + "dimensions": { + "marginTop": 40, + "marginLeft": 60, + "marginRight": 60, + "marginBottom": 40 + } + } + ], + "styles": { + "textStyleBase": { + "description": "Base font description; set color", + "values": [ + { + "color": "@colorTextPrimary" + } + ] + }, + "textStyleBase0": { + "description": "Thin version of basic font", + "extend": "textStyleBase", + "values": { + "fontWeight": "100" + } + }, + "textStyleBase1": { + "description": "Light version of basic font", + "extend": "textStyleBase", + "values": { + "fontWeight": "300" + } + }, + "textStyleBase2": { + "description": "Regular version of basic font", + "extend": "textStyleBase", + "values": { + "fontWeight": "500" + } + }, + "mixinBody": { + "values": { + "fontSize": "@textSizeBody" + } + }, + "mixinPrimary": { + "values": { + "fontSize": "@textSizePrimary" + } + }, + "mixinDetails": { + "values": { + "fontSize": "@textSizeDetails" + } + }, + "mixinSecondary": { + "values": { + "fontSize": "@textSizeSecondary" + } + }, + "textStylePrimary": { + "extend": [ + "textStyleBase1", + "mixinPrimary" + ] + }, + "textStyleSecondary": { + "extend": [ + "textStyleBase0", + "mixinSecondary" + ] + }, + "textStyleBody": { + "extend": [ + "textStyleBase1", + "mixinBody" + ] + }, + "textStyleSecondaryHint": { + "values": { + "fontFamily": "Bookerly", + "fontStyle": "italic", + "fontSize": "@textSizeSecondaryHint", + "color": "@colorTextPrimary" + } + }, + "textStyleDetails": { + "extend": [ + "textStyleBase2", + "mixinDetails" + ] + } + }, + "onMount": [], + "graphics": {}, + "commands": {}, + "layouts": { + "ListTemplate1": { + "parameters": [ + "backgroundImage", + "title", + "logo", + "hintText", + "listData" + ], + "item": [ + { + "type": "Container", + "width": "100vw", + "height": "100vh", + "direction": "column", + "items": [ + { + "type": "Image", + "source": "${backgroundImage}", + "scale": "best-fill", + "width": "100vw", + "height": "100vh", + "position": "absolute" + }, + { + "type": "AlexaHeader", + "headerTitle": "${title}", + "headerAttributionImage": "${logo}" + }, + { + "type": "Sequence", + "grow": 1, + "height": "80vh", + "scrollDirection": "vertical", + "paddingLeft": "@marginLeft", + "paddingRight": "@marginRight", + "data": "${listData}", + "numbered": true, + "items": [ + { + "type": "VerticalListItem", + "image": "${data.image.sources[0].url}", + "primaryText": "${data.textContent.primaryText.text}", + "secondaryText": "${data.textContent.secondaryText.text}", + "tertiaryText": "${data.textContent.tertiaryText.text}" + } + ] + } + ] + } + ] + }, + "VerticalListItem": { + "parameters": [ + "primaryText", + "secondaryText", + "tertiaryText", + "image" + ], + "item": [ + { + "when": "${viewport.shape == 'round'}", + "type": "Container", + "direction": "row", + "height": 200, + "width": 500, + "alignItems": "center", + "items": [ + { + "type": "Text", + "text": "${ordinal}", + "paddingBottom": "20dp", + "color": "white", + "spacing": "5dp" + }, + { + "type": "Image", + "when": "${image}", + "source": "${image}", + "height": 150, + "width": 150, + "spacing": 15, + "scale": "best-fit", + "align": "top" + }, + { + "type": "Container", + "direction": "column", + "spacing": 25, + "items": [ + { + "type": "Text", + "text": "${primaryText}", + "style": "textStyleDetail", + "grow": 1, + "shrink": 1, + "fontWeight": "300", + "maxLines": 1 + }, + { + "type": "Text", + "text": "${secondaryText}", + "style": "textStyleCaption", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + }, + { + "type": "Text", + "text": "${tertiaryText}", + "style": "textStyleDetails", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + } + ] + } + ] + }, + { + "type": "Container", + "direction": "row", + "height": 125, + "width": 800, + "alignItems": "center", + "items": [ + { + "type": "Text", + "text": "${ordinal}", + "paddingBottom": "20dp", + "color": "white", + "spacing": "5dp" + }, + { + "type": "Image", + "when": "${image}", + "source": "${image}", + "height": 100, + "width": 100, + "align": "top", + "spacing": 50, + "scale": "best-fit" + }, + { + "type": "Container", + "spacing": 30, + "direction": "column", + "items": [ + { + "type": "Text", + "text": "${primaryText}", + "style": "textStyleBody", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + }, + { + "type": "Text", + "text": "${secondaryText}", + "style": "textStyleDetails", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + } + ] + }, + { + "type": "Text", + "text": "${tertiaryText}", + "style": "textStyleBody", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "textAlign": "right", + "maxLines": 1 + } + ] + } + ] + } + }, + "mainTemplate": { + "parameters": [ + "payload" + ], + "item": [ + { + "type": "Container", + "id": "BookCabSimpleDialogAPL", + "items": [ + { + "type": "TouchWrapper", + "onPress": { + "type": "SendEvent", + "arguments": [ + "delegateToColtraneOld" + ] + }, + "item": { + "type": "Text", + "id": "BookCabSimpleDialogAPL", + "paddingTop": "100", + "paddingLeft": "100", + "color": "green", + "size": 50, + "text": "which date ?" + } + } + ] + } + ] + } + } \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/display/confirm_weather_apla_display/document.json b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/display/confirm_weather_apla_display/document.json new file mode 100644 index 00000000..1974945a --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/display/confirm_weather_apla_display/document.json @@ -0,0 +1,412 @@ +{ + "type": "APL", + "version": "1.1", + "settings": {}, + "theme": "dark", + "import": [ + { + "name": "alexa-layouts", + "version": "1.0.0" + } + ], + "resources": [ + { + "description": "Stock color for the light theme", + "colors": { + "colorTextPrimary": "#151920" + } + }, + { + "description": "Stock color for the dark theme", + "when": "${viewport.theme == 'dark'}", + "colors": { + "colorTextPrimary": "#f0f1ef" + } + }, + { + "description": "Standard font sizes", + "dimensions": { + "textSizeBody": 48, + "textSizePrimary": 27, + "textSizeSecondary": 23, + "textSizeDetails": 20, + "textSizeSecondaryHint": 25 + } + }, + { + "description": "Common spacing values", + "dimensions": { + "spacingThin": 6, + "spacingSmall": 12, + "spacingMedium": 24, + "spacingLarge": 48, + "spacingExtraLarge": 72 + } + }, + { + "description": "Common margins and padding", + "dimensions": { + "marginTop": 40, + "marginLeft": 60, + "marginRight": 60, + "marginBottom": 40 + } + } + ], + "styles": { + "textStyleBase": { + "description": "Base font description; set color", + "values": [ + { + "color": "@colorTextPrimary" + } + ] + }, + "textStyleBase0": { + "description": "Thin version of basic font", + "extend": "textStyleBase", + "values": { + "fontWeight": "100" + } + }, + "textStyleBase1": { + "description": "Light version of basic font", + "extend": "textStyleBase", + "values": { + "fontWeight": "300" + } + }, + "textStyleBase2": { + "description": "Regular version of basic font", + "extend": "textStyleBase", + "values": { + "fontWeight": "500" + } + }, + "mixinBody": { + "values": { + "fontSize": "@textSizeBody" + } + }, + "mixinPrimary": { + "values": { + "fontSize": "@textSizePrimary" + } + }, + "mixinDetails": { + "values": { + "fontSize": "@textSizeDetails" + } + }, + "mixinSecondary": { + "values": { + "fontSize": "@textSizeSecondary" + } + }, + "textStylePrimary": { + "extend": [ + "textStyleBase1", + "mixinPrimary" + ] + }, + "textStyleSecondary": { + "extend": [ + "textStyleBase0", + "mixinSecondary" + ] + }, + "textStyleBody": { + "extend": [ + "textStyleBase1", + "mixinBody" + ] + }, + "textStyleSecondaryHint": { + "values": { + "fontFamily": "Bookerly", + "fontStyle": "italic", + "fontSize": "@textSizeSecondaryHint", + "color": "@colorTextPrimary" + } + }, + "textStyleDetails": { + "extend": [ + "textStyleBase2", + "mixinDetails" + ] + } + }, + "onMount": [], + "graphics": {}, + "commands": {}, + "layouts": { + "ListTemplate1": { + "parameters": [ + "backgroundImage", + "title", + "logo", + "hintText", + "listData" + ], + "item": [ + { + "type": "Container", + "width": "100vw", + "height": "100vh", + "direction": "column", + "items": [ + { + "type": "Image", + "source": "${backgroundImage}", + "scale": "best-fill", + "width": "100vw", + "height": "100vh", + "position": "absolute" + }, + { + "type": "AlexaHeader", + "headerTitle": "${title}", + "headerAttributionImage": "${logo}" + }, + { + "type": "Sequence", + "grow": 1, + "height": "80vh", + "scrollDirection": "vertical", + "paddingLeft": "@marginLeft", + "paddingRight": "@marginRight", + "data": "${listData}", + "numbered": true, + "items": [ + { + "type": "VerticalListItem", + "image": "${data.image.sources[0].url}", + "primaryText": "${data.textContent.primaryText.text}", + "secondaryText": "${data.textContent.secondaryText.text}", + "tertiaryText": "${data.textContent.tertiaryText.text}" + } + ] + } + ] + } + ] + }, + "VerticalListItem": { + "parameters": [ + "primaryText", + "secondaryText", + "tertiaryText", + "image" + ], + "item": [ + { + "when": "${viewport.shape == 'round'}", + "type": "Container", + "direction": "row", + "height": 200, + "width": 500, + "alignItems": "center", + "items": [ + { + "type": "Text", + "text": "${ordinal}", + "paddingBottom": "20dp", + "color": "white", + "spacing": "5dp" + }, + { + "type": "Image", + "when": "${image}", + "source": "${image}", + "height": 150, + "width": 150, + "spacing": 15, + "scale": "best-fit", + "align": "top" + }, + { + "type": "Container", + "direction": "column", + "spacing": 25, + "items": [ + { + "type": "Text", + "text": "${primaryText}", + "style": "textStyleDetail", + "grow": 1, + "shrink": 1, + "fontWeight": "300", + "maxLines": 1 + }, + { + "type": "Text", + "text": "${secondaryText}", + "style": "textStyleCaption", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + }, + { + "type": "Text", + "text": "${tertiaryText}", + "style": "textStyleDetails", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + } + ] + } + ] + }, + { + "type": "Container", + "direction": "row", + "height": 125, + "width": 800, + "alignItems": "center", + "items": [ + { + "type": "Text", + "text": "${ordinal}", + "paddingBottom": "20dp", + "color": "white", + "spacing": "5dp" + }, + { + "type": "Image", + "when": "${image}", + "source": "${image}", + "height": 100, + "width": 100, + "align": "top", + "spacing": 50, + "scale": "best-fit" + }, + { + "type": "Container", + "spacing": 30, + "direction": "column", + "items": [ + { + "type": "Text", + "text": "${primaryText}", + "style": "textStyleBody", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + }, + { + "type": "Text", + "text": "${secondaryText}", + "style": "textStyleDetails", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + } + ] + }, + { + "type": "Text", + "text": "${tertiaryText}", + "style": "textStyleBody", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "textAlign": "right", + "maxLines": 1 + } + ] + } + ] + } + }, + "mainTemplate": { + "parameters": [ + "payload" + ], + "item": [ + { + "type": "Container", + "id": "BookCabSimpleDialogAPL", + "items": [ + { + "type": "TouchWrapper", + "onPress": { + "type": "SendEvent", + "arguments": [ + "delegateToSkillNew" + ] + }, + "item": { + "type": "Text", + "id": "BookCabSimpleDialogAPL", + "paddingTop": "100", + "paddingLeft": "100", + "color": "green", + "size": 50, + "text": "delegateToSkillNew" + } + }, + { + "type": "TouchWrapper", + "onPress": { + "type": "SendEvent", + "arguments": [ + "delegateToSkillOld" + ] + }, + "item": { + "type": "Text", + "id": "BookCabSimpleDialogAPL", + "paddingTop": "100", + "paddingLeft": "100", + "color": "green", + "size": 50, + "text": "delegateToSkillOld" + } + }, + { + "type": "TouchWrapper", + "onPress": { + "type": "SendEvent", + "arguments": [ + "delegateToColtraneNew" + ] + }, + "item": { + "type": "Text", + "id": "BookCabSimpleDialogAPL", + "paddingTop": "100", + "paddingLeft": "100", + "color": "green", + "size": 50, + "text": "delegateToColtraneNew" + } + }, + { + "type": "TouchWrapper", + "onPress": { + "type": "SendEvent", + "arguments": [ + "delegateToColtraneOld" + ] + }, + "item": { + "type": "Text", + "id": "BookCabSimpleDialogAPL", + "paddingTop": "100", + "paddingLeft": "100", + "color": "green", + "size": 50, + "text": "delegateToColtraneOld" + } + } + ] + } + ] + } +} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/display/display_de_apl/document.json b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/display/display_de_apl/document.json new file mode 100644 index 00000000..741e1a5f --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/display/display_de_apl/document.json @@ -0,0 +1,358 @@ +{ + "type": "APL", + "version": "1.1", + "settings": {}, + "theme": "dark", + "import": [ + { + "name": "alexa-layouts", + "version": "1.0.0" + } + ], + "resources": [ + { + "description": "Stock color for the light theme", + "colors": { + "colorTextPrimary": "#151920" + } + }, + { + "description": "Stock color for the dark theme", + "when": "${viewport.theme == 'dark'}", + "colors": { + "colorTextPrimary": "#f0f1ef" + } + }, + { + "description": "Standard font sizes", + "dimensions": { + "textSizeBody": 48, + "textSizePrimary": 27, + "textSizeSecondary": 23, + "textSizeDetails": 20, + "textSizeSecondaryHint": 25 + } + }, + { + "description": "Common spacing values", + "dimensions": { + "spacingThin": 6, + "spacingSmall": 12, + "spacingMedium": 24, + "spacingLarge": 48, + "spacingExtraLarge": 72 + } + }, + { + "description": "Common margins and padding", + "dimensions": { + "marginTop": 40, + "marginLeft": 60, + "marginRight": 60, + "marginBottom": 40 + } + } + ], + "styles": { + "textStyleBase": { + "description": "Base font description; set color", + "values": [ + { + "color": "@colorTextPrimary" + } + ] + }, + "textStyleBase0": { + "description": "Thin version of basic font", + "extend": "textStyleBase", + "values": { + "fontWeight": "100" + } + }, + "textStyleBase1": { + "description": "Light version of basic font", + "extend": "textStyleBase", + "values": { + "fontWeight": "300" + } + }, + "textStyleBase2": { + "description": "Regular version of basic font", + "extend": "textStyleBase", + "values": { + "fontWeight": "500" + } + }, + "mixinBody": { + "values": { + "fontSize": "@textSizeBody" + } + }, + "mixinPrimary": { + "values": { + "fontSize": "@textSizePrimary" + } + }, + "mixinDetails": { + "values": { + "fontSize": "@textSizeDetails" + } + }, + "mixinSecondary": { + "values": { + "fontSize": "@textSizeSecondary" + } + }, + "textStylePrimary": { + "extend": [ + "textStyleBase1", + "mixinPrimary" + ] + }, + "textStyleSecondary": { + "extend": [ + "textStyleBase0", + "mixinSecondary" + ] + }, + "textStyleBody": { + "extend": [ + "textStyleBase1", + "mixinBody" + ] + }, + "textStyleSecondaryHint": { + "values": { + "fontFamily": "Bookerly", + "fontStyle": "italic", + "fontSize": "@textSizeSecondaryHint", + "color": "@colorTextPrimary" + } + }, + "textStyleDetails": { + "extend": [ + "textStyleBase2", + "mixinDetails" + ] + } + }, + "onMount": [], + "graphics": {}, + "commands": {}, + "layouts": { + "ListTemplate1": { + "parameters": [ + "backgroundImage", + "title", + "logo", + "hintText", + "listData" + ], + "item": [ + { + "type": "Container", + "width": "100vw", + "height": "100vh", + "direction": "column", + "items": [ + { + "type": "Image", + "source": "${backgroundImage}", + "scale": "best-fill", + "width": "100vw", + "height": "100vh", + "position": "absolute" + }, + { + "type": "AlexaHeader", + "headerTitle": "${title}", + "headerAttributionImage": "${logo}" + }, + { + "type": "Sequence", + "grow": 1, + "height": "80vh", + "scrollDirection": "vertical", + "paddingLeft": "@marginLeft", + "paddingRight": "@marginRight", + "data": "${listData}", + "numbered": true, + "items": [ + { + "type": "VerticalListItem", + "image": "${data.image.sources[0].url}", + "primaryText": "${data.textContent.primaryText.text}", + "secondaryText": "${data.textContent.secondaryText.text}", + "tertiaryText": "${data.textContent.tertiaryText.text}" + } + ] + } + ] + } + ] + }, + "VerticalListItem": { + "parameters": [ + "primaryText", + "secondaryText", + "tertiaryText", + "image" + ], + "item": [ + { + "when": "${viewport.shape == 'round'}", + "type": "Container", + "direction": "row", + "height": 200, + "width": 500, + "alignItems": "center", + "items": [ + { + "type": "Text", + "text": "${ordinal}", + "paddingBottom": "20dp", + "color": "white", + "spacing": "5dp" + }, + { + "type": "Image", + "when": "${image}", + "source": "${image}", + "height": 150, + "width": 150, + "spacing": 15, + "scale": "best-fit", + "align": "top" + }, + { + "type": "Container", + "direction": "column", + "spacing": 25, + "items": [ + { + "type": "Text", + "text": "${primaryText}", + "style": "textStyleDetail", + "grow": 1, + "shrink": 1, + "fontWeight": "300", + "maxLines": 1 + }, + { + "type": "Text", + "text": "${secondaryText}", + "style": "textStyleCaption", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + }, + { + "type": "Text", + "text": "${tertiaryText}", + "style": "textStyleDetails", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + } + ] + } + ] + }, + { + "type": "Container", + "direction": "row", + "height": 125, + "width": 800, + "alignItems": "center", + "items": [ + { + "type": "Text", + "text": "${ordinal}", + "paddingBottom": "20dp", + "color": "white", + "spacing": "5dp" + }, + { + "type": "Image", + "when": "${image}", + "source": "${image}", + "height": 100, + "width": 100, + "align": "top", + "spacing": 50, + "scale": "best-fit" + }, + { + "type": "Container", + "spacing": 30, + "direction": "column", + "items": [ + { + "type": "Text", + "text": "${primaryText}", + "style": "textStyleBody", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + }, + { + "type": "Text", + "text": "${secondaryText}", + "style": "textStyleDetails", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + } + ] + }, + { + "type": "Text", + "text": "${tertiaryText}", + "style": "textStyleBody", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "textAlign": "right", + "maxLines": 1 + } + ] + } + ] + } + }, + "mainTemplate": { + "parameters": [ + "payload" + ], + "item": [ + { + "type": "Container", + "id": "BookCabSimpleDialogAPL", + "items": [ + { + "type": "TouchWrapper", + "onPress": { + "type": "SendEvent", + "arguments": [ + "delegateToColtraneOld" + ] + }, + "item": { + "type": "Text", + "id": "BookCabSimpleDialogAPL", + "paddingTop": "100", + "paddingLeft": "100", + "color": "green", + "size": 50, + "text": "which city ?" + } + } + ] + } + ] + } +} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/display/dummyLastScreen/datasources/default.json b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/display/dummyLastScreen/datasources/default.json new file mode 100644 index 00000000..9e26dfee --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/display/dummyLastScreen/datasources/default.json @@ -0,0 +1 @@ +{} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/display/dummyLastScreen/document.json b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/display/dummyLastScreen/document.json new file mode 100644 index 00000000..d8790b65 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/display/dummyLastScreen/document.json @@ -0,0 +1 @@ +{"type":"APL","version":"1.1","settings":{},"theme":"dark","import":[{"name":"alexa-layouts","version":"1.0.0"}],"resources":[{"description":"Stock color for the light theme","colors":{"colorTextPrimary":"#151920"}},{"description":"Stock color for the dark theme","when":"${viewport.theme == 'dark'}","colors":{"colorTextPrimary":"#f0f1ef"}},{"description":"Standard font sizes","dimensions":{"textSizeBody":48,"textSizePrimary":27,"textSizeSecondary":23,"textSizeDetails":20,"textSizeSecondaryHint":25}},{"description":"Common spacing values","dimensions":{"spacingThin":6,"spacingSmall":12,"spacingMedium":24,"spacingLarge":48,"spacingExtraLarge":72}},{"description":"Common margins and padding","dimensions":{"marginTop":40,"marginLeft":60,"marginRight":60,"marginBottom":40}}],"styles":{"textStyleBase":{"description":"Base font description; set color","values":[{"color":"@colorTextPrimary"}]},"textStyleBase0":{"description":"Thin version of basic font","extend":"textStyleBase","values":{"fontWeight":"100"}},"textStyleBase1":{"description":"Light version of basic font","extend":"textStyleBase","values":{"fontWeight":"300"}},"textStyleBase2":{"description":"Regular version of basic font","extend":"textStyleBase","values":{"fontWeight":"500"}},"mixinBody":{"values":{"fontSize":"@textSizeBody"}},"mixinPrimary":{"values":{"fontSize":"@textSizePrimary"}},"mixinDetails":{"values":{"fontSize":"@textSizeDetails"}},"mixinSecondary":{"values":{"fontSize":"@textSizeSecondary"}},"textStylePrimary":{"extend":["textStyleBase1","mixinPrimary"]},"textStyleSecondary":{"extend":["textStyleBase0","mixinSecondary"]},"textStyleBody":{"extend":["textStyleBase1","mixinBody"]},"textStyleSecondaryHint":{"values":{"fontFamily":"Bookerly","fontStyle":"italic","fontSize":"@textSizeSecondaryHint","color":"@colorTextPrimary"}},"textStyleDetails":{"extend":["textStyleBase2","mixinDetails"]}},"onMount":[],"graphics":{},"commands":{},"layouts":{"ListTemplate1":{"parameters":["backgroundImage","title","logo","hintText","listData"],"item":[{"type":"Container","width":"100vw","height":"100vh","direction":"column","items":[{"type":"Image","source":"${backgroundImage}","scale":"best-fill","width":"100vw","height":"100vh","position":"absolute"},{"type":"AlexaHeader","headerTitle":"${title}","headerAttributionImage":"${logo}"},{"type":"Sequence","grow":1,"height":"80vh","scrollDirection":"vertical","paddingLeft":"@marginLeft","paddingRight":"@marginRight","data":"${listData}","numbered":true,"items":[{"type":"VerticalListItem","image":"${data.image.sources[0].url}","primaryText":"${data.textContent.primaryText.text}","secondaryText":"${data.textContent.secondaryText.text}","tertiaryText":"${data.textContent.tertiaryText.text}"}]}]}]},"VerticalListItem":{"parameters":["primaryText","secondaryText","tertiaryText","image"],"item":[{"when":"${viewport.shape == 'round'}","type":"Container","direction":"row","height":200,"width":500,"alignItems":"center","items":[{"type":"Text","text":"${ordinal}","paddingBottom":"20dp","color":"white","spacing":"5dp"},{"type":"Image","when":"${image}","source":"${image}","height":150,"width":150,"spacing":15,"scale":"best-fit","align":"top"},{"type":"Container","direction":"column","spacing":25,"items":[{"type":"Text","text":"${primaryText}","style":"textStyleDetail","grow":1,"shrink":1,"fontWeight":"300","maxLines":1},{"type":"Text","text":"${secondaryText}","style":"textStyleCaption","fontWeight":"300","grow":1,"shrink":1,"maxLines":1},{"type":"Text","text":"${tertiaryText}","style":"textStyleDetails","fontWeight":"300","grow":1,"shrink":1,"maxLines":1}]}]},{"type":"Container","direction":"row","height":125,"width":800,"alignItems":"center","items":[{"type":"Text","text":"${ordinal}","paddingBottom":"20dp","color":"white","spacing":"5dp"},{"type":"Image","when":"${image}","source":"${image}","height":100,"width":100,"align":"top","spacing":50,"scale":"best-fit"},{"type":"Container","spacing":30,"direction":"column","items":[{"type":"Text","text":"${primaryText}","style":"textStyleBody","fontWeight":"300","grow":1,"shrink":1,"maxLines":1},{"type":"Text","text":"${secondaryText}","style":"textStyleDetails","fontWeight":"300","grow":1,"shrink":1,"maxLines":1}]},{"type":"Text","text":"${tertiaryText}","style":"textStyleBody","fontWeight":"300","grow":1,"shrink":1,"textAlign":"right","maxLines":1}]}]}},"mainTemplate":{"parameters":["payload"],"item":[{"type":"Container","id":"BookCabSimpleDialogAPL","items":[[],{"type":"Text","id":"BookCabSimpleDialogAPL","paddingTop":"100","paddingLeft":"100","color":"green","size":50,"text":"Blah Blah Blaa !!"}]}]}} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/display/dummyLastScreen/sources/default.json b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/display/dummyLastScreen/sources/default.json new file mode 100644 index 00000000..9e26dfee --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/display/dummyLastScreen/sources/default.json @@ -0,0 +1 @@ +{} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/display/request_city_apl_display/document.json b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/display/request_city_apl_display/document.json new file mode 100644 index 00000000..741e1a5f --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/display/request_city_apl_display/document.json @@ -0,0 +1,358 @@ +{ + "type": "APL", + "version": "1.1", + "settings": {}, + "theme": "dark", + "import": [ + { + "name": "alexa-layouts", + "version": "1.0.0" + } + ], + "resources": [ + { + "description": "Stock color for the light theme", + "colors": { + "colorTextPrimary": "#151920" + } + }, + { + "description": "Stock color for the dark theme", + "when": "${viewport.theme == 'dark'}", + "colors": { + "colorTextPrimary": "#f0f1ef" + } + }, + { + "description": "Standard font sizes", + "dimensions": { + "textSizeBody": 48, + "textSizePrimary": 27, + "textSizeSecondary": 23, + "textSizeDetails": 20, + "textSizeSecondaryHint": 25 + } + }, + { + "description": "Common spacing values", + "dimensions": { + "spacingThin": 6, + "spacingSmall": 12, + "spacingMedium": 24, + "spacingLarge": 48, + "spacingExtraLarge": 72 + } + }, + { + "description": "Common margins and padding", + "dimensions": { + "marginTop": 40, + "marginLeft": 60, + "marginRight": 60, + "marginBottom": 40 + } + } + ], + "styles": { + "textStyleBase": { + "description": "Base font description; set color", + "values": [ + { + "color": "@colorTextPrimary" + } + ] + }, + "textStyleBase0": { + "description": "Thin version of basic font", + "extend": "textStyleBase", + "values": { + "fontWeight": "100" + } + }, + "textStyleBase1": { + "description": "Light version of basic font", + "extend": "textStyleBase", + "values": { + "fontWeight": "300" + } + }, + "textStyleBase2": { + "description": "Regular version of basic font", + "extend": "textStyleBase", + "values": { + "fontWeight": "500" + } + }, + "mixinBody": { + "values": { + "fontSize": "@textSizeBody" + } + }, + "mixinPrimary": { + "values": { + "fontSize": "@textSizePrimary" + } + }, + "mixinDetails": { + "values": { + "fontSize": "@textSizeDetails" + } + }, + "mixinSecondary": { + "values": { + "fontSize": "@textSizeSecondary" + } + }, + "textStylePrimary": { + "extend": [ + "textStyleBase1", + "mixinPrimary" + ] + }, + "textStyleSecondary": { + "extend": [ + "textStyleBase0", + "mixinSecondary" + ] + }, + "textStyleBody": { + "extend": [ + "textStyleBase1", + "mixinBody" + ] + }, + "textStyleSecondaryHint": { + "values": { + "fontFamily": "Bookerly", + "fontStyle": "italic", + "fontSize": "@textSizeSecondaryHint", + "color": "@colorTextPrimary" + } + }, + "textStyleDetails": { + "extend": [ + "textStyleBase2", + "mixinDetails" + ] + } + }, + "onMount": [], + "graphics": {}, + "commands": {}, + "layouts": { + "ListTemplate1": { + "parameters": [ + "backgroundImage", + "title", + "logo", + "hintText", + "listData" + ], + "item": [ + { + "type": "Container", + "width": "100vw", + "height": "100vh", + "direction": "column", + "items": [ + { + "type": "Image", + "source": "${backgroundImage}", + "scale": "best-fill", + "width": "100vw", + "height": "100vh", + "position": "absolute" + }, + { + "type": "AlexaHeader", + "headerTitle": "${title}", + "headerAttributionImage": "${logo}" + }, + { + "type": "Sequence", + "grow": 1, + "height": "80vh", + "scrollDirection": "vertical", + "paddingLeft": "@marginLeft", + "paddingRight": "@marginRight", + "data": "${listData}", + "numbered": true, + "items": [ + { + "type": "VerticalListItem", + "image": "${data.image.sources[0].url}", + "primaryText": "${data.textContent.primaryText.text}", + "secondaryText": "${data.textContent.secondaryText.text}", + "tertiaryText": "${data.textContent.tertiaryText.text}" + } + ] + } + ] + } + ] + }, + "VerticalListItem": { + "parameters": [ + "primaryText", + "secondaryText", + "tertiaryText", + "image" + ], + "item": [ + { + "when": "${viewport.shape == 'round'}", + "type": "Container", + "direction": "row", + "height": 200, + "width": 500, + "alignItems": "center", + "items": [ + { + "type": "Text", + "text": "${ordinal}", + "paddingBottom": "20dp", + "color": "white", + "spacing": "5dp" + }, + { + "type": "Image", + "when": "${image}", + "source": "${image}", + "height": 150, + "width": 150, + "spacing": 15, + "scale": "best-fit", + "align": "top" + }, + { + "type": "Container", + "direction": "column", + "spacing": 25, + "items": [ + { + "type": "Text", + "text": "${primaryText}", + "style": "textStyleDetail", + "grow": 1, + "shrink": 1, + "fontWeight": "300", + "maxLines": 1 + }, + { + "type": "Text", + "text": "${secondaryText}", + "style": "textStyleCaption", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + }, + { + "type": "Text", + "text": "${tertiaryText}", + "style": "textStyleDetails", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + } + ] + } + ] + }, + { + "type": "Container", + "direction": "row", + "height": 125, + "width": 800, + "alignItems": "center", + "items": [ + { + "type": "Text", + "text": "${ordinal}", + "paddingBottom": "20dp", + "color": "white", + "spacing": "5dp" + }, + { + "type": "Image", + "when": "${image}", + "source": "${image}", + "height": 100, + "width": 100, + "align": "top", + "spacing": 50, + "scale": "best-fit" + }, + { + "type": "Container", + "spacing": 30, + "direction": "column", + "items": [ + { + "type": "Text", + "text": "${primaryText}", + "style": "textStyleBody", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + }, + { + "type": "Text", + "text": "${secondaryText}", + "style": "textStyleDetails", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + } + ] + }, + { + "type": "Text", + "text": "${tertiaryText}", + "style": "textStyleBody", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "textAlign": "right", + "maxLines": 1 + } + ] + } + ] + } + }, + "mainTemplate": { + "parameters": [ + "payload" + ], + "item": [ + { + "type": "Container", + "id": "BookCabSimpleDialogAPL", + "items": [ + { + "type": "TouchWrapper", + "onPress": { + "type": "SendEvent", + "arguments": [ + "delegateToColtraneOld" + ] + }, + "item": { + "type": "Text", + "id": "BookCabSimpleDialogAPL", + "paddingTop": "100", + "paddingLeft": "100", + "color": "green", + "size": 50, + "text": "which city ?" + } + } + ] + } + ] + } +} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/display/request_date_apl_display/document.json b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/display/request_date_apl_display/document.json new file mode 100644 index 00000000..9ff71e5c --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/display/request_date_apl_display/document.json @@ -0,0 +1,358 @@ +{ + "type": "APL", + "version": "1.1", + "settings": {}, + "theme": "dark", + "import": [ + { + "name": "alexa-layouts", + "version": "1.0.0" + } + ], + "resources": [ + { + "description": "Stock color for the light theme", + "colors": { + "colorTextPrimary": "#151920" + } + }, + { + "description": "Stock color for the dark theme", + "when": "${viewport.theme == 'dark'}", + "colors": { + "colorTextPrimary": "#f0f1ef" + } + }, + { + "description": "Standard font sizes", + "dimensions": { + "textSizeBody": 48, + "textSizePrimary": 27, + "textSizeSecondary": 23, + "textSizeDetails": 20, + "textSizeSecondaryHint": 25 + } + }, + { + "description": "Common spacing values", + "dimensions": { + "spacingThin": 6, + "spacingSmall": 12, + "spacingMedium": 24, + "spacingLarge": 48, + "spacingExtraLarge": 72 + } + }, + { + "description": "Common margins and padding", + "dimensions": { + "marginTop": 40, + "marginLeft": 60, + "marginRight": 60, + "marginBottom": 40 + } + } + ], + "styles": { + "textStyleBase": { + "description": "Base font description; set color", + "values": [ + { + "color": "@colorTextPrimary" + } + ] + }, + "textStyleBase0": { + "description": "Thin version of basic font", + "extend": "textStyleBase", + "values": { + "fontWeight": "100" + } + }, + "textStyleBase1": { + "description": "Light version of basic font", + "extend": "textStyleBase", + "values": { + "fontWeight": "300" + } + }, + "textStyleBase2": { + "description": "Regular version of basic font", + "extend": "textStyleBase", + "values": { + "fontWeight": "500" + } + }, + "mixinBody": { + "values": { + "fontSize": "@textSizeBody" + } + }, + "mixinPrimary": { + "values": { + "fontSize": "@textSizePrimary" + } + }, + "mixinDetails": { + "values": { + "fontSize": "@textSizeDetails" + } + }, + "mixinSecondary": { + "values": { + "fontSize": "@textSizeSecondary" + } + }, + "textStylePrimary": { + "extend": [ + "textStyleBase1", + "mixinPrimary" + ] + }, + "textStyleSecondary": { + "extend": [ + "textStyleBase0", + "mixinSecondary" + ] + }, + "textStyleBody": { + "extend": [ + "textStyleBase1", + "mixinBody" + ] + }, + "textStyleSecondaryHint": { + "values": { + "fontFamily": "Bookerly", + "fontStyle": "italic", + "fontSize": "@textSizeSecondaryHint", + "color": "@colorTextPrimary" + } + }, + "textStyleDetails": { + "extend": [ + "textStyleBase2", + "mixinDetails" + ] + } + }, + "onMount": [], + "graphics": {}, + "commands": {}, + "layouts": { + "ListTemplate1": { + "parameters": [ + "backgroundImage", + "title", + "logo", + "hintText", + "listData" + ], + "item": [ + { + "type": "Container", + "width": "100vw", + "height": "100vh", + "direction": "column", + "items": [ + { + "type": "Image", + "source": "${backgroundImage}", + "scale": "best-fill", + "width": "100vw", + "height": "100vh", + "position": "absolute" + }, + { + "type": "AlexaHeader", + "headerTitle": "${title}", + "headerAttributionImage": "${logo}" + }, + { + "type": "Sequence", + "grow": 1, + "height": "80vh", + "scrollDirection": "vertical", + "paddingLeft": "@marginLeft", + "paddingRight": "@marginRight", + "data": "${listData}", + "numbered": true, + "items": [ + { + "type": "VerticalListItem", + "image": "${data.image.sources[0].url}", + "primaryText": "${data.textContent.primaryText.text}", + "secondaryText": "${data.textContent.secondaryText.text}", + "tertiaryText": "${data.textContent.tertiaryText.text}" + } + ] + } + ] + } + ] + }, + "VerticalListItem": { + "parameters": [ + "primaryText", + "secondaryText", + "tertiaryText", + "image" + ], + "item": [ + { + "when": "${viewport.shape == 'round'}", + "type": "Container", + "direction": "row", + "height": 200, + "width": 500, + "alignItems": "center", + "items": [ + { + "type": "Text", + "text": "${ordinal}", + "paddingBottom": "20dp", + "color": "white", + "spacing": "5dp" + }, + { + "type": "Image", + "when": "${image}", + "source": "${image}", + "height": 150, + "width": 150, + "spacing": 15, + "scale": "best-fit", + "align": "top" + }, + { + "type": "Container", + "direction": "column", + "spacing": 25, + "items": [ + { + "type": "Text", + "text": "${primaryText}", + "style": "textStyleDetail", + "grow": 1, + "shrink": 1, + "fontWeight": "300", + "maxLines": 1 + }, + { + "type": "Text", + "text": "${secondaryText}", + "style": "textStyleCaption", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + }, + { + "type": "Text", + "text": "${tertiaryText}", + "style": "textStyleDetails", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + } + ] + } + ] + }, + { + "type": "Container", + "direction": "row", + "height": 125, + "width": 800, + "alignItems": "center", + "items": [ + { + "type": "Text", + "text": "${ordinal}", + "paddingBottom": "20dp", + "color": "white", + "spacing": "5dp" + }, + { + "type": "Image", + "when": "${image}", + "source": "${image}", + "height": 100, + "width": 100, + "align": "top", + "spacing": 50, + "scale": "best-fit" + }, + { + "type": "Container", + "spacing": 30, + "direction": "column", + "items": [ + { + "type": "Text", + "text": "${primaryText}", + "style": "textStyleBody", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + }, + { + "type": "Text", + "text": "${secondaryText}", + "style": "textStyleDetails", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + } + ] + }, + { + "type": "Text", + "text": "${tertiaryText}", + "style": "textStyleBody", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "textAlign": "right", + "maxLines": 1 + } + ] + } + ] + } + }, + "mainTemplate": { + "parameters": [ + "payload" + ], + "item": [ + { + "type": "Container", + "id": "BookCabSimpleDialogAPL", + "items": [ + { + "type": "TouchWrapper", + "onPress": { + "type": "SendEvent", + "arguments": [ + "delegateToColtraneOld" + ] + }, + "item": { + "type": "Text", + "id": "BookCabSimpleDialogAPL", + "paddingTop": "100", + "paddingLeft": "100", + "color": "green", + "size": 50, + "text": "which date ?" + } + } + ] + } + ] + } + } \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/display/weather_success_apl_display/document.json b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/display/weather_success_apl_display/document.json new file mode 100644 index 00000000..1974945a --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/display/weather_success_apl_display/document.json @@ -0,0 +1,412 @@ +{ + "type": "APL", + "version": "1.1", + "settings": {}, + "theme": "dark", + "import": [ + { + "name": "alexa-layouts", + "version": "1.0.0" + } + ], + "resources": [ + { + "description": "Stock color for the light theme", + "colors": { + "colorTextPrimary": "#151920" + } + }, + { + "description": "Stock color for the dark theme", + "when": "${viewport.theme == 'dark'}", + "colors": { + "colorTextPrimary": "#f0f1ef" + } + }, + { + "description": "Standard font sizes", + "dimensions": { + "textSizeBody": 48, + "textSizePrimary": 27, + "textSizeSecondary": 23, + "textSizeDetails": 20, + "textSizeSecondaryHint": 25 + } + }, + { + "description": "Common spacing values", + "dimensions": { + "spacingThin": 6, + "spacingSmall": 12, + "spacingMedium": 24, + "spacingLarge": 48, + "spacingExtraLarge": 72 + } + }, + { + "description": "Common margins and padding", + "dimensions": { + "marginTop": 40, + "marginLeft": 60, + "marginRight": 60, + "marginBottom": 40 + } + } + ], + "styles": { + "textStyleBase": { + "description": "Base font description; set color", + "values": [ + { + "color": "@colorTextPrimary" + } + ] + }, + "textStyleBase0": { + "description": "Thin version of basic font", + "extend": "textStyleBase", + "values": { + "fontWeight": "100" + } + }, + "textStyleBase1": { + "description": "Light version of basic font", + "extend": "textStyleBase", + "values": { + "fontWeight": "300" + } + }, + "textStyleBase2": { + "description": "Regular version of basic font", + "extend": "textStyleBase", + "values": { + "fontWeight": "500" + } + }, + "mixinBody": { + "values": { + "fontSize": "@textSizeBody" + } + }, + "mixinPrimary": { + "values": { + "fontSize": "@textSizePrimary" + } + }, + "mixinDetails": { + "values": { + "fontSize": "@textSizeDetails" + } + }, + "mixinSecondary": { + "values": { + "fontSize": "@textSizeSecondary" + } + }, + "textStylePrimary": { + "extend": [ + "textStyleBase1", + "mixinPrimary" + ] + }, + "textStyleSecondary": { + "extend": [ + "textStyleBase0", + "mixinSecondary" + ] + }, + "textStyleBody": { + "extend": [ + "textStyleBase1", + "mixinBody" + ] + }, + "textStyleSecondaryHint": { + "values": { + "fontFamily": "Bookerly", + "fontStyle": "italic", + "fontSize": "@textSizeSecondaryHint", + "color": "@colorTextPrimary" + } + }, + "textStyleDetails": { + "extend": [ + "textStyleBase2", + "mixinDetails" + ] + } + }, + "onMount": [], + "graphics": {}, + "commands": {}, + "layouts": { + "ListTemplate1": { + "parameters": [ + "backgroundImage", + "title", + "logo", + "hintText", + "listData" + ], + "item": [ + { + "type": "Container", + "width": "100vw", + "height": "100vh", + "direction": "column", + "items": [ + { + "type": "Image", + "source": "${backgroundImage}", + "scale": "best-fill", + "width": "100vw", + "height": "100vh", + "position": "absolute" + }, + { + "type": "AlexaHeader", + "headerTitle": "${title}", + "headerAttributionImage": "${logo}" + }, + { + "type": "Sequence", + "grow": 1, + "height": "80vh", + "scrollDirection": "vertical", + "paddingLeft": "@marginLeft", + "paddingRight": "@marginRight", + "data": "${listData}", + "numbered": true, + "items": [ + { + "type": "VerticalListItem", + "image": "${data.image.sources[0].url}", + "primaryText": "${data.textContent.primaryText.text}", + "secondaryText": "${data.textContent.secondaryText.text}", + "tertiaryText": "${data.textContent.tertiaryText.text}" + } + ] + } + ] + } + ] + }, + "VerticalListItem": { + "parameters": [ + "primaryText", + "secondaryText", + "tertiaryText", + "image" + ], + "item": [ + { + "when": "${viewport.shape == 'round'}", + "type": "Container", + "direction": "row", + "height": 200, + "width": 500, + "alignItems": "center", + "items": [ + { + "type": "Text", + "text": "${ordinal}", + "paddingBottom": "20dp", + "color": "white", + "spacing": "5dp" + }, + { + "type": "Image", + "when": "${image}", + "source": "${image}", + "height": 150, + "width": 150, + "spacing": 15, + "scale": "best-fit", + "align": "top" + }, + { + "type": "Container", + "direction": "column", + "spacing": 25, + "items": [ + { + "type": "Text", + "text": "${primaryText}", + "style": "textStyleDetail", + "grow": 1, + "shrink": 1, + "fontWeight": "300", + "maxLines": 1 + }, + { + "type": "Text", + "text": "${secondaryText}", + "style": "textStyleCaption", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + }, + { + "type": "Text", + "text": "${tertiaryText}", + "style": "textStyleDetails", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + } + ] + } + ] + }, + { + "type": "Container", + "direction": "row", + "height": 125, + "width": 800, + "alignItems": "center", + "items": [ + { + "type": "Text", + "text": "${ordinal}", + "paddingBottom": "20dp", + "color": "white", + "spacing": "5dp" + }, + { + "type": "Image", + "when": "${image}", + "source": "${image}", + "height": 100, + "width": 100, + "align": "top", + "spacing": 50, + "scale": "best-fit" + }, + { + "type": "Container", + "spacing": 30, + "direction": "column", + "items": [ + { + "type": "Text", + "text": "${primaryText}", + "style": "textStyleBody", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + }, + { + "type": "Text", + "text": "${secondaryText}", + "style": "textStyleDetails", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "maxLines": 1 + } + ] + }, + { + "type": "Text", + "text": "${tertiaryText}", + "style": "textStyleBody", + "fontWeight": "300", + "grow": 1, + "shrink": 1, + "textAlign": "right", + "maxLines": 1 + } + ] + } + ] + } + }, + "mainTemplate": { + "parameters": [ + "payload" + ], + "item": [ + { + "type": "Container", + "id": "BookCabSimpleDialogAPL", + "items": [ + { + "type": "TouchWrapper", + "onPress": { + "type": "SendEvent", + "arguments": [ + "delegateToSkillNew" + ] + }, + "item": { + "type": "Text", + "id": "BookCabSimpleDialogAPL", + "paddingTop": "100", + "paddingLeft": "100", + "color": "green", + "size": 50, + "text": "delegateToSkillNew" + } + }, + { + "type": "TouchWrapper", + "onPress": { + "type": "SendEvent", + "arguments": [ + "delegateToSkillOld" + ] + }, + "item": { + "type": "Text", + "id": "BookCabSimpleDialogAPL", + "paddingTop": "100", + "paddingLeft": "100", + "color": "green", + "size": 50, + "text": "delegateToSkillOld" + } + }, + { + "type": "TouchWrapper", + "onPress": { + "type": "SendEvent", + "arguments": [ + "delegateToColtraneNew" + ] + }, + "item": { + "type": "Text", + "id": "BookCabSimpleDialogAPL", + "paddingTop": "100", + "paddingLeft": "100", + "color": "green", + "size": 50, + "text": "delegateToColtraneNew" + } + }, + { + "type": "TouchWrapper", + "onPress": { + "type": "SendEvent", + "arguments": [ + "delegateToColtraneOld" + ] + }, + "item": { + "type": "Text", + "id": "BookCabSimpleDialogAPL", + "paddingTop": "100", + "paddingLeft": "100", + "color": "green", + "size": 50, + "text": "delegateToColtraneOld" + } + } + ] + } + ] + } +} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/AlexaConversationsBye/document.json b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/AlexaConversationsBye/document.json new file mode 100644 index 00000000..bde5ee56 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/AlexaConversationsBye/document.json @@ -0,0 +1,21 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": [ + "payload" + ], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "Bye.", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/AlexaConversationsNotifyFailure/document.json b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/AlexaConversationsNotifyFailure/document.json new file mode 100644 index 00000000..c31fe279 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/AlexaConversationsNotifyFailure/document.json @@ -0,0 +1,21 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": [ + "payload" + ], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "Sorry, there was an error in the request.", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/AlexaConversationsOutOfDomain/document.json b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/AlexaConversationsOutOfDomain/document.json new file mode 100644 index 00000000..3796d4d5 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/AlexaConversationsOutOfDomain/document.json @@ -0,0 +1,21 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": [ + "payload" + ], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "Sorry, I don't understand.", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/AlexaConversationsProvideHelp/document.json b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/AlexaConversationsProvideHelp/document.json new file mode 100644 index 00000000..13b27c11 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/AlexaConversationsProvideHelp/document.json @@ -0,0 +1,21 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": [ + "payload" + ], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "I can give you the weather report. Just say \"what's the weather\" to start.", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/AlexaConversationsRequestMore/document.json b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/AlexaConversationsRequestMore/document.json new file mode 100644 index 00000000..fb3e56ae --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/AlexaConversationsRequestMore/document.json @@ -0,0 +1,21 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": [ + "payload" + ], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "What do you want to do.", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/AlexaConversationsThankYou/document.json b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/AlexaConversationsThankYou/document.json new file mode 100644 index 00000000..2112f02e --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/AlexaConversationsThankYou/document.json @@ -0,0 +1,21 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": [ + "payload" + ], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "Thank you.", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/AlexaConversationsWelcome/document.json b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/AlexaConversationsWelcome/document.json new file mode 100644 index 00000000..aeacaae2 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/AlexaConversationsWelcome/document.json @@ -0,0 +1,21 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": [ + "payload" + ], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "Welcome to the weather bot, I can give you the weather report. Just say \"what's the weather\" to start.", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/AlexaConversationsYouAreWelcome/document.json b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/AlexaConversationsYouAreWelcome/document.json new file mode 100644 index 00000000..7ade07ba --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/AlexaConversationsYouAreWelcome/document.json @@ -0,0 +1,21 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": [ + "payload" + ], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "You are welcome.", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/alexa_prize_preconditions_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/alexa_prize_preconditions_apla/document.json new file mode 100644 index 00000000..e50c4e94 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/alexa_prize_preconditions_apla/document.json @@ -0,0 +1,91 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": [ + "payload" + ], + "item": { + "type": "Selector", + "description": "Selects the speech response to render when device/locale is not supported", + "items": [ + { + "when": "${payload.result.isDeviceSupported == 0}", + "type": "Speech", + "contentType": "text", + "content": "Sorry, Alexa Prize is not available on this device.", + "description": "" + }, + { + "when": "${payload.result.isLocaleSupported == 0}", + "type": "Speech", + "contentType": "text", + "content": "Sorry, Alexa Prize is not available in your locale.", + "description": "" + }, + { + "when": "${payload.result.isSocialBotAvailable == 0}", + "type": "Speech", + "contentType": "text", + "content": "Right now the Alexa Prize socialbots are busy. Please try again soon and help the university students in their competition to advance conversational A I.", + "description": "" + }, + { + "when": "${payload.result.isAlexaPrizeEnabled == 0}", + "type": "Speech", + "contentType": "text", + "content": "Alexa Prize is currently disabled for this account. Please visit the skill store in the Alexa App to re-enable it.", + "description": "" + }, + { + "when": "${payload.result.isTopicBanned == 1}", + "type": "Speech", + "contentType": "text", + "content": "I’d rather not talk about that, but there’s lots of other things to chat about. Do you still wanna chat?", + "description": "The topic that user wants to talk about is banned, ask if they still want to chat about something else" + }, + { + "when": "${payload.result.isFalseWake == 1}", + "type": "Speech", + "contentType": "text", + "content": "Would you like to chat with an Alexa Prize socialbot?", + "description": "" + }, + { + "when": "${payload.result.handoffPromptOverride == 'HandOffConversationForFilming'}", + "type": "Speech", + "contentType": "text", + "content": "Welcome to the Finals of the Alexa Prize Socialbot Grand Challenge 3, a university competition to advance AI. I’ll get you a socialbot now.", + "description": "" + }, + { + "when": "${payload.result.handoffPromptOverride == 'HandOffConversationForFinals'}", + "type": "Speech", + "contentType": "text", + "content": "Welcome to the Alexa Prize Socialbot Grand Challenge 3: Grand Finale. Here’s one of the finalists.", + "description": "" + }, + { + "when": "${payload.result.handoffPromptOverride == 'HandOffConversationForRepeatUser'}", + "type": "Speech", + "contentType": "text", + "content": "Welcome to the Alexa Prize, a university competition to advance AI. It’s quarterfinals for these socialbots and your ratings help determine who makes it to the semifinals. I’ll get you a socialbot now. When you’re done, say stop, and I’ll ask you for your rating. Your conversation and feedback will be shared with the university to help the socialbots improve.", + "description": "" + }, + { + "when": "${payload.result.handoffPromptOverride == 'CancelHandoff'}", + "type": "Speech", + "contentType": "text", + "content": "Okay", + "description": "" + }, + { + "type": "Speech", + "contentType": "text", + "content": "Welcome to the Alexa Prize, a university competition to advance AI. It’s quarterfinals for these socialbots and your ratings help determine who makes it to the semifinals. I’ll get you a socialbot now. When you’re done, say stop, and I’ll ask you for your rating. Your conversation and feedback will be shared with the university to help the socialbots improve.", + "description": "This is the current default handoff prompt" + } + ] + } + } +} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/confirm_color_for_fruit_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/confirm_color_for_fruit_apla/document.json new file mode 100644 index 00000000..835d7a8e --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/confirm_color_for_fruit_apla/document.json @@ -0,0 +1,21 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": [ + "payload" + ], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "confirm color is ${payload.colorName} ? ", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/confirm_fruitName_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/confirm_fruitName_apla/document.json new file mode 100644 index 00000000..42d63adc --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/confirm_fruitName_apla/document.json @@ -0,0 +1,21 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": [ + "payload" + ], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "confirm fruit ${payload.fruitName} ? ", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/getEmployeePosition_success_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/getEmployeePosition_success_apla/document.json new file mode 100644 index 00000000..4f5794c0 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/getEmployeePosition_success_apla/document.json @@ -0,0 +1,21 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": [ + "payload" + ], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "${payload.result.name1} born on ${payload.result.a_dateOfBirth} with employee id ${payload.result.emplyee1id} , is an ${payload.result.position} ", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/no_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/no_apla/document.json new file mode 100644 index 00000000..76610fcc --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/no_apla/document.json @@ -0,0 +1,21 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": [ + "payload" + ], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "I'm sorry you didn't like it", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/nothing2_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/nothing2_apla/document.json new file mode 100644 index 00000000..98f7ebef --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/nothing2_apla/document.json @@ -0,0 +1,21 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": [ + "payload" + ], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "The number you gave us was not 3.", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/nothing_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/nothing_apla/document.json new file mode 100644 index 00000000..5272f2a9 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/nothing_apla/document.json @@ -0,0 +1,21 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": [ + "payload" + ], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "The number you gave us was 3.", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/numericfeedback_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/numericfeedback_apla/document.json new file mode 100644 index 00000000..4d855af6 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/numericfeedback_apla/document.json @@ -0,0 +1,21 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": [ + "payload" + ], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "Your random number was ${payload.num}. How did we do? Please give this interaction a rating between 1-5, where 5 is the highest rating", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/rating_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/rating_apla/document.json new file mode 100644 index 00000000..7d50a649 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/rating_apla/document.json @@ -0,0 +1,21 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": [ + "payload" + ], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "rating please?", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/requestArgs_request_fruitName_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/requestArgs_request_fruitName_apla/document.json new file mode 100644 index 00000000..a27a7d1e --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/requestArgs_request_fruitName_apla/document.json @@ -0,0 +1,27 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": [ + "payload" + ], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "tell me the fruit name ?", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + }, + { + "type": "Speech", + "contentType": "text", + "content": "random slection tell me the fruit name ?", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/request_city_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/request_city_apla/document.json new file mode 100644 index 00000000..65c28562 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/request_city_apla/document.json @@ -0,0 +1,21 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": [ + "payload" + ], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "Which city?", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/request_city_date_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/request_city_date_apla/document.json new file mode 100644 index 00000000..f685b93e --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/request_city_date_apla/document.json @@ -0,0 +1,21 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": [ + "payload" + ], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "Which city and for which date?", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/request_colorName_multiple_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/request_colorName_multiple_apla/document.json new file mode 100644 index 00000000..62911ca4 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/request_colorName_multiple_apla/document.json @@ -0,0 +1,21 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": [ + "payload" + ], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "which color?", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/request_date_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/request_date_apla/document.json new file mode 100644 index 00000000..3beebe7b --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/request_date_apla/document.json @@ -0,0 +1,21 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": [ + "payload" + ], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "Which date?", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/request_dob_getDate_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/request_dob_getDate_apla/document.json new file mode 100644 index 00000000..cabe7441 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/request_dob_getDate_apla/document.json @@ -0,0 +1,21 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": [ + "payload" + ], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "SSML", + "content": "provide date?", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/request_getEmploeeID_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/request_getEmploeeID_apla/document.json new file mode 100644 index 00000000..7649453f --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/request_getEmploeeID_apla/document.json @@ -0,0 +1,21 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": [ + "payload" + ], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "SSML", + "content": "provide employee id?", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/request_name_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/request_name_apla/document.json new file mode 100644 index 00000000..8afc80bf --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/request_name_apla/document.json @@ -0,0 +1,21 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": [ + "payload" + ], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "SSML", + "content": "what is your cool name?", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/response0Prompt16/document.json b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/response0Prompt16/document.json new file mode 100644 index 00000000..9460f0b2 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/response0Prompt16/document.json @@ -0,0 +1 @@ +{"type":"APLA","version":"0.8","mainTemplate":{"parameters":["payload"],"item":{"type":"Selector","strategy":"randomItem","description":"Change 'type' above to try different Selector Component Types like Sequencer","items":[{"type":"Speech","contentType":"text","content":"confirm color is ${payload.colorName} ?","description":"Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that"}]}}} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/secondEarthAPI_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/secondEarthAPI_apla/document.json new file mode 100644 index 00000000..be1095b2 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/secondEarthAPI_apla/document.json @@ -0,0 +1,21 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": [ + "payload" + ], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "success delegating", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/success_colorFruitAPI_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/success_colorFruitAPI_apla/document.json new file mode 100644 index 00000000..873e2711 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/success_colorFruitAPI_apla/document.json @@ -0,0 +1,21 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": [ + "payload" + ], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "price of an ${payload.result.fruitName} is free bucks ", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/success_fruitPriceAPI_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/success_fruitPriceAPI_apla/document.json new file mode 100644 index 00000000..b4a7272b --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/success_fruitPriceAPI_apla/document.json @@ -0,0 +1,21 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": [ + "payload" + ], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "price of an ${payload.result.fruitName} is ${payload.result.price} bucks ", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/weather_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/weather_apla/document.json new file mode 100644 index 00000000..4c5d2883 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/weather_apla/document.json @@ -0,0 +1,29 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": [ + "payload" + ], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "when": "${payload.weatherResult != null && payload.weatherResult.cityName != null && payload.weatherResult.highTemp != null && payload.weatherResult.lowTemp != null}", + "type": "Speech", + "contentType": "text", + "content": "In ${payload.weatherResult.cityName}, it's a high of ${payload.weatherResult.highTemp} degrees and a low of ${payload.weatherResult.lowTemp} degrees.", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + }, + { + "when": "${payload.weatherResult != null && payload.weatherResult.cityNameChanged != null && payload.weatherResult.highTemp != null && payload.weatherResult.lowTemp != null}", + "type": "Speech", + "contentType": "text", + "content": "In ${payload.weatherResult.cityName}, it's a high of ${payload.weatherResult.highTemp} degrees and a low of ${payload.weatherResult.lowTemp} degrees.", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/weather_apla_de_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/weather_apla_de_apla/document.json new file mode 100644 index 00000000..a2d34b37 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/weather_apla_de_apla/document.json @@ -0,0 +1,29 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": [ + "payload" + ], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "when": "${payload.weatherResult != null && payload.weatherResult.cityName != null && payload.weatherResult.highTemp != null && payload.weatherResult.lowTemp != null}", + "type": "Speech", + "contentType": "text", + "content": "German result satheesh In ${payload.weatherResult.cityName}, it's a high of ${payload.weatherResult.highTemp} degrees and a low of ${payload.weatherResult.lowTemp} degrees.", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + }, + { + "when": "${payload.weatherResult != null && payload.weatherResult.cityNameChanged != null && payload.weatherResult.highTemp != null && payload.weatherResult.lowTemp != null}", + "type": "Speech", + "contentType": "text", + "content": "German result satheesh In ${payload.weatherResult.cityName}, it's a high of ${payload.weatherResult.highTemp} degrees and a low of ${payload.weatherResult.lowTemp} degrees.", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/whoAmiSuccess/datasources/default.json b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/whoAmiSuccess/datasources/default.json new file mode 100644 index 00000000..6f317d9e --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/whoAmiSuccess/datasources/default.json @@ -0,0 +1,7 @@ +{ + "weatherResult": { + "cityName": "Houston", + "highTemperature": "92", + "lowTemperature": "78" + } +} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/whoAmiSuccess/document.json b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/whoAmiSuccess/document.json new file mode 100644 index 00000000..4c7b4dc2 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/whoAmiSuccess/document.json @@ -0,0 +1,22 @@ +{ + "type": "APLA", + "version": "0.8", + "mainTemplate": { + "parameters": [ + "payload" + ], + "item": { + "type": "Selector", + "strategy": "randomItem", + "description": "Change 'type' above to try different Selector Component Types like Sequencer", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "who am i result", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/yes_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/yes_apla/document.json new file mode 100644 index 00000000..021dec67 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/yes_apla/document.json @@ -0,0 +1,21 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": [ + "payload" + ], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "Nice! Glad you like it", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/yesnofeedback_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/yesnofeedback_apla/document.json new file mode 100644 index 00000000..f0242d89 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/yesnofeedback_apla/document.json @@ -0,0 +1,21 @@ +{ + "type": "APL-A", + "version": "0.1", + "mainTemplate": { + "parameters": [ + "payload" + ], + "item": { + "type": "RandomSelector", + "description": "Change 'type' above to try different Selector Component Types like Sequential", + "items": [ + { + "type": "Speech", + "contentType": "text", + "content": "Your number was ${payload.num}. Is this a good number, yes or no?", + "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" + } + ] + } + } +} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/skill.json b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/skill.json new file mode 100644 index 00000000..4b64e280 --- /dev/null +++ b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/skill.json @@ -0,0 +1,119 @@ +{ + "manifest": { + "apis": { + "custom": { + "dialogManagement": { + "dialogManagers": [ + { + "type": "AMAZON.Conversations" + } + ], + "sessionStartDelegationStrategy": { + "target": "AMAZON.Conversations" + } + }, + "endpoint": { + "uri": "arn:aws:lambda:us-west-2:267006587462:function:ramansatTestFunction" + }, + "interfaces": [ + { + "supportedViewports": [ + { + "maxHeight": 480, + "maxWidth": 480, + "minHeight": 480, + "minWidth": 480, + "mode": "HUB", + "shape": "ROUND" + }, + { + "maxHeight": 600, + "maxWidth": 1024, + "minHeight": 600, + "minWidth": 1024, + "mode": "HUB", + "shape": "RECTANGLE" + }, + { + "maxHeight": 800, + "maxWidth": 1280, + "minHeight": 800, + "minWidth": 1280, + "mode": "HUB", + "shape": "RECTANGLE" + }, + { + "maxHeight": 540, + "maxWidth": 960, + "minHeight": 540, + "minWidth": 960, + "mode": "TV", + "shape": "RECTANGLE" + } + ], + "type": "ALEXA_PRESENTATION_APL" + } + ], + "regions": { + "NA": { + "endpoint": { + "uri": "arn:aws:lambda:us-west-2:267006587462:function:ramansatTestFunction" + } + }, + "EU": { + "endpoint": { + "uri": "arn:aws:lambda:us-west-2:267006587462:function:ramansatTestFunction" + } + }, + "FE": { + "endpoint": { + "uri": "arn:aws:lambda:us-west-2:267006587462:function:ramansatTestFunction" + } + } + } + } + }, + "manifestVersion": "1.0", + "publishingInformation": { + "category": "KNOWLEDGE_AND_TRIVIA", + "distributionCountries": [], + "isAvailableWorldwide": true, + "locales": { + "en-US": { + "description": "Sample Full Description", + "examplePhrases": [ + "Alexa open hello world", + "hello", + "help" + ], + "keywords": [], + "name": "engineering test skill three_six", + "summary": "Sample Short Description" + }, + "de-DE": { + "description": "Sample Full Description", + "examplePhrases": [ + "Alexa open hello world", + "hello", + "help" + ], + "keywords": [], + "name": "engineering test skill three_three", + "summary": "Sample Short Description" + }, + "en-GB": { + "description": "Sample Full Description", + "examplePhrases": [ + "Alexa open hello world", + "hello", + "help" + ], + "keywords": [], + "name": "engineering test skill three_three", + "summary": "Sample Short Description" + } + }, + "testingInstructions": "Sample Testing Instructions." + } + } +} \ No newline at end of file diff --git a/test/unit/fixture/model/app-config-no-profiles.json b/test/unit/fixture/model/app-config-no-profiles.json index 43e0c99c..6c095dc6 100644 --- a/test/unit/fixture/model/app-config-no-profiles.json +++ b/test/unit/fixture/model/app-config-no-profiles.json @@ -1,3 +1,3 @@ { "profiles": {} -} \ No newline at end of file +} diff --git a/test/unit/fixture/model/app-config.yaml b/test/unit/fixture/model/app-config.yaml index a04de766..73170606 100644 --- a/test/unit/fixture/model/app-config.yaml +++ b/test/unit/fixture/model/app-config.yaml @@ -17,5 +17,5 @@ profiles: refresh_token: Atzr|n token_type: bearer expires_in: 3600 - expires_at: '2018-09-11T18:12:18.843Z' + expires_at: "2018-09-11T18:12:18.843Z" vendor_id: wn diff --git a/test/unit/fixture/model/dialog/dialog-replay-file.json b/test/unit/fixture/model/dialog/dialog-replay-file.json index 51d4065d..e81223c6 100644 --- a/test/unit/fixture/model/dialog/dialog-replay-file.json +++ b/test/unit/fixture/model/dialog/dialog-replay-file.json @@ -1,9 +1,6 @@ { - "skillId": "amzn1.ask.skill.1234567890", - "locale": "en-US", - "type": "text", - "userInput": [ - "hello", - "world" - ] -} \ No newline at end of file + "skillId": "amzn1.ask.skill.1234567890", + "locale": "en-US", + "type": "text", + "userInput": ["hello", "world"] +} diff --git a/test/unit/fixture/model/dialog/invalid-dialog-replay-file.json b/test/unit/fixture/model/dialog/invalid-dialog-replay-file.json index fd2bff1e..f9c5f5ba 100644 --- a/test/unit/fixture/model/dialog/invalid-dialog-replay-file.json +++ b/test/unit/fixture/model/dialog/invalid-dialog-replay-file.json @@ -1,9 +1,6 @@ { - "skillId": "", - "locale": "", - "type": "text", - "userInput": [ - " ", - "world" - ] -} \ No newline at end of file + "skillId": "", + "locale": "", + "type": "text", + "userInput": [" ", "world"] +} diff --git a/test/unit/fixture/model/regional-stack-file.json b/test/unit/fixture/model/regional-stack-file.json index 4df643cc..0dfdd176 100644 --- a/test/unit/fixture/model/regional-stack-file.json +++ b/test/unit/fixture/model/regional-stack-file.json @@ -10,13 +10,9 @@ { "Effect": "Allow", "Principal": { - "Service": [ - "lambda.amazonaws.com" - ] + "Service": ["lambda.amazonaws.com"] }, - "Action": [ - "sts:AssumeRole" - ] + "Action": ["sts:AssumeRole"] } ] }, @@ -29,9 +25,7 @@ "Statement": [ { "Effect": "Allow", - "Action": [ - "logs:*" - ], + "Action": ["logs:*"], "Resource": "arn:aws:logs:*:*:*" } ] diff --git a/test/unit/fixture/model/regional-stack-file.yaml b/test/unit/fixture/model/regional-stack-file.yaml index 978766ec..336dd5ee 100644 --- a/test/unit/fixture/model/regional-stack-file.yaml +++ b/test/unit/fixture/model/regional-stack-file.yaml @@ -1,27 +1,27 @@ AWSTemplateFormatVersion: 2010-09-09 Resources: AlexaSkillIAMRole: - Type: AWS::IAM::Role - Properties: - AssumeRolePolicyDocument: - Version: 2012-10-17 - Statement: - - Effect: Allow - Principal: - Service: - - lambda.amazonaws.com - Action: - - sts:AssumeRole - Path: / - Policies: - - PolicyName: alexaSkillExectionPolicy - PolicyDocument: - Version: 2012-10-17 - Statement: - - Effect: Allow - Action: - - logs:* - Resource: arn:aws:logs:*:*:* + Type: AWS::IAM::Role + Properties: + AssumeRolePolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Principal: + Service: + - lambda.amazonaws.com + Action: + - sts:AssumeRole + Path: / + Policies: + - PolicyName: alexaSkillExectionPolicy + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: + - logs:* + Resource: arn:aws:logs:*:*:* AlexaSkillFunction: Type: AWS::Lambda::Function Properties: diff --git a/test/unit/fixture/model/regular-proj/.ask/ask-states.json b/test/unit/fixture/model/regular-proj/.ask/ask-states.json index aa6a6363..3307a494 100644 --- a/test/unit/fixture/model/regular-proj/.ask/ask-states.json +++ b/test/unit/fixture/model/regular-proj/.ask/ask-states.json @@ -4,7 +4,8 @@ "default": { "skillId": "amzn1.ask.skill.1234567890", "skillMetadata": { - "lastDeployHash": "hash==" + "lastDeployHash": "hash==", + "lastDeployType": "interaction-model" }, "code": { "default": { diff --git a/test/unit/fixture/model/regular-proj/random-json-config.json b/test/unit/fixture/model/regular-proj/random-json-config.json index b8daec3b..e96de5cb 100644 --- a/test/unit/fixture/model/regular-proj/random-json-config.json +++ b/test/unit/fixture/model/regular-proj/random-json-config.json @@ -1,18 +1,14 @@ { - "simpleKey": "simpleValue", - "objectField": { - "internalKey": "internalValue" - }, - "arrayField": [ - 1, - 2, - 3 - ], - "nested": { - "innerArray": [ - { - "innerKey": "treasure" - } - ] - } + "simpleKey": "simpleValue", + "objectField": { + "internalKey": "internalValue" + }, + "arrayField": [1, 2, 3], + "nested": { + "innerArray": [ + { + "innerKey": "treasure" + } + ] } +} diff --git a/test/unit/fixture/model/resources-config.yaml b/test/unit/fixture/model/resources-config.yaml index bac42295..c12647b8 100644 --- a/test/unit/fixture/model/resources-config.yaml +++ b/test/unit/fixture/model/resources-config.yaml @@ -1,20 +1,20 @@ -askcliResourcesobjectVersion: '1.0' +askcliResourcesobjectVersion: "1.0" profiles: default: skillId: amzn1.ask.skill.5555555-4444-3333-2222-1111111111 skillMetadata: src: "./skillPackage" - lastDeployHash: '' + lastDeployHash: "" code: default: src: "./awsStack/lambda-NA/src" - lastDeployHash: '' + lastDeployHash: "" NA: src: "./awsStack/lambda-NA/src" - lastDeployHash: '' + lastDeployHash: "" EU: src: "./awsStack/lambda-EU/src" - lastDeployHash: '' + lastDeployHash: "" skillInfrastructure: type: "@ask-cli/cfn-deployer" userConfig: @@ -30,20 +30,20 @@ profiles: template: "./awsStacks/skill-infra.yaml" deployState: default: - stackId: '' + stackId: "" s3: - bucket: '' + bucket: "" key: endpoint/code - objectVersion: '' + objectVersion: "" NA: - stackId: '' + stackId: "" s3: - bucket: '' + bucket: "" key: endpoint/code - objectVersion: '' + objectVersion: "" EU: - stackId: '' + stackId: "" s3: - bucket: '' + bucket: "" key: endpoint/code - objectVersion: '' + objectVersion: "" diff --git a/test/unit/model/abstract-config-file-test.js b/test/unit/model/abstract-config-file-test.js index 54f5f8c7..198a7e63 100644 --- a/test/unit/model/abstract-config-file-test.js +++ b/test/unit/model/abstract-config-file-test.js @@ -1,330 +1,330 @@ -const { expect } = require('chai'); -const sinon = require('sinon'); -const path = require('path'); -const fs = require('fs-extra'); -const jsonfile = require('jsonfile'); +const {expect} = require("chai"); +const sinon = require("sinon"); +const path = require("path"); +const fs = require("fs-extra"); +const jsonfile = require("jsonfile"); -const ConfigFile = require('@src/model/abstract-config-file'); -const yaml = require('@src/model/yaml-parser'); -const jsonView = require('@src/view/json-view'); +const ConfigFile = require("../../../lib/model/abstract-config-file"); +const yaml = require("../../../lib/model/yaml-parser"); +const jsonView = require("../../../lib/view/json-view"); -describe('Model test - abstract config file test', () => { - const FIXTURE_PATH = path.join(process.cwd(), 'test', 'unit', 'fixture', 'model'); - const JSON_CONFIG_PATH = path.join(FIXTURE_PATH, 'json-config.json'); - const YAML_CONFIG_PATH = path.join(FIXTURE_PATH, 'json-config-yaml.yaml'); - const CONFIG_FILE = path.join(FIXTURE_PATH, 'cli_config'); +describe("Model test - abstract config file test", () => { + const FIXTURE_PATH = path.join(process.cwd(), "test", "unit", "fixture", "model"); + const JSON_CONFIG_PATH = path.join(FIXTURE_PATH, "json-config.json"); + const YAML_CONFIG_PATH = path.join(FIXTURE_PATH, "json-config-yaml.yaml"); + const CONFIG_FILE = path.join(FIXTURE_PATH, "cli_config"); - describe('# inspect correctness for constructor and content loading', () => { - const NOT_EXISTING_CONFIG_PATH = path.join(FIXTURE_PATH, 'out-of-noWhere.json'); - const INVALID_JSON_CONFIG_PATH = path.join(FIXTURE_PATH, 'invalid-json.json'); - const INVALID_YAML_CONFIG_PATH = path.join(FIXTURE_PATH, 'invalid-yaml.yaml'); - const NOT_SUPPORTED_FILE_PATH = path.join(FIXTURE_PATH, 'unsupported-file-type.notsupport'); + describe("# inspect correctness for constructor and content loading", () => { + const NOT_EXISTING_CONFIG_PATH = path.join(FIXTURE_PATH, "out-of-noWhere.json"); + const INVALID_JSON_CONFIG_PATH = path.join(FIXTURE_PATH, "invalid-json.json"); + const INVALID_YAML_CONFIG_PATH = path.join(FIXTURE_PATH, "invalid-yaml.yaml"); + const NOT_SUPPORTED_FILE_PATH = path.join(FIXTURE_PATH, "unsupported-file-type.notsupport"); - it('| init with valid config file name, expect to create a ConfigFile instance successfully', () => { - let configContent, jsonContent; - try { - // call - configContent = new ConfigFile(CONFIG_FILE); - configContent.read(); - jsonContent = jsonfile.readFileSync(CONFIG_FILE); - } catch (err) { - expect(err).equal(null); - } - // verify - expect(configContent).to.be.instanceOf(ConfigFile); - expect(configContent.fileType).equal('JSON'); - expect(configContent.content).deep.eq(jsonContent); - }); + it("| init with valid config file name, expect to create a ConfigFile instance successfully", () => { + let configContent, jsonContent; + try { + // call + configContent = new ConfigFile(CONFIG_FILE); + configContent.read(); + jsonContent = jsonfile.readFileSync(CONFIG_FILE); + } catch (err) { + expect(err).equal(null); + } + // verify + expect(configContent).to.be.instanceOf(ConfigFile); + expect(configContent.fileType).equal("JSON"); + expect(configContent.content).deep.eq(jsonContent); + }); - it('| init with valid JSON file path, expect to create a ConfigFile instance successfully', () => { - let configContent, jsonContent; - try { - // call - configContent = new ConfigFile(JSON_CONFIG_PATH); - configContent.read(); - jsonContent = jsonfile.readFileSync(JSON_CONFIG_PATH); - } catch (err) { - expect(err).equal(null); - } - // verify - expect(configContent).to.be.instanceOf(ConfigFile); - expect(configContent.fileType).equal('JSON'); - expect(configContent.content).deep.eq(jsonContent); - }); + it("| init with valid JSON file path, expect to create a ConfigFile instance successfully", () => { + let configContent, jsonContent; + try { + // call + configContent = new ConfigFile(JSON_CONFIG_PATH); + configContent.read(); + jsonContent = jsonfile.readFileSync(JSON_CONFIG_PATH); + } catch (err) { + expect(err).equal(null); + } + // verify + expect(configContent).to.be.instanceOf(ConfigFile); + expect(configContent.fileType).equal("JSON"); + expect(configContent.content).deep.eq(jsonContent); + }); - it('| init with valid YAML file path, expect to create a ConfigFile instance successfully', () => { - let yamlContent, jsonContent; - try { - // call - yamlContent = new ConfigFile(YAML_CONFIG_PATH); - yamlContent.read(); - jsonContent = jsonfile.readFileSync(JSON_CONFIG_PATH); - } catch (err) { - expect(err).equal(null); - } - // verify - expect(yamlContent).to.be.instanceOf(ConfigFile); - expect(yamlContent.fileType).equal('YAML'); - expect(yamlContent.content).deep.eq(jsonContent); - }); + it("| init with valid YAML file path, expect to create a ConfigFile instance successfully", () => { + let yamlContent, jsonContent; + try { + // call + yamlContent = new ConfigFile(YAML_CONFIG_PATH); + yamlContent.read(); + jsonContent = jsonfile.readFileSync(JSON_CONFIG_PATH); + } catch (err) { + expect(err).equal(null); + } + // verify + expect(yamlContent).to.be.instanceOf(ConfigFile); + expect(yamlContent.fileType).equal("YAML"); + expect(yamlContent.content).deep.eq(jsonContent); + }); - it('| init with a file path not existing, expect correct error message thrown', () => { - try { - // call - const config = new ConfigFile(NOT_EXISTING_CONFIG_PATH); - config.read(); - throw new Error('No error caught but supposed to throw an error when new.'); - } catch (err) { - // verify - const expectedError = `File ${NOT_EXISTING_CONFIG_PATH} not exists.`; - expect(err.message.indexOf(expectedError) !== -1).equal(true); - } - }); + it("| init with a file path not existing, expect correct error message thrown", () => { + try { + // call + const config = new ConfigFile(NOT_EXISTING_CONFIG_PATH); + config.read(); + throw new Error("No error caught but supposed to throw an error when new."); + } catch (err) { + // verify + const expectedError = `File ${NOT_EXISTING_CONFIG_PATH} not exists.`; + expect(err.message.indexOf(expectedError) !== -1).equal(true); + } + }); - it('| init with a file path without access permission, expect correct error message thrown', () => { - // setup - fs.chmodSync(JSON_CONFIG_PATH, 0o111); - try { - // call - const config = new ConfigFile(JSON_CONFIG_PATH); - config.read(); - throw new Error('No error caught but supposed to throw an error when new.'); - } catch (err) { - // verify - const expectedError = `No access to read/write file ${JSON_CONFIG_PATH}.`; - expect(err.message.indexOf(expectedError) !== -1).equal(true); - } finally { - // clear - fs.chmodSync(JSON_CONFIG_PATH, 0o644); - } - }); + it("| init with a file path without access permission, expect correct error message thrown", () => { + // setup + fs.chmodSync(JSON_CONFIG_PATH, 0o111); + try { + // call + const config = new ConfigFile(JSON_CONFIG_PATH); + config.read(); + throw new Error("No error caught but supposed to throw an error when new."); + } catch (err) { + // verify + const expectedError = `No access to read/write file ${JSON_CONFIG_PATH}.`; + expect(err.message.indexOf(expectedError) !== -1).equal(true); + } finally { + // clear + fs.chmodSync(JSON_CONFIG_PATH, 0o644); + } + }); - it('| init with an invalid json file, expect correct error message thrown', () => { - try { - const config = new ConfigFile(INVALID_JSON_CONFIG_PATH); - config.read(); - throw new Error('No error caught but supposed to throw an error when new.'); - } catch (err) { - const expectedError = `Failed to parse JSON file ${INVALID_JSON_CONFIG_PATH}.`; - expect(err.message.indexOf(expectedError) !== -1).equal(true); - } - }); + it("| init with an invalid json file, expect correct error message thrown", () => { + try { + const config = new ConfigFile(INVALID_JSON_CONFIG_PATH); + config.read(); + throw new Error("No error caught but supposed to throw an error when new."); + } catch (err) { + const expectedError = `Failed to parse JSON file ${INVALID_JSON_CONFIG_PATH}.`; + expect(err.message.indexOf(expectedError) !== -1).equal(true); + } + }); - it('| init with an invalid yaml file, expect correct error message thrown', () => { - try { - const config = new ConfigFile(INVALID_YAML_CONFIG_PATH); - config.read(); - throw new Error('No error caught but supposed to throw an error when new.'); - } catch (err) { - const expectedError = `Failed to parse YAML file ${INVALID_YAML_CONFIG_PATH}.`; - expect(err.message.indexOf(expectedError) !== -1).equal(true); - } - }); + it("| init with an invalid yaml file, expect correct error message thrown", () => { + try { + const config = new ConfigFile(INVALID_YAML_CONFIG_PATH); + config.read(); + throw new Error("No error caught but supposed to throw an error when new."); + } catch (err) { + const expectedError = `Failed to parse YAML file ${INVALID_YAML_CONFIG_PATH}.`; + expect(err.message.indexOf(expectedError) !== -1).equal(true); + } + }); - it('| init with a non-supported file type, expect correct error message thrown', () => { - try { - const config = new ConfigFile(NOT_SUPPORTED_FILE_PATH); - config.read(); - throw new Error('No error caught but supposed to throw an error when new.'); - } catch (err) { - expect(err.message).to.equal(`File type for ${NOT_SUPPORTED_FILE_PATH} is not supported. Only JSON and YAML files are supported.`); - } - }); + it("| init with a non-supported file type, expect correct error message thrown", () => { + try { + const config = new ConfigFile(NOT_SUPPORTED_FILE_PATH); + config.read(); + throw new Error("No error caught but supposed to throw an error when new."); + } catch (err) { + expect(err.message).to.equal(`File type for ${NOT_SUPPORTED_FILE_PATH} is not supported. Only JSON and YAML files are supported.`); + } }); + }); - describe('# inspect correctness for withContent method', () => { - const TEST_FILE_PATH = 'any path'; - const TEST_CONTENT = { key: 'any content' }; + describe("# inspect correctness for withContent method", () => { + const TEST_FILE_PATH = "any path"; + const TEST_CONTENT = {key: "any content"}; - beforeEach(() => { - sinon.stub(fs, 'existsSync'); - sinon.stub(fs, 'ensureDirSync'); - sinon.stub(fs, 'writeFileSync'); - sinon.stub(path, 'dirname'); - }); + beforeEach(() => { + sinon.stub(fs, "existsSync"); + sinon.stub(fs, "ensureDirSync"); + sinon.stub(fs, "writeFileSync"); + sinon.stub(path, "dirname"); + }); - afterEach(() => { - sinon.restore(); - }); + afterEach(() => { + sinon.restore(); + }); - it('| if file does exist, it is logical error to call this method, throw error out', () => { - // setup - fs.existsSync.returns(true); - path.dirname.returns(TEST_FILE_PATH); - // call - try { - ConfigFile.withContent(TEST_FILE_PATH, TEST_CONTENT); - throw 'Expect this line is not called as it should have failed before this line.'; - } catch (e) { - // verify - expect(e.message).equal(`Failed to create file ${TEST_FILE_PATH} as it already exists.`); - } - }); + it("| if file does exist, it is logical error to call this method, throw error out", () => { + // setup + fs.existsSync.returns(true); + path.dirname.returns(TEST_FILE_PATH); + // call + try { + ConfigFile.withContent(TEST_FILE_PATH, TEST_CONTENT); + throw "Expect this line is not called as it should have failed before this line."; + } catch (e) { + // verify + expect(e.message).equal(`Failed to create file ${TEST_FILE_PATH} as it already exists.`); + } + }); - it('| with content of JSON file, expect it will write to file correctly', () => { - // setup - fs.existsSync.returns(false); - path.dirname.returns(JSON_CONFIG_PATH); - // call - try { - ConfigFile.withContent(JSON_CONFIG_PATH, TEST_CONTENT); - } catch (e) { - expect(e).equal(undefined); - } - // verify - expect(fs.writeFileSync.args[0][0]).equal(JSON_CONFIG_PATH); - expect(fs.writeFileSync.args[0][1]).equal(jsonView.toString(TEST_CONTENT)); - }); + it("| with content of JSON file, expect it will write to file correctly", () => { + // setup + fs.existsSync.returns(false); + path.dirname.returns(JSON_CONFIG_PATH); + // call + try { + ConfigFile.withContent(JSON_CONFIG_PATH, TEST_CONTENT); + } catch (e) { + expect(e).equal(undefined); + } + // verify + expect(fs.writeFileSync.args[0][0]).equal(JSON_CONFIG_PATH); + expect(fs.writeFileSync.args[0][1]).equal(jsonView.toString(TEST_CONTENT)); }); + }); - describe('# inspect correctness for getProperty method', () => { - const json = new ConfigFile(JSON_CONFIG_PATH); - json.read(); + describe("# inspect correctness for getProperty method", () => { + const json = new ConfigFile(JSON_CONFIG_PATH); + json.read(); - [ - { - testCase: 'get property value at first level correctly', - input: ['simpleKey'], - expectation: 'simpleValue' - }, - { - testCase: 'get property value in an object correctly', - input: ['objectField', 'internalKey'], - expectation: 'internalValue' - }, - { - testCase: 'get property value in an array correctly', - input: ['arrayField', 1], - expectation: 2 - }, - { - testCase: 'get property value in nested level correctly', - input: ['nested', 'innerArray', 0, 'innerKey'], - expectation: 'treasure' - }, - { - testCase: 'get property value which does not exist', - input: ['nested', 5], - expectation: undefined - }, - ].forEach(({ testCase, input, expectation }) => { - it(`| ${testCase}`, () => { - expect(json.getProperty(input)).equal(expectation); - }); - }); + [ + { + testCase: "get property value at first level correctly", + input: ["simpleKey"], + expectation: "simpleValue", + }, + { + testCase: "get property value in an object correctly", + input: ["objectField", "internalKey"], + expectation: "internalValue", + }, + { + testCase: "get property value in an array correctly", + input: ["arrayField", 1], + expectation: 2, + }, + { + testCase: "get property value in nested level correctly", + input: ["nested", "innerArray", 0, "innerKey"], + expectation: "treasure", + }, + { + testCase: "get property value which does not exist", + input: ["nested", 5], + expectation: undefined, + }, + ].forEach(({testCase, input, expectation}) => { + it(`| ${testCase}`, () => { + expect(json.getProperty(input)).equal(expectation); + }); }); + }); - describe('# inspect correctness for setProperty method', () => { - const json = new ConfigFile(JSON_CONFIG_PATH); - json.read(); - [ - { - testCase: 'set value for property correctly', - inputPath: ['simpleKey'], - inputValue: 'dummy' - }, - { - testCase: 'set value for property inside an object correctly', - inputPath: ['objectField', 'internalKey'], - inputValue: 'dummy' - }, - { - testCase: 'set value for property inside an array correctly', - inputPath: ['arrayField', 0], - inputValue: 'dummy' - }, - { - testCase: 'set value for property in nested level correctly', - inputPath: ['nested', 'innerArray', 0, 'innerKey'], - inputValue: 'dummy' - }, - { - testCase: 'set value for property not existing', - inputPath: ['newField'], - inputValue: 'dummy' - }, - ].forEach(({ testCase, inputPath, inputValue }) => { - it(`| ${testCase}`, () => { - const copy = json.getProperty(inputPath); - json.setProperty(inputPath, inputValue); - expect(json.getProperty(inputPath)).equal(inputValue); - json.setProperty(inputPath, copy); - expect(json.getProperty(inputPath)).equal(copy); - }); - }); + describe("# inspect correctness for setProperty method", () => { + const json = new ConfigFile(JSON_CONFIG_PATH); + json.read(); + [ + { + testCase: "set value for property correctly", + inputPath: ["simpleKey"], + inputValue: "dummy", + }, + { + testCase: "set value for property inside an object correctly", + inputPath: ["objectField", "internalKey"], + inputValue: "dummy", + }, + { + testCase: "set value for property inside an array correctly", + inputPath: ["arrayField", 0], + inputValue: "dummy", + }, + { + testCase: "set value for property in nested level correctly", + inputPath: ["nested", "innerArray", 0, "innerKey"], + inputValue: "dummy", + }, + { + testCase: "set value for property not existing", + inputPath: ["newField"], + inputValue: "dummy", + }, + ].forEach(({testCase, inputPath, inputValue}) => { + it(`| ${testCase}`, () => { + const copy = json.getProperty(inputPath); + json.setProperty(inputPath, inputValue); + expect(json.getProperty(inputPath)).equal(inputValue); + json.setProperty(inputPath, copy); + expect(json.getProperty(inputPath)).equal(copy); + }); }); + }); - describe('# inspect correctness for write method', () => { - it('| write to JSON file successfully', () => { - // setup - const jsonConfig = new ConfigFile(JSON_CONFIG_PATH); - jsonConfig.read(); - const propertyPath = ['simpleKey']; - const copy = jsonConfig.getProperty(propertyPath); - jsonConfig.setProperty(propertyPath, 'notSimpleValue'); - // call - jsonConfig.write(); - // verify - const verifyConfig = new ConfigFile(JSON_CONFIG_PATH); - verifyConfig.read(); - expect(verifyConfig.getProperty(propertyPath)).equal('notSimpleValue'); - // clear - jsonConfig.setProperty(propertyPath, copy); - jsonConfig.write(); - }); + describe("# inspect correctness for write method", () => { + it("| write to JSON file successfully", () => { + // setup + const jsonConfig = new ConfigFile(JSON_CONFIG_PATH); + jsonConfig.read(); + const propertyPath = ["simpleKey"]; + const copy = jsonConfig.getProperty(propertyPath); + jsonConfig.setProperty(propertyPath, "notSimpleValue"); + // call + jsonConfig.write(); + // verify + const verifyConfig = new ConfigFile(JSON_CONFIG_PATH); + verifyConfig.read(); + expect(verifyConfig.getProperty(propertyPath)).equal("notSimpleValue"); + // clear + jsonConfig.setProperty(propertyPath, copy); + jsonConfig.write(); + }); - it('| write to YAML file successfully', () => { - // setup - const yamlConfig = new ConfigFile(YAML_CONFIG_PATH); - yamlConfig.read(); - const propertyPath = ['simpleKey']; - const copy = yamlConfig.getProperty(propertyPath); - yamlConfig.setProperty(propertyPath, 'notSimpleValue'); - // call - yamlConfig.write(); - // verify - const verifyConfig = new ConfigFile(YAML_CONFIG_PATH); - verifyConfig.read(); - expect(verifyConfig.getProperty(propertyPath)).equal('notSimpleValue'); - // clear - yamlConfig.setProperty(propertyPath, copy); - yamlConfig.write(); - }); + it("| write to YAML file successfully", () => { + // setup + const yamlConfig = new ConfigFile(YAML_CONFIG_PATH); + yamlConfig.read(); + const propertyPath = ["simpleKey"]; + const copy = yamlConfig.getProperty(propertyPath); + yamlConfig.setProperty(propertyPath, "notSimpleValue"); + // call + yamlConfig.write(); + // verify + const verifyConfig = new ConfigFile(YAML_CONFIG_PATH); + verifyConfig.read(); + expect(verifyConfig.getProperty(propertyPath)).equal("notSimpleValue"); + // clear + yamlConfig.setProperty(propertyPath, copy); + yamlConfig.write(); + }); - it('| expect error thrown when fs writeFileSync fails', () => { - // setup - sinon.stub(fs, 'writeFileSync'); - fs.writeFileSync.throws('error'); - try { - // call - const json = new ConfigFile(JSON_CONFIG_PATH); - json.read(); - json.write(); - } catch (err) { - // verify - expect(err).match(/error/); - } finally { - // clear - sinon.restore(); - } - }); + it("| expect error thrown when fs writeFileSync fails", () => { + // setup + sinon.stub(fs, "writeFileSync"); + fs.writeFileSync.throws("error"); + try { + // call + const json = new ConfigFile(JSON_CONFIG_PATH); + json.read(); + json.write(); + } catch (err) { + // verify + expect(err).match(/error/); + } finally { + // clear + sinon.restore(); + } + }); - it('| expect error thrown when yaml dump fails', () => { - // setup - sinon.stub(yaml, 'dump'); - yaml.dump.throws(new Error('load error')); - try { - // call - const yamlConfig = new ConfigFile(YAML_CONFIG_PATH); - yamlConfig.read(); - yamlConfig.write(); - } catch (err) { - // verify - expect(err.message).equal('load error'); - } finally { - // clear - sinon.restore(); - } - }); + it("| expect error thrown when yaml dump fails", () => { + // setup + sinon.stub(yaml, "dump"); + yaml.dump.throws(new Error("load error")); + try { + // call + const yamlConfig = new ConfigFile(YAML_CONFIG_PATH); + yamlConfig.read(); + yamlConfig.write(); + } catch (err) { + // verify + expect(err.message).equal("load error"); + } finally { + // clear + sinon.restore(); + } }); + }); }); diff --git a/test/unit/model/app-config-test.js b/test/unit/model/app-config-test.js index c36d1c09..f22210b5 100644 --- a/test/unit/model/app-config-test.js +++ b/test/unit/model/app-config-test.js @@ -1,240 +1,237 @@ -const { expect } = require('chai'); -const sinon = require('sinon'); -const path = require('path'); -const fs = require('fs-extra'); -const jsonfile = require('jsonfile'); - -const profileHelper = require('@src/utils/profile-helper'); -const AppConfig = require('@src/model/app-config'); - -describe('Model test - app config test', () => { - const FIXTURE_PATH = path.join(process.cwd(), 'test', 'unit', 'fixture', 'model'); - const APP_CONFIG_PATH = path.join(FIXTURE_PATH, 'app-config.json'); - const APP_CONFIG_NO_PROFILES_PATH = path.join(FIXTURE_PATH, 'app-config-no-profiles.json'); - const YAML_APP_CONFIG_PATH = path.join(FIXTURE_PATH, 'app-config.yaml'); - - describe('# inspect correctness for constructor, getInstance and dispose', () => { - beforeEach(() => { - sinon.stub(profileHelper, 'isEnvProfile').returns(false); - }); - - const NOT_EXISTING_PROJECT_CONFIG_PATH = path.join(FIXTURE_PATH, 'out-of-noWhere.json'); - const INVALID_JSON_PROJECT_CONFIG_PATH = path.join(FIXTURE_PATH, 'invalid-json.json'); - - it('| initiate as a AppConfig class', () => { - const appConfig = new AppConfig(APP_CONFIG_PATH); - expect(appConfig).to.be.instanceof(AppConfig); - }); - - it('| make sure AppConfig class is singleton', () => { - const config1 = new AppConfig(APP_CONFIG_PATH); - const config2 = new AppConfig(APP_CONFIG_PATH); - expect(config1 === config2); - }); - - it('| make sure YAML and JSON resources config can both be created well', () => { - const yamlConfig = new AppConfig(YAML_APP_CONFIG_PATH); - const jsonConfig = jsonfile.readFileSync(APP_CONFIG_PATH); - expect(yamlConfig.content).deep.equal(jsonConfig); - }); - - it('| get instance function return the instance constructed before', () => { - const appConfig = new AppConfig(APP_CONFIG_PATH); - expect(AppConfig.getInstance() === appConfig).equal(true); - }); - - it('| dispose the instance correctly', () => { - new AppConfig(APP_CONFIG_PATH); - AppConfig.dispose(); - expect(AppConfig.getInstance()).equal(null); - }); - - it('| init with a file path not existing, expect correct error message thrown', () => { - try { - new AppConfig(NOT_EXISTING_PROJECT_CONFIG_PATH); - throw new Error('No error caught but supposed to throw an error when new.'); - } catch (err) { - const expectedError = `File ${NOT_EXISTING_PROJECT_CONFIG_PATH} not exists.`; - expect(err.message.indexOf(expectedError) !== -1).equal(true); - } - }); - - it('| init with a file path without access permission, expect correct error message thrown', () => { - // setup - fs.chmodSync(APP_CONFIG_PATH, 0o111); - try { - // call - new AppConfig(APP_CONFIG_PATH); - throw new Error('No error caught but supposed to throw an error when new.'); - } catch (err) { - // verify - const expectedError = `No access to read/write file ${APP_CONFIG_PATH}.`; - expect(err.message.indexOf(expectedError) !== -1).equal(true); - } finally { - // clear - fs.chmodSync(APP_CONFIG_PATH, 0o644); - } - }); - - it('| init with a invalid json file, expect correct error message thrown', () => { - try { - new AppConfig(INVALID_JSON_PROJECT_CONFIG_PATH); - throw new Error('No error caught but supposed to throw an error when new.'); - } catch (err) { - const expectedError = `Failed to parse JSON file ${INVALID_JSON_PROJECT_CONFIG_PATH}.`; - expect(err.message.indexOf(expectedError) !== -1).equal(true); - } - }); - - afterEach(() => { - AppConfig.dispose(); - sinon.restore(); - }); - }); - - describe('# inspect getter and setter for each field', () => { - const TEST_PROFILE = 'testProfile'; - - beforeEach(() => { - sinon.stub(profileHelper, 'isEnvProfile').returns(false); - new AppConfig(APP_CONFIG_PATH); - }); - - [ - { - field: 'AwsProfile', - profile: TEST_PROFILE, - newValue: 'awsProfile new', - oldValue: 'awsProfile' - }, - { - field: 'Token', - profile: TEST_PROFILE, - newValue: 'token new', - oldValue: { - access_token: 'accessToken', - refresh_token: 'refreshToken', - token_type: 'bearer', - expires_in: 3600, - expires_at: 'expiresAt' - } - }, - { - field: 'VendorId', - profile: TEST_PROFILE, - newValue: 'vendorId new', - oldValue: 'vendorId' - } - ].forEach(({ - field, - profile, - newValue, - oldValue - }) => { - it(`test get${field} function successfully`, () => { - expect(AppConfig.getInstance()[`get${field}`](profile)).deep.equal(oldValue); - }); - - it(`test set${field} function successfully`, () => { - AppConfig.getInstance()[`set${field}`](profile, newValue); - expect(AppConfig.getInstance()[`get${field}`](profile)).equal(newValue); - }); - }); - - it('test getMachineId function successfully', () => { - expect(AppConfig.getInstance().getMachineId()).deep.equal('machineId'); - }); - - it('test setMachineId function successfully', () => { - AppConfig.getInstance().setMachineId('new Machine id'); - expect(AppConfig.getInstance().getMachineId()).equal('new Machine id'); - }); - - it('test getShareUsage function successfully', () => { - expect(AppConfig.getInstance().getShareUsage()).deep.equal(false); - }); - - it('test getShareUsage when property is not set', () => { - sinon.stub(AppConfig.prototype, 'getProperty').returns(); - expect(AppConfig.getInstance().getShareUsage()).deep.equal(true); - }); - - afterEach(() => { - AppConfig.dispose(); - sinon.restore(); - }); - }); - - describe('# inspect getter when using profile from env', () => { - const TEST_PROFILE = 'testProfile'; - - beforeEach(() => { - process.env.ASK_ACCESS_TOKEN = 'testAccessTokenFromEnv'; - process.env.ASK_REFRESH_TOKEN = 'testRefreshTokenFromEnv'; - process.env.ASK_VENDOR_ID = 'testVendorIdFromEnv'; - sinon.stub(profileHelper, 'isEnvProfile').returns(true); - new AppConfig(); - }); - - it('| should get tokens with values from env variables', () => { - const token = AppConfig.getInstance().getToken(TEST_PROFILE); - expect(token.access_token).eql(process.env.ASK_ACCESS_TOKEN); - expect(token.refresh_token).eql(process.env.ASK_REFRESH_TOKEN); - }); - - it('| should get vendor id from env variable', () => { - const vendorId = AppConfig.getInstance().getVendorId(TEST_PROFILE); - expect(vendorId).eql(process.env.ASK_VENDOR_ID); - }); - - afterEach(() => { - delete process.env.ASK_ACCESS_TOKEN; - delete process.env.ASK_REFRESH_TOKEN; - delete process.env.ASK_VENDOR_ID; - AppConfig.dispose(); - sinon.restore(); - }); - }); - - describe('# inspect correctness of getProfilesList', () => { - it('| test with empty profiles config file, expect empty array', () => { - // setup - new AppConfig(APP_CONFIG_NO_PROFILES_PATH); - - // call & verify - expect(AppConfig.getInstance().getProfilesList().length).to.equal(0); - }); - - it('| test with valid profiles config file, expect array of objects', () => { - // setup - new AppConfig(APP_CONFIG_PATH); - - // call & verify - expect(AppConfig.getInstance().getProfilesList().length).to.equal(2); - expect(AppConfig.getInstance().getProfilesList()).to.deep.equal([{ askProfile: 'testProfile', awsProfile: 'awsProfile' }, - { askProfile: 'default', awsProfile: 'default' }]); - }); - - afterEach(() => { - AppConfig.dispose(); - }); - }); - - describe('# inspect correctness of configFileExists', () => { - it('| returns true if config file exists', () => { - sinon.stub(fs, 'existsSync').returns(true); - - expect(AppConfig.configFileExists()).to.equal(true); - }); - - it('| returns false if config file does not exist', () => { - sinon.stub(fs, 'existsSync').returns(false); - - expect(AppConfig.configFileExists()).to.equal(false); - }); - - afterEach(() => { - sinon.restore(); - }); +const {expect} = require("chai"); +const sinon = require("sinon"); +const path = require("path"); +const fs = require("fs-extra"); +const jsonfile = require("jsonfile"); + +const profileHelper = require("../../../lib/utils/profile-helper"); +const AppConfig = require("../../../lib/model/app-config"); + +describe("Model test - app config test", () => { + const FIXTURE_PATH = path.join(process.cwd(), "test", "unit", "fixture", "model"); + const APP_CONFIG_PATH = path.join(FIXTURE_PATH, "app-config.json"); + const APP_CONFIG_NO_PROFILES_PATH = path.join(FIXTURE_PATH, "app-config-no-profiles.json"); + const YAML_APP_CONFIG_PATH = path.join(FIXTURE_PATH, "app-config.yaml"); + + describe("# inspect correctness for constructor, getInstance and dispose", () => { + beforeEach(() => { + sinon.stub(profileHelper, "isEnvProfile").returns(false); }); + + const NOT_EXISTING_PROJECT_CONFIG_PATH = path.join(FIXTURE_PATH, "out-of-noWhere.json"); + const INVALID_JSON_PROJECT_CONFIG_PATH = path.join(FIXTURE_PATH, "invalid-json.json"); + + it("| initiate as a AppConfig class", () => { + const appConfig = new AppConfig(APP_CONFIG_PATH); + expect(appConfig).to.be.instanceof(AppConfig); + }); + + it("| make sure AppConfig class is singleton", () => { + const config1 = new AppConfig(APP_CONFIG_PATH); + const config2 = new AppConfig(APP_CONFIG_PATH); + expect(config1 === config2); + }); + + it("| make sure YAML and JSON resources config can both be created well", () => { + const yamlConfig = new AppConfig(YAML_APP_CONFIG_PATH); + const jsonConfig = jsonfile.readFileSync(APP_CONFIG_PATH); + expect(yamlConfig.content).deep.equal(jsonConfig); + }); + + it("| get instance function return the instance constructed before", () => { + const appConfig = new AppConfig(APP_CONFIG_PATH); + expect(AppConfig.getInstance() === appConfig).equal(true); + }); + + it("| dispose the instance correctly", () => { + new AppConfig(APP_CONFIG_PATH); + AppConfig.dispose(); + expect(AppConfig.getInstance()).equal(null); + }); + + it("| init with a file path not existing, expect correct error message thrown", () => { + try { + new AppConfig(NOT_EXISTING_PROJECT_CONFIG_PATH); + throw new Error("No error caught but supposed to throw an error when new."); + } catch (err) { + const expectedError = `File ${NOT_EXISTING_PROJECT_CONFIG_PATH} not exists.`; + expect(err.message.indexOf(expectedError) !== -1).equal(true); + } + }); + + it("| init with a file path without access permission, expect correct error message thrown", () => { + // setup + fs.chmodSync(APP_CONFIG_PATH, 0o111); + try { + // call + new AppConfig(APP_CONFIG_PATH); + throw new Error("No error caught but supposed to throw an error when new."); + } catch (err) { + // verify + const expectedError = `No access to read/write file ${APP_CONFIG_PATH}.`; + expect(err.message.indexOf(expectedError) !== -1).equal(true); + } finally { + // clear + fs.chmodSync(APP_CONFIG_PATH, 0o644); + } + }); + + it("| init with a invalid json file, expect correct error message thrown", () => { + try { + new AppConfig(INVALID_JSON_PROJECT_CONFIG_PATH); + throw new Error("No error caught but supposed to throw an error when new."); + } catch (err) { + const expectedError = `Failed to parse JSON file ${INVALID_JSON_PROJECT_CONFIG_PATH}.`; + expect(err.message.indexOf(expectedError) !== -1).equal(true); + } + }); + + afterEach(() => { + AppConfig.dispose(); + sinon.restore(); + }); + }); + + describe("# inspect getter and setter for each field", () => { + const TEST_PROFILE = "testProfile"; + + beforeEach(() => { + sinon.stub(profileHelper, "isEnvProfile").returns(false); + new AppConfig(APP_CONFIG_PATH); + }); + + [ + { + field: "AwsProfile", + profile: TEST_PROFILE, + newValue: "awsProfile new", + oldValue: "awsProfile", + }, + { + field: "Token", + profile: TEST_PROFILE, + newValue: "token new", + oldValue: { + access_token: "accessToken", + refresh_token: "refreshToken", + token_type: "bearer", + expires_in: 3600, + expires_at: "expiresAt", + }, + }, + { + field: "VendorId", + profile: TEST_PROFILE, + newValue: "vendorId new", + oldValue: "vendorId", + }, + ].forEach(({field, profile, newValue, oldValue}) => { + it(`test get${field} function successfully`, () => { + expect(AppConfig.getInstance()[`get${field}`](profile)).deep.equal(oldValue); + }); + + it(`test set${field} function successfully`, () => { + AppConfig.getInstance()[`set${field}`](profile, newValue); + expect(AppConfig.getInstance()[`get${field}`](profile)).equal(newValue); + }); + }); + + it("test getMachineId function successfully", () => { + expect(AppConfig.getInstance().getMachineId()).deep.equal("machineId"); + }); + + it("test setMachineId function successfully", () => { + AppConfig.getInstance().setMachineId("new Machine id"); + expect(AppConfig.getInstance().getMachineId()).equal("new Machine id"); + }); + + it("test getShareUsage function successfully", () => { + expect(AppConfig.getInstance().getShareUsage()).deep.equal(false); + }); + + it("test getShareUsage when property is not set", () => { + sinon.stub(AppConfig.prototype, "getProperty").returns(); + expect(AppConfig.getInstance().getShareUsage()).deep.equal(true); + }); + + afterEach(() => { + AppConfig.dispose(); + sinon.restore(); + }); + }); + + describe("# inspect getter when using profile from env", () => { + const TEST_PROFILE = "testProfile"; + + beforeEach(() => { + process.env.ASK_ACCESS_TOKEN = "testAccessTokenFromEnv"; + process.env.ASK_REFRESH_TOKEN = "testRefreshTokenFromEnv"; + process.env.ASK_VENDOR_ID = "testVendorIdFromEnv"; + sinon.stub(profileHelper, "isEnvProfile").returns(true); + new AppConfig(); + }); + + it("| should get tokens with values from env variables", () => { + const token = AppConfig.getInstance().getToken(TEST_PROFILE); + expect(token.access_token).eql(process.env.ASK_ACCESS_TOKEN); + expect(token.refresh_token).eql(process.env.ASK_REFRESH_TOKEN); + }); + + it("| should get vendor id from env variable", () => { + const vendorId = AppConfig.getInstance().getVendorId(TEST_PROFILE); + expect(vendorId).eql(process.env.ASK_VENDOR_ID); + }); + + afterEach(() => { + delete process.env.ASK_ACCESS_TOKEN; + delete process.env.ASK_REFRESH_TOKEN; + delete process.env.ASK_VENDOR_ID; + AppConfig.dispose(); + sinon.restore(); + }); + }); + + describe("# inspect correctness of getProfilesList", () => { + it("| test with empty profiles config file, expect empty array", () => { + // setup + new AppConfig(APP_CONFIG_NO_PROFILES_PATH); + + // call & verify + expect(AppConfig.getInstance().getProfilesList().length).to.equal(0); + }); + + it("| test with valid profiles config file, expect array of objects", () => { + // setup + new AppConfig(APP_CONFIG_PATH); + + // call & verify + expect(AppConfig.getInstance().getProfilesList().length).to.equal(2); + expect(AppConfig.getInstance().getProfilesList()).to.deep.equal([ + {askProfile: "testProfile", awsProfile: "awsProfile"}, + {askProfile: "default", awsProfile: "default"}, + ]); + }); + + afterEach(() => { + AppConfig.dispose(); + }); + }); + + describe("# inspect correctness of configFileExists", () => { + it("| returns true if config file exists", () => { + sinon.stub(fs, "existsSync").returns(true); + + expect(AppConfig.configFileExists()).to.equal(true); + }); + + it("| returns false if config file does not exist", () => { + sinon.stub(fs, "existsSync").returns(false); + + expect(AppConfig.configFileExists()).to.equal(false); + }); + + afterEach(() => { + sinon.restore(); + }); + }); }); diff --git a/test/unit/model/build-status-local-cache-test.ts b/test/unit/model/build-status-local-cache-test.ts new file mode 100644 index 00000000..8be07be6 --- /dev/null +++ b/test/unit/model/build-status-local-cache-test.ts @@ -0,0 +1,158 @@ +import {expect} from "chai"; +import {BuildStatusLocalCache, BuildStatusLocalCacheEntry} from "../../../lib/model/build-status-local-cache"; +import {ImportBuildStatus} from "../../../lib/model/import-status"; +import {BuildDetailStep, BuildLocale, BuildStatus, BuildType} from "../../../lib/model/skill-status"; + +describe("BuildStatusLocalCache ", () => { + const LOCALE1: BuildLocale = BuildLocale["en-GB"]; + const LOCALE2: BuildLocale = BuildLocale["en-US"]; + const BUILD_TYPE1: BuildType = "ALEXA_CONVERSATIONS_QUICK_BUILD"; + const BUILD_TYPE2: BuildType = "ALEXA_CONVERSATIONS_FULL_BUILD"; + const BUILD_STATUS1: BuildStatus = "SUCCEEDED"; + const BUILD_STATUS2: BuildStatus = "FAILED"; + const IMPORT_BUILD_STATUS1: ImportBuildStatus = "IN_PROGRESS"; + const IMPORT_BUILD_STATUS2: ImportBuildStatus = "FAILED"; + const BUILD_DETAIL_STEP_1: BuildDetailStep = new BuildDetailStep(BUILD_TYPE1, BUILD_STATUS1); + const BUILD_DETAIL_STEP_2: BuildDetailStep = new BuildDetailStep(BUILD_TYPE2, BUILD_STATUS2); + + it("constructor initializes a class object", () => { + const obj: BuildStatusLocalCache = new BuildStatusLocalCache(); + expect(obj).to.be.instanceOf(BuildStatusLocalCache); + }); + + describe("get", () => { + let localCache: BuildStatusLocalCache; + + beforeEach(() => { + localCache = new BuildStatusLocalCache(); + localCache.set(LOCALE1, IMPORT_BUILD_STATUS1); + localCache.get(LOCALE1).setBuildDetailStep(BUILD_DETAIL_STEP_1); + }); + + it("get when no object in the local cache", () => { + expect(localCache.get(LOCALE2)).equal(undefined); + }); + + it("get when object is in the local cache", () => { + const result: BuildStatusLocalCacheEntry = localCache.get(LOCALE1); + expect(result.getBuildDetailStep(BUILD_TYPE1)).not.equal(undefined); + expect(result.getBuildDetailStep(BUILD_TYPE1).buildType).equal(BUILD_TYPE1); + expect(result.getBuildDetailStep(BUILD_TYPE1).buildStatus).equal(BUILD_STATUS1); + expect(result.getBuildDetailStep(BUILD_TYPE1).isACBuildType).equal(true); + }); + + it("isACBuildType", () => { + const nonACBuildType = "LANGUAGE_MODEL_FULL_BUILD"; + localCache.get(LOCALE1).setBuildDetailStep(new BuildDetailStep(nonACBuildType, BUILD_STATUS2)); + + const result: BuildStatusLocalCacheEntry = localCache.get(LOCALE1); + expect(result.getBuildDetailStep(nonACBuildType)).not.equal(undefined); + expect(result.getBuildDetailStep(nonACBuildType).buildType).equal(nonACBuildType); + expect(result.getBuildDetailStep(nonACBuildType).buildStatus).equal(BUILD_STATUS2); + expect(result.getBuildDetailStep(nonACBuildType).isACBuildType).equal(false); + }); + }); + + describe("set", () => { + let localCache: BuildStatusLocalCache; + + beforeEach(() => { + localCache = new BuildStatusLocalCache(); + }); + + it("inserts multiple local cache entries", () => { + localCache.set(LOCALE1, IMPORT_BUILD_STATUS1); + localCache.get(LOCALE1).setBuildDetailStep(new BuildDetailStep(BUILD_TYPE1, BUILD_STATUS1)); + localCache.set(LOCALE2, IMPORT_BUILD_STATUS2); + localCache.get(LOCALE2).setBuildDetailStep(new BuildDetailStep(BUILD_TYPE2, BUILD_STATUS2)); + + let result: BuildStatusLocalCacheEntry = localCache.get(LOCALE1); + expect(result.getBuildDetailStep(BUILD_TYPE1).buildStatus).equal(BUILD_STATUS1); + expect(result.getBuildDetailStep(BUILD_TYPE1).buildType).equal(BUILD_TYPE1); + expect(result.getBuildDetailStep(BUILD_TYPE1).isACBuildType).equal(true); + + result = localCache.get(LOCALE2); + expect(result.getBuildDetailStep(BUILD_TYPE2).buildStatus).equal(BUILD_STATUS2); + expect(result.getBuildDetailStep(BUILD_TYPE2).buildType).equal(BUILD_TYPE2); + expect(result.getBuildDetailStep(BUILD_TYPE2).isACBuildType).equal(true); + }); + }); + + describe("BuildStatusLocalCacheEntry", () => { + let localCacheEntry: BuildStatusLocalCacheEntry; + + beforeEach(() => { + localCacheEntry = new BuildStatusLocalCacheEntry(IMPORT_BUILD_STATUS1); + localCacheEntry.setBuildDetailStep(BUILD_DETAIL_STEP_1); + }); + + describe("getBuildDetailStep", () => { + it("returns the buildDetailStep", () => { + const entry: BuildDetailStep = localCacheEntry.getBuildDetailStep(BUILD_TYPE1); + expect(entry).not.eql(undefined); + expect(entry.buildType).eql(BUILD_TYPE1); + expect(entry.buildStatus).eql(BUILD_STATUS1); + expect(entry.isACBuildType).eql(true); + }); + + it("with missing input returns undefined", () => { + const entry: BuildDetailStep = localCacheEntry.getBuildDetailStep(BUILD_TYPE2); + expect(entry).eql(undefined); + }); + }); + + describe("setBuildDetailStep", () => { + it("can set multiple entries", () => { + localCacheEntry.setBuildDetailStep(BUILD_DETAIL_STEP_2); + let entry: BuildDetailStep = localCacheEntry.getBuildDetailStep(BUILD_TYPE1); + expect(entry).not.eql(undefined); + expect(entry.buildType).eql(BUILD_TYPE1); + expect(entry.buildStatus).eql(BUILD_STATUS1); + expect(entry.isACBuildType).eql(true); + + entry = localCacheEntry.getBuildDetailStep(BUILD_TYPE2); + expect(entry).not.eql(undefined); + expect(entry.buildType).eql(BUILD_TYPE2); + expect(entry.buildStatus).eql(BUILD_STATUS2); + expect(entry.isACBuildType).eql(true); + }); + + it("can override entries", () => { + let entry: BuildDetailStep = localCacheEntry.getBuildDetailStep(BUILD_TYPE1); + expect(entry.buildStatus).eql(BUILD_STATUS1); + + const updatedBuildDetailStep1: BuildDetailStep = new BuildDetailStep(BUILD_TYPE1, BUILD_STATUS2); + localCacheEntry.setBuildDetailStep(updatedBuildDetailStep1); + entry = localCacheEntry.getBuildDetailStep(BUILD_TYPE1); + + expect(entry.buildType).eql(BUILD_TYPE1); + expect(entry.buildStatus).eql(BUILD_STATUS2); + expect(entry.isACBuildType).eql(true); + }); + }); + + describe("ImportStatus", () => { + it("returns initial import status passed to the constructor", () => { + expect(localCacheEntry.getImportStatus()).eql(IMPORT_BUILD_STATUS1); + }); + + it("can be updated", () => { + expect(localCacheEntry.getImportStatus()).eql(IMPORT_BUILD_STATUS1); + localCacheEntry.setImportStatus(IMPORT_BUILD_STATUS2); + expect(localCacheEntry.getImportStatus()).eql(IMPORT_BUILD_STATUS2); + }); + }); + + describe("hasBuildStarted", () => { + it("when no build status specified", () => { + localCacheEntry.setImportStatus(undefined as unknown as ImportBuildStatus); + expect(localCacheEntry.hasBuildStarted()).to.be.false; + }); + + it("when any kind of build status is specified", () => { + localCacheEntry.setImportStatus("anything" as unknown as ImportBuildStatus); + expect(localCacheEntry.hasBuildStarted()).to.be.true; + }); + }); + }); +}); diff --git a/test/unit/model/build-status-local-cache.test.ts b/test/unit/model/build-status-local-cache.test.ts new file mode 100644 index 00000000..8be07be6 --- /dev/null +++ b/test/unit/model/build-status-local-cache.test.ts @@ -0,0 +1,158 @@ +import {expect} from "chai"; +import {BuildStatusLocalCache, BuildStatusLocalCacheEntry} from "../../../lib/model/build-status-local-cache"; +import {ImportBuildStatus} from "../../../lib/model/import-status"; +import {BuildDetailStep, BuildLocale, BuildStatus, BuildType} from "../../../lib/model/skill-status"; + +describe("BuildStatusLocalCache ", () => { + const LOCALE1: BuildLocale = BuildLocale["en-GB"]; + const LOCALE2: BuildLocale = BuildLocale["en-US"]; + const BUILD_TYPE1: BuildType = "ALEXA_CONVERSATIONS_QUICK_BUILD"; + const BUILD_TYPE2: BuildType = "ALEXA_CONVERSATIONS_FULL_BUILD"; + const BUILD_STATUS1: BuildStatus = "SUCCEEDED"; + const BUILD_STATUS2: BuildStatus = "FAILED"; + const IMPORT_BUILD_STATUS1: ImportBuildStatus = "IN_PROGRESS"; + const IMPORT_BUILD_STATUS2: ImportBuildStatus = "FAILED"; + const BUILD_DETAIL_STEP_1: BuildDetailStep = new BuildDetailStep(BUILD_TYPE1, BUILD_STATUS1); + const BUILD_DETAIL_STEP_2: BuildDetailStep = new BuildDetailStep(BUILD_TYPE2, BUILD_STATUS2); + + it("constructor initializes a class object", () => { + const obj: BuildStatusLocalCache = new BuildStatusLocalCache(); + expect(obj).to.be.instanceOf(BuildStatusLocalCache); + }); + + describe("get", () => { + let localCache: BuildStatusLocalCache; + + beforeEach(() => { + localCache = new BuildStatusLocalCache(); + localCache.set(LOCALE1, IMPORT_BUILD_STATUS1); + localCache.get(LOCALE1).setBuildDetailStep(BUILD_DETAIL_STEP_1); + }); + + it("get when no object in the local cache", () => { + expect(localCache.get(LOCALE2)).equal(undefined); + }); + + it("get when object is in the local cache", () => { + const result: BuildStatusLocalCacheEntry = localCache.get(LOCALE1); + expect(result.getBuildDetailStep(BUILD_TYPE1)).not.equal(undefined); + expect(result.getBuildDetailStep(BUILD_TYPE1).buildType).equal(BUILD_TYPE1); + expect(result.getBuildDetailStep(BUILD_TYPE1).buildStatus).equal(BUILD_STATUS1); + expect(result.getBuildDetailStep(BUILD_TYPE1).isACBuildType).equal(true); + }); + + it("isACBuildType", () => { + const nonACBuildType = "LANGUAGE_MODEL_FULL_BUILD"; + localCache.get(LOCALE1).setBuildDetailStep(new BuildDetailStep(nonACBuildType, BUILD_STATUS2)); + + const result: BuildStatusLocalCacheEntry = localCache.get(LOCALE1); + expect(result.getBuildDetailStep(nonACBuildType)).not.equal(undefined); + expect(result.getBuildDetailStep(nonACBuildType).buildType).equal(nonACBuildType); + expect(result.getBuildDetailStep(nonACBuildType).buildStatus).equal(BUILD_STATUS2); + expect(result.getBuildDetailStep(nonACBuildType).isACBuildType).equal(false); + }); + }); + + describe("set", () => { + let localCache: BuildStatusLocalCache; + + beforeEach(() => { + localCache = new BuildStatusLocalCache(); + }); + + it("inserts multiple local cache entries", () => { + localCache.set(LOCALE1, IMPORT_BUILD_STATUS1); + localCache.get(LOCALE1).setBuildDetailStep(new BuildDetailStep(BUILD_TYPE1, BUILD_STATUS1)); + localCache.set(LOCALE2, IMPORT_BUILD_STATUS2); + localCache.get(LOCALE2).setBuildDetailStep(new BuildDetailStep(BUILD_TYPE2, BUILD_STATUS2)); + + let result: BuildStatusLocalCacheEntry = localCache.get(LOCALE1); + expect(result.getBuildDetailStep(BUILD_TYPE1).buildStatus).equal(BUILD_STATUS1); + expect(result.getBuildDetailStep(BUILD_TYPE1).buildType).equal(BUILD_TYPE1); + expect(result.getBuildDetailStep(BUILD_TYPE1).isACBuildType).equal(true); + + result = localCache.get(LOCALE2); + expect(result.getBuildDetailStep(BUILD_TYPE2).buildStatus).equal(BUILD_STATUS2); + expect(result.getBuildDetailStep(BUILD_TYPE2).buildType).equal(BUILD_TYPE2); + expect(result.getBuildDetailStep(BUILD_TYPE2).isACBuildType).equal(true); + }); + }); + + describe("BuildStatusLocalCacheEntry", () => { + let localCacheEntry: BuildStatusLocalCacheEntry; + + beforeEach(() => { + localCacheEntry = new BuildStatusLocalCacheEntry(IMPORT_BUILD_STATUS1); + localCacheEntry.setBuildDetailStep(BUILD_DETAIL_STEP_1); + }); + + describe("getBuildDetailStep", () => { + it("returns the buildDetailStep", () => { + const entry: BuildDetailStep = localCacheEntry.getBuildDetailStep(BUILD_TYPE1); + expect(entry).not.eql(undefined); + expect(entry.buildType).eql(BUILD_TYPE1); + expect(entry.buildStatus).eql(BUILD_STATUS1); + expect(entry.isACBuildType).eql(true); + }); + + it("with missing input returns undefined", () => { + const entry: BuildDetailStep = localCacheEntry.getBuildDetailStep(BUILD_TYPE2); + expect(entry).eql(undefined); + }); + }); + + describe("setBuildDetailStep", () => { + it("can set multiple entries", () => { + localCacheEntry.setBuildDetailStep(BUILD_DETAIL_STEP_2); + let entry: BuildDetailStep = localCacheEntry.getBuildDetailStep(BUILD_TYPE1); + expect(entry).not.eql(undefined); + expect(entry.buildType).eql(BUILD_TYPE1); + expect(entry.buildStatus).eql(BUILD_STATUS1); + expect(entry.isACBuildType).eql(true); + + entry = localCacheEntry.getBuildDetailStep(BUILD_TYPE2); + expect(entry).not.eql(undefined); + expect(entry.buildType).eql(BUILD_TYPE2); + expect(entry.buildStatus).eql(BUILD_STATUS2); + expect(entry.isACBuildType).eql(true); + }); + + it("can override entries", () => { + let entry: BuildDetailStep = localCacheEntry.getBuildDetailStep(BUILD_TYPE1); + expect(entry.buildStatus).eql(BUILD_STATUS1); + + const updatedBuildDetailStep1: BuildDetailStep = new BuildDetailStep(BUILD_TYPE1, BUILD_STATUS2); + localCacheEntry.setBuildDetailStep(updatedBuildDetailStep1); + entry = localCacheEntry.getBuildDetailStep(BUILD_TYPE1); + + expect(entry.buildType).eql(BUILD_TYPE1); + expect(entry.buildStatus).eql(BUILD_STATUS2); + expect(entry.isACBuildType).eql(true); + }); + }); + + describe("ImportStatus", () => { + it("returns initial import status passed to the constructor", () => { + expect(localCacheEntry.getImportStatus()).eql(IMPORT_BUILD_STATUS1); + }); + + it("can be updated", () => { + expect(localCacheEntry.getImportStatus()).eql(IMPORT_BUILD_STATUS1); + localCacheEntry.setImportStatus(IMPORT_BUILD_STATUS2); + expect(localCacheEntry.getImportStatus()).eql(IMPORT_BUILD_STATUS2); + }); + }); + + describe("hasBuildStarted", () => { + it("when no build status specified", () => { + localCacheEntry.setImportStatus(undefined as unknown as ImportBuildStatus); + expect(localCacheEntry.hasBuildStarted()).to.be.false; + }); + + it("when any kind of build status is specified", () => { + localCacheEntry.setImportStatus("anything" as unknown as ImportBuildStatus); + expect(localCacheEntry.hasBuildStarted()).to.be.true; + }); + }); + }); +}); diff --git a/test/unit/model/dialog-replay-file-test.js b/test/unit/model/dialog-replay-file-test.js index 71071c9b..abd66a8f 100644 --- a/test/unit/model/dialog-replay-file-test.js +++ b/test/unit/model/dialog-replay-file-test.js @@ -1,252 +1,253 @@ -const { expect } = require('chai'); -const fs = require('fs-extra'); -const path = require('path'); -const sinon = require('sinon'); - -const DialogReplayFile = require('@src/model/dialog-replay-file'); - -describe('Model test - dialog replay file test', () => { - let dialogReplayFile; - const TEST_ERROR = 'error'; - const DIALOG_FIXTURE_PATH = path.join(process.cwd(), 'test', 'unit', 'fixture', 'model', 'dialog'); - const DIALOG_REPLAY_FILE_JSON_PATH = path.join(DIALOG_FIXTURE_PATH, 'dialog-replay-file.json'); - const FIXTURE_PATH = path.join(process.cwd(), 'test', 'unit', 'fixture', 'model'); - const NOT_EXISTING_DIALOG_REPLAY_FILE_PATH = path.join(FIXTURE_PATH, 'out-of-noWhere.json'); - const INVALID_JSON_DIALOG_REPLAY_FILE_PATH = path.join(FIXTURE_PATH, 'invalid-json.json'); - - describe('# test constructor', () => { - it('| constructor with non-existing file expect to catch error', () => { - try { - // setup & call - dialogReplayFile = new DialogReplayFile(NOT_EXISTING_DIALOG_REPLAY_FILE_PATH); - throw new Error('No error caught but supposed to throw an error when new.'); - } catch (err) { - // verify - const expectedError = `File ${NOT_EXISTING_DIALOG_REPLAY_FILE_PATH} not exists.`; - expect(err.endsWith(expectedError)).equal(true); - } - }); +const {expect} = require("chai"); +const fs = require("fs-extra"); +const path = require("path"); +const sinon = require("sinon"); + +const DialogReplayFile = require("../../../lib/model/dialog-replay-file"); + +describe("Model test - dialog replay file test", () => { + let dialogReplayFile; + const TEST_ERROR = "error"; + const DIALOG_FIXTURE_PATH = path.join(process.cwd(), "test", "unit", "fixture", "model", "dialog"); + const DIALOG_REPLAY_FILE_JSON_PATH = path.join(DIALOG_FIXTURE_PATH, "dialog-replay-file.json"); + const FIXTURE_PATH = path.join(process.cwd(), "test", "unit", "fixture", "model"); + const NOT_EXISTING_DIALOG_REPLAY_FILE_PATH = path.join(FIXTURE_PATH, "out-of-noWhere.json"); + const INVALID_JSON_DIALOG_REPLAY_FILE_PATH = path.join(FIXTURE_PATH, "invalid-json.json"); + + describe("# test constructor", () => { + it("| constructor with non-existing file expect to catch error", () => { + try { + // setup & call + dialogReplayFile = new DialogReplayFile(NOT_EXISTING_DIALOG_REPLAY_FILE_PATH); + throw new Error("No error caught but supposed to throw an error when new."); + } catch (err) { + // verify + const expectedError = `File ${NOT_EXISTING_DIALOG_REPLAY_FILE_PATH} not exists.`; + expect(err.endsWith(expectedError)).equal(true); + } + }); - it('| constructor with existing JSON file reads successfully', () => { - // setup - const TEST_CONTENT = JSON.parse(fs.readFileSync(DIALOG_REPLAY_FILE_JSON_PATH)); + it("| constructor with existing JSON file reads successfully", () => { + // setup + const TEST_CONTENT = JSON.parse(fs.readFileSync(DIALOG_REPLAY_FILE_JSON_PATH)); - // call - dialogReplayFile = new DialogReplayFile(DIALOG_REPLAY_FILE_JSON_PATH); + // call + dialogReplayFile = new DialogReplayFile(DIALOG_REPLAY_FILE_JSON_PATH); - // verify - expect(dialogReplayFile.content).deep.equal(TEST_CONTENT); - }); + // verify + expect(dialogReplayFile.content).deep.equal(TEST_CONTENT); + }); - it('| make sure DialogReplayFile class is singleton', () => { - // setup & call - const dialogConfig1 = new DialogReplayFile(DIALOG_REPLAY_FILE_JSON_PATH); - const dialogConfig2 = new DialogReplayFile(DIALOG_REPLAY_FILE_JSON_PATH); + it("| make sure DialogReplayFile class is singleton", () => { + // setup & call + const dialogConfig1 = new DialogReplayFile(DIALOG_REPLAY_FILE_JSON_PATH); + const dialogConfig2 = new DialogReplayFile(DIALOG_REPLAY_FILE_JSON_PATH); - // verify - expect(dialogConfig1 === dialogConfig2); - }); + // verify + expect(dialogConfig1 === dialogConfig2); + }); - afterEach(() => { - dialogReplayFile = null; - }); + afterEach(() => { + dialogReplayFile = null; }); + }); - describe('# test getter methods', () => { - const TEST_CONTENT = JSON.parse(fs.readFileSync(DIALOG_REPLAY_FILE_JSON_PATH)); + describe("# test getter methods", () => { + const TEST_CONTENT = JSON.parse(fs.readFileSync(DIALOG_REPLAY_FILE_JSON_PATH)); - before(() => { - dialogReplayFile = new DialogReplayFile(DIALOG_REPLAY_FILE_JSON_PATH); - }); + before(() => { + dialogReplayFile = new DialogReplayFile(DIALOG_REPLAY_FILE_JSON_PATH); + }); - it('| test getSkillId', () => { - // setup & call - const res = dialogReplayFile.getSkillId(); + it("| test getSkillId", () => { + // setup & call + const res = dialogReplayFile.getSkillId(); - // verify - expect(res).equal(TEST_CONTENT.skillId); - }); + // verify + expect(res).equal(TEST_CONTENT.skillId); + }); - it('| test getLocale', () => { - // setup & call - const res = dialogReplayFile.getLocale(); + it("| test getLocale", () => { + // setup & call + const res = dialogReplayFile.getLocale(); - // verify - expect(res).equal(TEST_CONTENT.locale); - }); + // verify + expect(res).equal(TEST_CONTENT.locale); + }); - it('| test getType', () => { - // setup & call - const res = dialogReplayFile.getType(); + it("| test getType", () => { + // setup & call + const res = dialogReplayFile.getType(); - // verify - expect(res).equal(TEST_CONTENT.type); - }); + // verify + expect(res).equal(TEST_CONTENT.type); + }); - it('| test getUserInput', () => { - // setup & call - const res = dialogReplayFile.getUserInput(); + it("| test getUserInput", () => { + // setup & call + const res = dialogReplayFile.getUserInput(); - // verify - expect(res).deep.equal(TEST_CONTENT.userInput); - }); + // verify + expect(res).deep.equal(TEST_CONTENT.userInput); + }); - after(() => { - dialogReplayFile = null; - }); + after(() => { + dialogReplayFile = null; }); + }); - describe('# test setter methods', () => { - before(() => { - dialogReplayFile = new DialogReplayFile(DIALOG_REPLAY_FILE_JSON_PATH); - }); + describe("# test setter methods", () => { + before(() => { + dialogReplayFile = new DialogReplayFile(DIALOG_REPLAY_FILE_JSON_PATH); + }); - after(() => { - dialogReplayFile = null; - }); + after(() => { + dialogReplayFile = null; + }); - it('| test setSkillId', () => { - // setup - const TEST_SKILLID = 'TEST_SKILLID'; - dialogReplayFile.setSkillId(TEST_SKILLID); + it("| test setSkillId", () => { + // setup + const TEST_SKILLID = "TEST_SKILLID"; + dialogReplayFile.setSkillId(TEST_SKILLID); - // call - const res = dialogReplayFile.getSkillId(); + // call + const res = dialogReplayFile.getSkillId(); - // verify - expect(res).equal(TEST_SKILLID); - }); + // verify + expect(res).equal(TEST_SKILLID); + }); - it('| test setLocale', () => { - // setup - const TEST_LOCALE = 'TEST_LOCALE'; - dialogReplayFile.setLocale(TEST_LOCALE); + it("| test setLocale", () => { + // setup + const TEST_LOCALE = "TEST_LOCALE"; + dialogReplayFile.setLocale(TEST_LOCALE); - // call - const res = dialogReplayFile.getLocale(); + // call + const res = dialogReplayFile.getLocale(); - // verify - expect(res).equal(TEST_LOCALE); - }); + // verify + expect(res).equal(TEST_LOCALE); + }); - it('| test setType', () => { - // setup - const TEST_TYPE = 'TEST_TYPE'; - dialogReplayFile.setType(TEST_TYPE); + it("| test setType", () => { + // setup + const TEST_TYPE = "TEST_TYPE"; + dialogReplayFile.setType(TEST_TYPE); - // call - const res = dialogReplayFile.getType(); + // call + const res = dialogReplayFile.getType(); - // verify - expect(res).equal(TEST_TYPE); - }); + // verify + expect(res).equal(TEST_TYPE); + }); - it('| test setUserInput', () => { - // setup - const TEST_USER_INPUT = ['TEST', 'USER', 'INPUT']; - dialogReplayFile.setUserInput(TEST_USER_INPUT); + it("| test setUserInput", () => { + // setup + const TEST_USER_INPUT = ["TEST", "USER", "INPUT"]; + dialogReplayFile.setUserInput(TEST_USER_INPUT); - // call - const res = dialogReplayFile.getUserInput(); + // call + const res = dialogReplayFile.getUserInput(); - // verify - expect(res).deep.equal(TEST_USER_INPUT); - }); + // verify + expect(res).deep.equal(TEST_USER_INPUT); + }); - describe('# test read file content', () => { - afterEach(() => { - dialogReplayFile = null; - sinon.restore(); - }); - - it('| throws error if input file path does not exist', () => { - try { - // setup and call - dialogReplayFile = new DialogReplayFile(NOT_EXISTING_DIALOG_REPLAY_FILE_PATH); - } catch (error) { - // verify - expect(error).equal(`Failed to parse file: ${NOT_EXISTING_DIALOG_REPLAY_FILE_PATH}.` - + `\nFile ${NOT_EXISTING_DIALOG_REPLAY_FILE_PATH} not exists.`); - } - }); - - it('| throws error if READ permission is not granted', () => { - // setup - sinon.stub(fs, 'accessSync').throws(new Error(TEST_ERROR)); - try { - // call - dialogReplayFile = new DialogReplayFile(INVALID_JSON_DIALOG_REPLAY_FILE_PATH); - } catch (error) { - // verify - expect(error).equal(`Failed to parse file: ${INVALID_JSON_DIALOG_REPLAY_FILE_PATH}.` - + `\n${TEST_ERROR}`); - } - }); - - it('| test JSON file path extension', () => { - // setup - sinon.stub(fs, 'readJsonSync').returns({ skillId: 'amzn1.ask.skill.1234567890' }); - - // call - dialogReplayFile = new DialogReplayFile(DIALOG_REPLAY_FILE_JSON_PATH); - - // verify - expect(dialogReplayFile.content).deep.equal({ - skillId: 'amzn1.ask.skill.1234567890' - }); - }); - }); + describe("# test read file content", () => { + afterEach(() => { + dialogReplayFile = null; + sinon.restore(); + }); + + it("| throws error if input file path does not exist", () => { + try { + // setup and call + dialogReplayFile = new DialogReplayFile(NOT_EXISTING_DIALOG_REPLAY_FILE_PATH); + } catch (error) { + // verify + expect(error).equal( + `Failed to parse file: ${NOT_EXISTING_DIALOG_REPLAY_FILE_PATH}.` + `\nFile ${NOT_EXISTING_DIALOG_REPLAY_FILE_PATH} not exists.`, + ); + } + }); + + it("| throws error if READ permission is not granted", () => { + // setup + sinon.stub(fs, "accessSync").throws(new Error(TEST_ERROR)); + try { + // call + dialogReplayFile = new DialogReplayFile(INVALID_JSON_DIALOG_REPLAY_FILE_PATH); + } catch (error) { + // verify + expect(error).equal(`Failed to parse file: ${INVALID_JSON_DIALOG_REPLAY_FILE_PATH}.` + `\n${TEST_ERROR}`); + } + }); + + it("| test JSON file path extension", () => { + // setup + sinon.stub(fs, "readJsonSync").returns({skillId: "amzn1.ask.skill.1234567890"}); + + // call + dialogReplayFile = new DialogReplayFile(DIALOG_REPLAY_FILE_JSON_PATH); + + // verify + expect(dialogReplayFile.content).deep.equal({ + skillId: "amzn1.ask.skill.1234567890", + }); + }); + }); - describe('# test write file content', () => { - beforeEach(() => { - sinon.stub(DialogReplayFile.prototype, 'readFileContent').returns({}); - }); - - afterEach(() => { - dialogReplayFile = null; - sinon.restore(); - }); - - it('| throws error if input file path does not exist', () => { - // setup - dialogReplayFile = new DialogReplayFile(NOT_EXISTING_DIALOG_REPLAY_FILE_PATH); - - try { - // call - dialogReplayFile.writeContentToFile('', NOT_EXISTING_DIALOG_REPLAY_FILE_PATH); - } catch (error) { - // verify - expect(error).equal(`Failed to write to file ${NOT_EXISTING_DIALOG_REPLAY_FILE_PATH}.` - + `\nFile ${NOT_EXISTING_DIALOG_REPLAY_FILE_PATH} not exists.`); - } - }); - - it('| throws error if WRITE permission is not granted', () => { - // setup - sinon.stub(fs, 'accessSync').throws(new Error(TEST_ERROR)); - dialogReplayFile = new DialogReplayFile(DIALOG_REPLAY_FILE_JSON_PATH); - - try { - // call - dialogReplayFile.writeContentToFile('', DIALOG_REPLAY_FILE_JSON_PATH); - } catch (error) { - // verify - expect(error).equal(`Failed to write to file ${DIALOG_REPLAY_FILE_JSON_PATH}.` - + `\n${TEST_ERROR}`); - } - }); - - it('| test JSON file path extension', () => { - // setup - const writeFileStub = sinon.stub(fs, 'writeFileSync'); - dialogReplayFile = new DialogReplayFile(DIALOG_REPLAY_FILE_JSON_PATH); - - // call - dialogReplayFile.writeContentToFile('', DIALOG_REPLAY_FILE_JSON_PATH); - - // verify - expect(writeFileStub.calledOnce).equal(true); - }); - }); + describe("# test write file content", () => { + beforeEach(() => { + sinon.stub(DialogReplayFile.prototype, "readFileContent").returns({}); + }); + + afterEach(() => { + dialogReplayFile = null; + sinon.restore(); + }); + + it("| throws error if input file path does not exist", () => { + // setup + dialogReplayFile = new DialogReplayFile(NOT_EXISTING_DIALOG_REPLAY_FILE_PATH); + + try { + // call + dialogReplayFile.writeContentToFile("", NOT_EXISTING_DIALOG_REPLAY_FILE_PATH); + } catch (error) { + // verify + expect(error).equal( + `Failed to write to file ${NOT_EXISTING_DIALOG_REPLAY_FILE_PATH}.` + + `\nFile ${NOT_EXISTING_DIALOG_REPLAY_FILE_PATH} not exists.`, + ); + } + }); + + it("| throws error if WRITE permission is not granted", () => { + // setup + sinon.stub(fs, "accessSync").throws(new Error(TEST_ERROR)); + dialogReplayFile = new DialogReplayFile(DIALOG_REPLAY_FILE_JSON_PATH); + + try { + // call + dialogReplayFile.writeContentToFile("", DIALOG_REPLAY_FILE_JSON_PATH); + } catch (error) { + // verify + expect(error).equal(`Failed to write to file ${DIALOG_REPLAY_FILE_JSON_PATH}.` + `\n${TEST_ERROR}`); + } + }); + + it("| test JSON file path extension", () => { + // setup + const writeFileStub = sinon.stub(fs, "writeFileSync"); + dialogReplayFile = new DialogReplayFile(DIALOG_REPLAY_FILE_JSON_PATH); + + // call + dialogReplayFile.writeContentToFile("", DIALOG_REPLAY_FILE_JSON_PATH); + + // verify + expect(writeFileStub.calledOnce).equal(true); + }); }); + }); }); diff --git a/test/unit/model/dialog-save-skill-io-file-test.js b/test/unit/model/dialog-save-skill-io-file-test.js index 7f3cccdf..84130bea 100644 --- a/test/unit/model/dialog-save-skill-io-file-test.js +++ b/test/unit/model/dialog-save-skill-io-file-test.js @@ -1,65 +1,65 @@ -const { expect } = require('chai'); -const sinon = require('sinon'); -const fs = require('fs-extra'); -const jsonView = require('@src/view/json-view'); -const DialogSaveSkillIoFile = require('@src/model/dialog-save-skill-io-file'); +const {expect} = require("chai"); +const sinon = require("sinon"); +const fs = require("fs-extra"); +const jsonView = require("../../../lib/view/json-view"); +const DialogSaveSkillIoFile = require("../../../lib/model/dialog-save-skill-io-file"); -describe('Model test - dialog output file test', () => { - const outputFilePath = 'somePath'; - let writeFileStub; - beforeEach(() => { - writeFileStub = sinon.stub(fs, 'writeFileSync'); - }); +describe("Model test - dialog output file test", () => { + const outputFilePath = "somePath"; + let writeFileStub; + beforeEach(() => { + writeFileStub = sinon.stub(fs, "writeFileSync"); + }); - it('| should write dialog history to a file', () => { - const dialogOutputFile = new DialogSaveSkillIoFile(outputFilePath); + it("| should write dialog history to a file", () => { + const dialogOutputFile = new DialogSaveSkillIoFile(outputFilePath); - dialogOutputFile.startInvocation({ someItem: 'some start item' }); - dialogOutputFile.endInvocation({ someItem: 'some end item' }); - dialogOutputFile.startInvocation({ someItem: 'another start item' }); - dialogOutputFile.endInvocation({ someItem: 'another end item' }); + dialogOutputFile.startInvocation({someItem: "some start item"}); + dialogOutputFile.endInvocation({someItem: "some end item"}); + dialogOutputFile.startInvocation({someItem: "another start item"}); + dialogOutputFile.endInvocation({someItem: "another end item"}); - dialogOutputFile.save(); + dialogOutputFile.save(); - const expectedContent = { - invocations: [ - { - request: { - someItem: 'some start item' - }, - response: { - someItem: 'some end item' - } - }, - { - request: { - someItem: 'another start item' - }, - response: { - someItem: 'another end item' - } - } - ] - }; + const expectedContent = { + invocations: [ + { + request: { + someItem: "some start item", + }, + response: { + someItem: "some end item", + }, + }, + { + request: { + someItem: "another start item", + }, + response: { + someItem: "another end item", + }, + }, + ], + }; - expect(dialogOutputFile).to.be.instanceof(DialogSaveSkillIoFile); - expect(writeFileStub.callCount).eq(1); - expect(writeFileStub.args[0][0]).eq(outputFilePath); - expect(writeFileStub.args[0][1]).eq(jsonView.toString((expectedContent))); - }); + expect(dialogOutputFile).to.be.instanceof(DialogSaveSkillIoFile); + expect(writeFileStub.callCount).eq(1); + expect(writeFileStub.args[0][0]).eq(outputFilePath); + expect(writeFileStub.args[0][1]).eq(jsonView.toString(expectedContent)); + }); - it('| should not write to file if no output path provided', () => { - const dialogOutputFile = new DialogSaveSkillIoFile(); + it("| should not write to file if no output path provided", () => { + const dialogOutputFile = new DialogSaveSkillIoFile(); - dialogOutputFile.endInvocation({ someItem: 'some end item' }); + dialogOutputFile.endInvocation({someItem: "some end item"}); - dialogOutputFile.save(); + dialogOutputFile.save(); - expect(dialogOutputFile).to.be.instanceof(DialogSaveSkillIoFile); - expect(writeFileStub.callCount).eq(0); - }); + expect(dialogOutputFile).to.be.instanceof(DialogSaveSkillIoFile); + expect(writeFileStub.callCount).eq(0); + }); - afterEach(() => { - sinon.restore(); - }); + afterEach(() => { + sinon.restore(); + }); }); diff --git a/test/unit/model/dialog/input.test.ts b/test/unit/model/dialog/input.test.ts new file mode 100644 index 00000000..6c7de379 --- /dev/null +++ b/test/unit/model/dialog/input.test.ts @@ -0,0 +1,18 @@ +import {expect} from "chai"; +import {inputToCommand, SpecialCommand} from "../../../../lib/model/dialog/inputs"; + +describe("Dialog Model - Input Helpers", () => { + describe("input to command", () => { + it("resolves commands from inputs", () => { + expect(inputToCommand(".quit")).equals(SpecialCommand.QUIT); + }); + + it("is case insensitive", () => { + expect(inputToCommand(".Quit")).equals(SpecialCommand.QUIT); + }); + + it("unknown commands return unknown", () => { + expect(inputToCommand(".hi")).equals(SpecialCommand.UNKNOWN); + }); + }); +}); diff --git a/test/unit/model/import-status-test.ts b/test/unit/model/import-status-test.ts new file mode 100644 index 00000000..a5b830a9 --- /dev/null +++ b/test/unit/model/import-status-test.ts @@ -0,0 +1,69 @@ +import {expect} from "chai"; +import {ImportStatus} from "../../../lib/model/import-status"; + +describe("import status", () => { + const SKILL_ID = "test.id"; + const RESOURCE1_NAME = "InteractionModel.ar-SA"; + const RESOURCE1_STATUS = "status1"; + const RESOURCE2_NAME = "InteractionModel.pt-BR"; + const RESOURCE2_STATUS = "status2"; + const SMAPI_RESPONSE = { + body: { + skill: { + skillId: SKILL_ID, + resources: [ + { + name: RESOURCE1_NAME, + status: RESOURCE1_STATUS, + }, + { + name: RESOURCE2_NAME, + status: RESOURCE2_STATUS, + }, + ], + }, + }, + }; + + describe("ImportStatus Constructor", () => { + it("when empty SMAPI response", () => { + let importStatus: ImportStatus = new ImportStatus({}); + + expect(importStatus).not.equal(null); + expect(importStatus.skillId).equal(undefined); + expect(importStatus.resources).not.equal(null); + expect(importStatus.resources.length).equal(0); + }); + + it("when empty body SMAPI response", () => { + let importStatus: ImportStatus = new ImportStatus({body: {}}); + + expect(importStatus).not.equal(null); + expect(importStatus.skillId).equal(undefined); + expect(importStatus.resources).not.equal(null); + expect(importStatus.resources.length).equal(0); + }); + + it("when empty skill SMAPI response", () => { + let importStatus: ImportStatus = new ImportStatus({body: {skill: {}}}); + + expect(importStatus).not.equal(null); + expect(importStatus.skillId).equal(undefined); + expect(importStatus.resources).not.equal(null); + expect(importStatus.resources.length).equal(0); + }); + + it("with full SMAPI response", () => { + let importStatus: ImportStatus = new ImportStatus(SMAPI_RESPONSE); + + expect(importStatus).not.equal(null); + expect(importStatus.skillId).equal(SKILL_ID); + expect(importStatus.resources).not.equal(null); + expect(importStatus.resources.length).equal(2); + expect(importStatus.resources[0].locale).equal("ar-SA"); + expect(importStatus.resources[0].status).equal(RESOURCE1_STATUS); + expect(importStatus.resources[1].locale).equal("pt-BR"); + expect(importStatus.resources[1].status).equal(RESOURCE2_STATUS); + }); + }); +}); diff --git a/test/unit/model/import-status.test.ts b/test/unit/model/import-status.test.ts new file mode 100644 index 00000000..a5b830a9 --- /dev/null +++ b/test/unit/model/import-status.test.ts @@ -0,0 +1,69 @@ +import {expect} from "chai"; +import {ImportStatus} from "../../../lib/model/import-status"; + +describe("import status", () => { + const SKILL_ID = "test.id"; + const RESOURCE1_NAME = "InteractionModel.ar-SA"; + const RESOURCE1_STATUS = "status1"; + const RESOURCE2_NAME = "InteractionModel.pt-BR"; + const RESOURCE2_STATUS = "status2"; + const SMAPI_RESPONSE = { + body: { + skill: { + skillId: SKILL_ID, + resources: [ + { + name: RESOURCE1_NAME, + status: RESOURCE1_STATUS, + }, + { + name: RESOURCE2_NAME, + status: RESOURCE2_STATUS, + }, + ], + }, + }, + }; + + describe("ImportStatus Constructor", () => { + it("when empty SMAPI response", () => { + let importStatus: ImportStatus = new ImportStatus({}); + + expect(importStatus).not.equal(null); + expect(importStatus.skillId).equal(undefined); + expect(importStatus.resources).not.equal(null); + expect(importStatus.resources.length).equal(0); + }); + + it("when empty body SMAPI response", () => { + let importStatus: ImportStatus = new ImportStatus({body: {}}); + + expect(importStatus).not.equal(null); + expect(importStatus.skillId).equal(undefined); + expect(importStatus.resources).not.equal(null); + expect(importStatus.resources.length).equal(0); + }); + + it("when empty skill SMAPI response", () => { + let importStatus: ImportStatus = new ImportStatus({body: {skill: {}}}); + + expect(importStatus).not.equal(null); + expect(importStatus.skillId).equal(undefined); + expect(importStatus.resources).not.equal(null); + expect(importStatus.resources.length).equal(0); + }); + + it("with full SMAPI response", () => { + let importStatus: ImportStatus = new ImportStatus(SMAPI_RESPONSE); + + expect(importStatus).not.equal(null); + expect(importStatus.skillId).equal(SKILL_ID); + expect(importStatus.resources).not.equal(null); + expect(importStatus.resources.length).equal(2); + expect(importStatus.resources[0].locale).equal("ar-SA"); + expect(importStatus.resources[0].status).equal(RESOURCE1_STATUS); + expect(importStatus.resources[1].locale).equal("pt-BR"); + expect(importStatus.resources[1].status).equal(RESOURCE2_STATUS); + }); + }); +}); diff --git a/test/unit/model/manifest-test.js b/test/unit/model/manifest-test.js index ea76a192..a9663acb 100644 --- a/test/unit/model/manifest-test.js +++ b/test/unit/model/manifest-test.js @@ -1,229 +1,215 @@ -const { expect } = require('chai'); -const path = require('path'); -const fs = require('fs'); - -const Manifest = require('@src/model/manifest'); - -describe('Model test - manifest file test', () => { - const FIXTURE_PATH = path.join(process.cwd(), 'test', 'unit', 'fixture', 'model'); - const MANIFEST_FILE = path.join(FIXTURE_PATH, 'manifest.json'); - - describe('# inspect correctness for constructor, getInstance and dispose', () => { - const NOT_EXISTING_PROJECT_CONFIG_PATH = path.join(FIXTURE_PATH, 'out-of-noWhere.json'); - const INVALID_JSON_PROJECT_CONFIG_PATH = path.join(FIXTURE_PATH, 'invalid-json.json'); - - it('| initiate as a Manifest class', () => { - const manifest = new Manifest(MANIFEST_FILE); - expect(manifest).to.be.instanceof(Manifest); - }); - - it('| make sure Manifest class is singleton', () => { - const manifest1 = new Manifest(MANIFEST_FILE); - const manifest2 = new Manifest(MANIFEST_FILE); - expect(manifest1 === manifest2).equal(true); - }); - - it('| get instance function return the instance constructed before', () => { - const manifest = new Manifest(MANIFEST_FILE); - expect(Manifest.getInstance() === manifest).equal(true); - }); - - it('| dispose the instance correctly', () => { - new Manifest(MANIFEST_FILE); - Manifest.dispose(); - expect(Manifest.getInstance()).equal(null); - }); - - it('| init with a file path not existing, expect correct error message thrown', () => { - try { - new Manifest(NOT_EXISTING_PROJECT_CONFIG_PATH); - throw new Error('No error caught but supposed to throw an error when new.'); - } catch (err) { - const expectedError = `File ${NOT_EXISTING_PROJECT_CONFIG_PATH} not exists.`; - expect(err.message.indexOf(expectedError) !== -1).equal(true); - } - }); - - it('| init with a file path without access permission, expect correct error message thrown', () => { - // setup - fs.chmodSync(MANIFEST_FILE, 0o111); - try { - // call - new Manifest(MANIFEST_FILE); - throw new Error('No error caught but supposed to throw an error when new.'); - } catch (err) { - // verify - const expectedError = `No access to read/write file ${MANIFEST_FILE}.`; - expect(err.message.indexOf(expectedError) !== -1).equal(true); - } finally { - // clear - fs.chmodSync(MANIFEST_FILE, 0o644); - } - }); - - it('| init with a invalid json file, expect correct error message thrown', () => { - try { - new Manifest(INVALID_JSON_PROJECT_CONFIG_PATH); - throw new Error('No error caught but supposed to throw an error when new.'); - } catch (err) { - const expectedError = `Failed to parse JSON file ${INVALID_JSON_PROJECT_CONFIG_PATH}.`; - expect(err.message.indexOf(expectedError) !== -1).equal(true); - } - }); - - afterEach(() => { - Manifest.dispose(); - }); +const {expect} = require("chai"); +const path = require("path"); +const fs = require("fs"); + +const Manifest = require("../../../lib/model/manifest"); + +describe("Model test - manifest file test", () => { + const FIXTURE_PATH = path.join(process.cwd(), "test", "unit", "fixture", "model"); + const MANIFEST_FILE = path.join(FIXTURE_PATH, "manifest.json"); + + describe("# inspect correctness for constructor, getInstance and dispose", () => { + const NOT_EXISTING_PROJECT_CONFIG_PATH = path.join(FIXTURE_PATH, "out-of-noWhere.json"); + const INVALID_JSON_PROJECT_CONFIG_PATH = path.join(FIXTURE_PATH, "invalid-json.json"); + + it("| initiate as a Manifest class", () => { + const manifest = new Manifest(MANIFEST_FILE); + expect(manifest).to.be.instanceof(Manifest); }); - describe('# inspect correctness for getter and setter for different fields', () => { - beforeEach(() => { - new Manifest(MANIFEST_FILE); - }); + it("| make sure Manifest class is singleton", () => { + const manifest1 = new Manifest(MANIFEST_FILE); + const manifest2 = new Manifest(MANIFEST_FILE); + expect(manifest1 === manifest2).equal(true); + }); - [ - { - field: 'PublishingLocales', - input: [], - newValue: 'locales new', - oldValue: { - 'de-DE': { - summary: 'one sentence description', - examplePhrases: [ - 'This is good', - 'no icon' - ], - name: 'skillName de', - description: 'skill description' - }, - 'en-US': { - summary: 'Sample Short Description', - examplePhrases: [ - 'Alexa open hello world', - 'Alexa tell hello world hello', - 'Alexa ask hello world say hello' - ], - name: 'skillName us', - description: 'Sample Full Description' - }, - 'ja-JP': { - summary: 'coniqiwa', - examplePhrases: [ - 'More to come', - 'coniqiwa' - ], - name: 'skillName jp', - description: 'coniqiwa' - } - } - }, - { - field: 'PublishingLocale', - input: ['de-DE'], - newValue: 'locale new', - oldValue: { - summary: 'one sentence description', - examplePhrases: [ - 'This is good', - 'no icon' - ], - name: 'skillName de', - description: 'skill description' - } + it("| get instance function return the instance constructed before", () => { + const manifest = new Manifest(MANIFEST_FILE); + expect(Manifest.getInstance() === manifest).equal(true); + }); + + it("| dispose the instance correctly", () => { + new Manifest(MANIFEST_FILE); + Manifest.dispose(); + expect(Manifest.getInstance()).equal(null); + }); + + it("| init with a file path not existing, expect correct error message thrown", () => { + try { + new Manifest(NOT_EXISTING_PROJECT_CONFIG_PATH); + throw new Error("No error caught but supposed to throw an error when new."); + } catch (err) { + const expectedError = `File ${NOT_EXISTING_PROJECT_CONFIG_PATH} not exists.`; + expect(err.message.indexOf(expectedError) !== -1).equal(true); + } + }); + + it("| init with a file path without access permission, expect correct error message thrown", () => { + // setup + fs.chmodSync(MANIFEST_FILE, 0o111); + try { + // call + new Manifest(MANIFEST_FILE); + throw new Error("No error caught but supposed to throw an error when new."); + } catch (err) { + // verify + const expectedError = `No access to read/write file ${MANIFEST_FILE}.`; + expect(err.message.indexOf(expectedError) !== -1).equal(true); + } finally { + // clear + fs.chmodSync(MANIFEST_FILE, 0o644); + } + }); + + it("| init with a invalid json file, expect correct error message thrown", () => { + try { + new Manifest(INVALID_JSON_PROJECT_CONFIG_PATH); + throw new Error("No error caught but supposed to throw an error when new."); + } catch (err) { + const expectedError = `Failed to parse JSON file ${INVALID_JSON_PROJECT_CONFIG_PATH}.`; + expect(err.message.indexOf(expectedError) !== -1).equal(true); + } + }); + + afterEach(() => { + Manifest.dispose(); + }); + }); + + describe("# inspect correctness for getter and setter for different fields", () => { + beforeEach(() => { + new Manifest(MANIFEST_FILE); + }); + + [ + { + field: "PublishingLocales", + input: [], + newValue: "locales new", + oldValue: { + "de-DE": { + summary: "one sentence description", + examplePhrases: ["This is good", "no icon"], + name: "skillName de", + description: "skill description", + }, + "en-US": { + summary: "Sample Short Description", + examplePhrases: ["Alexa open hello world", "Alexa tell hello world hello", "Alexa ask hello world say hello"], + name: "skillName us", + description: "Sample Full Description", + }, + "ja-JP": { + summary: "coniqiwa", + examplePhrases: ["More to come", "coniqiwa"], + name: "skillName jp", + description: "coniqiwa", + }, + }, + }, + { + field: "PublishingLocale", + input: ["de-DE"], + newValue: "locale new", + oldValue: { + summary: "one sentence description", + examplePhrases: ["This is good", "no icon"], + name: "skillName de", + description: "skill description", + }, + }, + { + field: "Apis", + input: [], + newValue: "apis new", + oldValue: { + custom: { + endpoint: { + url: "TEST_URL1", }, - { - field: 'Apis', - input: [], - newValue: 'apis new', - oldValue: { - custom: { - endpoint: { - url: 'TEST_URL1' - }, - interfaces: [{ - type: 'VIDEO_APP' - }], - regions: { - EU: { - endpoint: { - url: 'TEST_URL2' - } - } - } - } - } + interfaces: [ + { + type: "VIDEO_APP", + }, + ], + regions: { + EU: { + endpoint: { + url: "TEST_URL2", + }, + }, }, + }, + }, + }, + { + field: "ApisDomain", + input: ["custom"], + newValue: "apisDomain new", + oldValue: { + endpoint: { + url: "TEST_URL1", + }, + interfaces: [ { - field: 'ApisDomain', - input: ['custom'], - newValue: 'apisDomain new', - oldValue: { - endpoint: { - url: 'TEST_URL1' - }, - interfaces: [{ - type: 'VIDEO_APP' - }], - regions: { - EU: { - endpoint: { - url: 'TEST_URL2' - } - } - } - } + type: "VIDEO_APP", }, - { - field: 'ApisEndpointByDomainRegion', - input: ['custom', 'default'], - newValue: 'endpoint new default', - oldValue: { - url: 'TEST_URL1' - } + ], + regions: { + EU: { + endpoint: { + url: "TEST_URL2", + }, }, - { - field: 'ApisEndpointByDomainRegion', - input: ['custom', 'EU'], - newValue: 'endpoint new EU', - oldValue: { - url: 'TEST_URL2' - } - } - ].forEach(({ - field, - input, - newValue, - oldValue - }) => { - it(`test get${field} function successfully`, () => { - expect(Manifest.getInstance()[`get${field}`](...input)).deep.equal(oldValue); - }); - - it(`test set${field} function successfully`, () => { - Manifest.getInstance()[`set${field}`](...input, newValue); - expect(Manifest.getInstance()[`get${field}`](...input)).equal(newValue); - }); - }); - - afterEach(() => { - Manifest.dispose(); - }); + }, + }, + }, + { + field: "ApisEndpointByDomainRegion", + input: ["custom", "default"], + newValue: "endpoint new default", + oldValue: { + url: "TEST_URL1", + }, + }, + { + field: "ApisEndpointByDomainRegion", + input: ["custom", "EU"], + newValue: "endpoint new EU", + oldValue: { + url: "TEST_URL2", + }, + }, + ].forEach(({field, input, newValue, oldValue}) => { + it(`test get${field} function successfully`, () => { + expect(Manifest.getInstance()[`get${field}`](...input)).deep.equal(oldValue); + }); + + it(`test set${field} function successfully`, () => { + Manifest.getInstance()[`set${field}`](...input, newValue); + expect(Manifest.getInstance()[`get${field}`](...input)).equal(newValue); + }); }); - describe('# verify generic functionality of manifest file', () => { - describe('# verify function getSkillName', () => { - it('| locale en-US exists, expect use skill name by en-US', () => { - new Manifest(MANIFEST_FILE); - expect(Manifest.getInstance().getSkillName()).equal('skillName us'); - Manifest.dispose(); - }); - - it('| en-US does not exist, expect use the first locale in locale list', () => { - new Manifest(MANIFEST_FILE); - Manifest.getInstance().setPublishingLocale('en-US', undefined); - expect(Manifest.getInstance().getSkillName()).equal('skillName de'); - Manifest.dispose(); - }); - }); + afterEach(() => { + Manifest.dispose(); + }); + }); + + describe("# verify generic functionality of manifest file", () => { + describe("# verify function getSkillName", () => { + it("| locale en-US exists, expect use skill name by en-US", () => { + new Manifest(MANIFEST_FILE); + expect(Manifest.getInstance().getSkillName()).equal("skillName us"); + Manifest.dispose(); + }); + + it("| en-US does not exist, expect use the first locale in locale list", () => { + new Manifest(MANIFEST_FILE); + Manifest.getInstance().setPublishingLocale("en-US", undefined); + expect(Manifest.getInstance().getSkillName()).equal("skillName de"); + Manifest.dispose(); + }); }); + }); }); diff --git a/test/unit/model/regional-stack-file-test.js b/test/unit/model/regional-stack-file-test.js index 12523958..59cff77d 100644 --- a/test/unit/model/regional-stack-file-test.js +++ b/test/unit/model/regional-stack-file-test.js @@ -1,143 +1,143 @@ -const { expect } = require('chai'); -const path = require('path'); -const fs = require('fs'); -const jsonfile = require('jsonfile'); +const {expect} = require("chai"); +const path = require("path"); +const fs = require("fs"); +const jsonfile = require("jsonfile"); -const RegionalStackFile = require('@src/model/regional-stack-file'); +const RegionalStackFile = require("../../../lib/model/regional-stack-file"); -describe('Model test - regional stack file test', () => { - const FIXTURE_PATH = path.join(process.cwd(), 'test', 'unit', 'fixture', 'model'); - const REGIONAL_STACK_PATH = path.join(FIXTURE_PATH, 'regional-stack-file.json'); - const YAML_REGIONAL_STACK_PATH = path.join(FIXTURE_PATH, 'regional-stack-file.yaml'); +describe("Model test - regional stack file test", () => { + const FIXTURE_PATH = path.join(process.cwd(), "test", "unit", "fixture", "model"); + const REGIONAL_STACK_PATH = path.join(FIXTURE_PATH, "regional-stack-file.json"); + const YAML_REGIONAL_STACK_PATH = path.join(FIXTURE_PATH, "regional-stack-file.yaml"); - describe('# inspect correctness for constructor, getInstance and dispose', () => { - const NOT_EXISTING_PROJECT_CONFIG_PATH = path.join(FIXTURE_PATH, 'out-of-noWhere.json'); - const INVALID_JSON_PROJECT_CONFIG_PATH = path.join(FIXTURE_PATH, 'invalid-json.json'); + describe("# inspect correctness for constructor, getInstance and dispose", () => { + const NOT_EXISTING_PROJECT_CONFIG_PATH = path.join(FIXTURE_PATH, "out-of-noWhere.json"); + const INVALID_JSON_PROJECT_CONFIG_PATH = path.join(FIXTURE_PATH, "invalid-json.json"); - it('| initiate as a RegionalStackFile class', () => { - const projConfig = new RegionalStackFile(REGIONAL_STACK_PATH); - expect(projConfig).to.be.instanceof(RegionalStackFile); - }); + it("| initiate as a RegionalStackFile class", () => { + const projConfig = new RegionalStackFile(REGIONAL_STACK_PATH); + expect(projConfig).to.be.instanceof(RegionalStackFile); + }); - it('| make sure RegionalStackFile class is singleton', () => { - const config1 = new RegionalStackFile(REGIONAL_STACK_PATH); - const config2 = new RegionalStackFile(REGIONAL_STACK_PATH); - expect(config1 === config2).equal(true); - }); + it("| make sure RegionalStackFile class is singleton", () => { + const config1 = new RegionalStackFile(REGIONAL_STACK_PATH); + const config2 = new RegionalStackFile(REGIONAL_STACK_PATH); + expect(config1 === config2).equal(true); + }); - it('| make sure YAML and JSON resources config can both be created well', () => { - const yamlConfig = new RegionalStackFile(YAML_REGIONAL_STACK_PATH); - const jsonConfig = jsonfile.readFileSync(REGIONAL_STACK_PATH); - expect(yamlConfig.content).deep.equal(jsonConfig); - }); + it("| make sure YAML and JSON resources config can both be created well", () => { + const yamlConfig = new RegionalStackFile(YAML_REGIONAL_STACK_PATH); + const jsonConfig = jsonfile.readFileSync(REGIONAL_STACK_PATH); + expect(yamlConfig.content).deep.equal(jsonConfig); + }); - it('| get instance function return the instance constructed before', () => { - const projConfig = new RegionalStackFile(REGIONAL_STACK_PATH); - expect(RegionalStackFile.getInstance() === projConfig).equal(true); - }); + it("| get instance function return the instance constructed before", () => { + const projConfig = new RegionalStackFile(REGIONAL_STACK_PATH); + expect(RegionalStackFile.getInstance() === projConfig).equal(true); + }); - it('| dispose the instance correctly', () => { - new RegionalStackFile(REGIONAL_STACK_PATH); - RegionalStackFile.dispose(); - expect(RegionalStackFile.getInstance()).equal(null); - }); + it("| dispose the instance correctly", () => { + new RegionalStackFile(REGIONAL_STACK_PATH); + RegionalStackFile.dispose(); + expect(RegionalStackFile.getInstance()).equal(null); + }); - it('| init with a file path not existing, expect correct error message thrown', () => { - try { - new RegionalStackFile(NOT_EXISTING_PROJECT_CONFIG_PATH); - throw new Error('No error caught but supposed to throw an error when new.'); - } catch (err) { - const expectedError = `File ${NOT_EXISTING_PROJECT_CONFIG_PATH} not exists.`; - expect(err.message.indexOf(expectedError) !== -1).equal(true); - } - }); + it("| init with a file path not existing, expect correct error message thrown", () => { + try { + new RegionalStackFile(NOT_EXISTING_PROJECT_CONFIG_PATH); + throw new Error("No error caught but supposed to throw an error when new."); + } catch (err) { + const expectedError = `File ${NOT_EXISTING_PROJECT_CONFIG_PATH} not exists.`; + expect(err.message.indexOf(expectedError) !== -1).equal(true); + } + }); - it('| init with a file path without access permission, expect correct error message thrown', () => { - // setup - fs.chmodSync(REGIONAL_STACK_PATH, 0o111); - try { - // call - new RegionalStackFile(REGIONAL_STACK_PATH); - throw new Error('No error caught but supposed to throw an error when new.'); - } catch (err) { - // verify - const expectedError = `No access to read/write file ${REGIONAL_STACK_PATH}.`; - expect(err.message.indexOf(expectedError) !== -1).equal(true); - } finally { - // clear - fs.chmodSync(REGIONAL_STACK_PATH, 0o644); - } - }); + it("| init with a file path without access permission, expect correct error message thrown", () => { + // setup + fs.chmodSync(REGIONAL_STACK_PATH, 0o111); + try { + // call + new RegionalStackFile(REGIONAL_STACK_PATH); + throw new Error("No error caught but supposed to throw an error when new."); + } catch (err) { + // verify + const expectedError = `No access to read/write file ${REGIONAL_STACK_PATH}.`; + expect(err.message.indexOf(expectedError) !== -1).equal(true); + } finally { + // clear + fs.chmodSync(REGIONAL_STACK_PATH, 0o644); + } + }); - it('| init with a invalid json file, expect correct error message thrown', () => { - try { - new RegionalStackFile(INVALID_JSON_PROJECT_CONFIG_PATH); - throw new Error('No error caught but supposed to throw an error when new.'); - } catch (err) { - const expectedError = `Failed to parse JSON file ${INVALID_JSON_PROJECT_CONFIG_PATH}.`; - expect(err.message.indexOf(expectedError) !== -1).equal(true); - } - }); + it("| init with a invalid json file, expect correct error message thrown", () => { + try { + new RegionalStackFile(INVALID_JSON_PROJECT_CONFIG_PATH); + throw new Error("No error caught but supposed to throw an error when new."); + } catch (err) { + const expectedError = `Failed to parse JSON file ${INVALID_JSON_PROJECT_CONFIG_PATH}.`; + expect(err.message.indexOf(expectedError) !== -1).equal(true); + } + }); - afterEach(() => { - RegionalStackFile.dispose(); - }); + afterEach(() => { + RegionalStackFile.dispose(); }); + }); - describe('# inspect correctness for getter and setter for different fields', () => { - const TEST_BUCKET = 'BUCKET'; - const TEST_KEY = 'KEY'; - const TEST_VERSION = 'VERSION'; - const jsonFileObject = jsonfile.readFileSync(REGIONAL_STACK_PATH); + describe("# inspect correctness for getter and setter for different fields", () => { + const TEST_BUCKET = "BUCKET"; + const TEST_KEY = "KEY"; + const TEST_VERSION = "VERSION"; + const jsonFileObject = jsonfile.readFileSync(REGIONAL_STACK_PATH); - beforeEach(() => { - new RegionalStackFile(REGIONAL_STACK_PATH); - }); + beforeEach(() => { + new RegionalStackFile(REGIONAL_STACK_PATH); + }); - afterEach(() => { - RegionalStackFile.dispose(); - }); + afterEach(() => { + RegionalStackFile.dispose(); + }); - describe('# verify method getResources()', () => { - it('| get resource object', () => { - expect(RegionalStackFile.getInstance().getResources()).deep.equal(jsonFileObject.Resources); - }); - }); + describe("# verify method getResources()", () => { + it("| get resource object", () => { + expect(RegionalStackFile.getInstance().getResources()).deep.equal(jsonFileObject.Resources); + }); + }); - describe('# verify method getLambdaFunction()', () => { - it('| get aws lambda function object', () => { - expect(RegionalStackFile.getInstance().getLambdaFunction()).deep.equal(jsonFileObject.Resources.AlexaSkillFunction); - }); + describe("# verify method getLambdaFunction()", () => { + it("| get aws lambda function object", () => { + expect(RegionalStackFile.getInstance().getLambdaFunction()).deep.equal(jsonFileObject.Resources.AlexaSkillFunction); + }); - it('| return null when aws lambda function object is empty', () => { - RegionalStackFile.getInstance().content.Resources.AlexaSkillFunction = undefined; - expect(RegionalStackFile.getInstance().getLambdaFunction()).equal(null); - }); + it("| return null when aws lambda function object is empty", () => { + RegionalStackFile.getInstance().content.Resources.AlexaSkillFunction = undefined; + expect(RegionalStackFile.getInstance().getLambdaFunction()).equal(null); + }); - it('| return null when resources object is empty', () => { - RegionalStackFile.getInstance().content.Resources = undefined; - expect(RegionalStackFile.getInstance().getLambdaFunction()).equal(null); - }); - }); + it("| return null when resources object is empty", () => { + RegionalStackFile.getInstance().content.Resources = undefined; + expect(RegionalStackFile.getInstance().getLambdaFunction()).equal(null); + }); + }); - describe('# verify method setLambdaFunctionCode()', () => { - it('| set aws lambda function code property correctly', () => { - expect(RegionalStackFile.getInstance().setLambdaFunctionCode(TEST_BUCKET, TEST_KEY, TEST_VERSION)); - expect(RegionalStackFile.getInstance().getLambdaFunction().Properties.Code).deep.equal({ - S3Bucket: TEST_BUCKET, - S3Key: TEST_KEY, - S3ObjectVersion: TEST_VERSION - }); - }); - - it('| throw error when no resources property exists in template', () => { - RegionalStackFile.getInstance().content.Resources = undefined; - try { - RegionalStackFile.getInstance().setLambdaFunctionCode(TEST_BUCKET, TEST_KEY, TEST_VERSION); - } catch (e) { - expect(e.message).equal('[Error]: Resources field must not be empty in regional template file'); - } - }); + describe("# verify method setLambdaFunctionCode()", () => { + it("| set aws lambda function code property correctly", () => { + expect(RegionalStackFile.getInstance().setLambdaFunctionCode(TEST_BUCKET, TEST_KEY, TEST_VERSION)); + expect(RegionalStackFile.getInstance().getLambdaFunction().Properties.Code).deep.equal({ + S3Bucket: TEST_BUCKET, + S3Key: TEST_KEY, + S3ObjectVersion: TEST_VERSION, }); + }); + + it("| throw error when no resources property exists in template", () => { + RegionalStackFile.getInstance().content.Resources = undefined; + try { + RegionalStackFile.getInstance().setLambdaFunctionCode(TEST_BUCKET, TEST_KEY, TEST_VERSION); + } catch (e) { + expect(e.message).equal("[Error]: Resources field must not be empty in regional template file"); + } + }); }); + }); }); diff --git a/test/unit/model/resources-config/ask-resources-test.js b/test/unit/model/resources-config/ask-resources-test.js index 10c9e46f..def79a6b 100644 --- a/test/unit/model/resources-config/ask-resources-test.js +++ b/test/unit/model/resources-config/ask-resources-test.js @@ -1,113 +1,113 @@ -const sinon = require('sinon'); -const { expect } = require('chai'); -const path = require('path'); -const fs = require('fs-extra'); +const sinon = require("sinon"); +const {expect} = require("chai"); +const path = require("path"); +const fs = require("fs-extra"); -const AbstractConfigFile = require('@src/model/abstract-config-file'); -const AskResources = require('@src/model/resources-config/ask-resources'); +const AbstractConfigFile = require("../../../../lib/model/abstract-config-file"); +const AskResources = require("../../../../lib/model/resources-config/ask-resources"); -describe('Model test resources config - ask resources test', () => { - const FIXTURE_PATH = path.join(process.cwd(), 'test', 'unit', 'fixture', 'model'); - const RESOURCS_CONFIG_PATH = path.join(FIXTURE_PATH, 'resources-config.json'); - const YAML_RESOURCES_CONFIG_PATH = path.join(FIXTURE_PATH, 'resources-config.yaml'); +describe("Model test resources config - ask resources test", () => { + const FIXTURE_PATH = path.join(process.cwd(), "test", "unit", "fixture", "model"); + const RESOURCS_CONFIG_PATH = path.join(FIXTURE_PATH, "resources-config.json"); + const YAML_RESOURCES_CONFIG_PATH = path.join(FIXTURE_PATH, "resources-config.yaml"); - describe('# inspect correctness for constructor, getInstance and dispose', () => { - const NOT_EXISTING_PROJECT_CONFIG_PATH = path.join(FIXTURE_PATH, 'out-of-noWhere.json'); - const INVALID_JSON_PROJECT_CONFIG_PATH = path.join(FIXTURE_PATH, 'invalid-json.json'); + describe("# inspect correctness for constructor, getInstance and dispose", () => { + const NOT_EXISTING_PROJECT_CONFIG_PATH = path.join(FIXTURE_PATH, "out-of-noWhere.json"); + const INVALID_JSON_PROJECT_CONFIG_PATH = path.join(FIXTURE_PATH, "invalid-json.json"); - it('| initiate as an AskResources class', () => { - const projConfig = new AskResources(RESOURCS_CONFIG_PATH); - expect(projConfig).to.be.instanceof(AskResources); - }); + it("| initiate as an AskResources class", () => { + const projConfig = new AskResources(RESOURCS_CONFIG_PATH); + expect(projConfig).to.be.instanceof(AskResources); + }); - it('| make sure AskResources class is singleton', () => { - const config1 = new AskResources(RESOURCS_CONFIG_PATH); - const config2 = new AskResources(RESOURCS_CONFIG_PATH); - expect(config1 === config2).equal(true); - }); + it("| make sure AskResources class is singleton", () => { + const config1 = new AskResources(RESOURCS_CONFIG_PATH); + const config2 = new AskResources(RESOURCS_CONFIG_PATH); + expect(config1 === config2).equal(true); + }); - it('| make sure YAML and JSON resources config can both be created well', () => { - const yamlConfig = new AskResources(YAML_RESOURCES_CONFIG_PATH); - const jsonConfig = fs.readJSONSync(RESOURCS_CONFIG_PATH); - expect(yamlConfig.content).deep.equal(jsonConfig); - }); + it("| make sure YAML and JSON resources config can both be created well", () => { + const yamlConfig = new AskResources(YAML_RESOURCES_CONFIG_PATH); + const jsonConfig = fs.readJSONSync(RESOURCS_CONFIG_PATH); + expect(yamlConfig.content).deep.equal(jsonConfig); + }); - it('| get instance function return the instance constructed before', () => { - const projConfig = new AskResources(RESOURCS_CONFIG_PATH); - expect(AskResources.getInstance() === projConfig).equal(true); - }); + it("| get instance function return the instance constructed before", () => { + const projConfig = new AskResources(RESOURCS_CONFIG_PATH); + expect(AskResources.getInstance() === projConfig).equal(true); + }); - it('| dispose the instance correctly', () => { - new AskResources(RESOURCS_CONFIG_PATH); - AskResources.dispose(); - expect(AskResources.getInstance()).equal(null); - }); + it("| dispose the instance correctly", () => { + new AskResources(RESOURCS_CONFIG_PATH); + AskResources.dispose(); + expect(AskResources.getInstance()).equal(null); + }); - it('| init with a file path not existing, expect correct error message thrown', () => { - try { - new AskResources(NOT_EXISTING_PROJECT_CONFIG_PATH); - throw new Error('No error caught but supposed to throw an error when new.'); - } catch (err) { - const expectedError = `File ${NOT_EXISTING_PROJECT_CONFIG_PATH} not exists.`; - expect(err.message.indexOf(expectedError) !== -1).equal(true); - } - }); + it("| init with a file path not existing, expect correct error message thrown", () => { + try { + new AskResources(NOT_EXISTING_PROJECT_CONFIG_PATH); + throw new Error("No error caught but supposed to throw an error when new."); + } catch (err) { + const expectedError = `File ${NOT_EXISTING_PROJECT_CONFIG_PATH} not exists.`; + expect(err.message.indexOf(expectedError) !== -1).equal(true); + } + }); - it('| init with a file path without access permission, expect correct error message thrown', () => { - // setup - fs.chmodSync(RESOURCS_CONFIG_PATH, 0o111); - try { - // call - new AskResources(RESOURCS_CONFIG_PATH); - throw new Error('No error caught but supposed to throw an error when new.'); - } catch (err) { - // verify - const expectedError = `No access to read/write file ${RESOURCS_CONFIG_PATH}.`; - expect(err.message.indexOf(expectedError) !== -1).equal(true); - } finally { - // clear - fs.chmodSync(RESOURCS_CONFIG_PATH, 0o644); - } - }); + it("| init with a file path without access permission, expect correct error message thrown", () => { + // setup + fs.chmodSync(RESOURCS_CONFIG_PATH, 0o111); + try { + // call + new AskResources(RESOURCS_CONFIG_PATH); + throw new Error("No error caught but supposed to throw an error when new."); + } catch (err) { + // verify + const expectedError = `No access to read/write file ${RESOURCS_CONFIG_PATH}.`; + expect(err.message.indexOf(expectedError) !== -1).equal(true); + } finally { + // clear + fs.chmodSync(RESOURCS_CONFIG_PATH, 0o644); + } + }); - it('| init with a invalid json file, expect correct error message thrown', () => { - try { - new AskResources(INVALID_JSON_PROJECT_CONFIG_PATH); - throw new Error('No error caught but supposed to throw an error when new.'); - } catch (err) { - const expectedError = `Failed to parse JSON file ${INVALID_JSON_PROJECT_CONFIG_PATH}.`; - expect(err.message.indexOf(expectedError) !== -1).equal(true); - } - }); + it("| init with a invalid json file, expect correct error message thrown", () => { + try { + new AskResources(INVALID_JSON_PROJECT_CONFIG_PATH); + throw new Error("No error caught but supposed to throw an error when new."); + } catch (err) { + const expectedError = `Failed to parse JSON file ${INVALID_JSON_PROJECT_CONFIG_PATH}.`; + expect(err.message.indexOf(expectedError) !== -1).equal(true); + } + }); - afterEach(() => { - AskResources.dispose(); - }); + afterEach(() => { + AskResources.dispose(); }); + }); - describe('# inspect class static property', () => { - it('| check BASE correctness', () => { - expect(AskResources.BASE).deep.equal({ - askcliResourcesVersion: '2020-03-31', - profiles: {} - }); - }); + describe("# inspect class static property", () => { + it("| check BASE correctness", () => { + expect(AskResources.BASE).deep.equal({ + askcliResourcesVersion: "2020-03-31", + profiles: {}, + }); }); + }); - describe('# verify method withContent', () => { - afterEach(() => { - sinon.restore(); - }); + describe("# verify method withContent", () => { + afterEach(() => { + sinon.restore(); + }); - it('| expect AbstractConfigFile withContent gets called and return AskResources instance', () => { - // setup - sinon.stub(AbstractConfigFile, 'withContent'); - sinon.stub(AbstractConfigFile.prototype, '_validateFilePath'); - sinon.stub(AbstractConfigFile.prototype, 'read'); - // call - AskResources.withContent(RESOURCS_CONFIG_PATH); - // expect - expect(AskResources.getInstance()).to.be.instanceof(AskResources); - }); + it("| expect AbstractConfigFile withContent gets called and return AskResources instance", () => { + // setup + sinon.stub(AbstractConfigFile, "withContent"); + sinon.stub(AbstractConfigFile.prototype, "_validateFilePath"); + sinon.stub(AbstractConfigFile.prototype, "read"); + // call + AskResources.withContent(RESOURCS_CONFIG_PATH); + // expect + expect(AskResources.getInstance()).to.be.instanceof(AskResources); }); + }); }); diff --git a/test/unit/model/resources-config/ask-states-test.js b/test/unit/model/resources-config/ask-states-test.js index e6880c7d..4e531ca9 100644 --- a/test/unit/model/resources-config/ask-states-test.js +++ b/test/unit/model/resources-config/ask-states-test.js @@ -1,113 +1,113 @@ -const sinon = require('sinon'); -const { expect } = require('chai'); -const path = require('path'); -const fs = require('fs-extra'); +const sinon = require("sinon"); +const {expect} = require("chai"); +const path = require("path"); +const fs = require("fs-extra"); -const AbstractConfigFile = require('@src/model/abstract-config-file'); -const AskStates = require('@src/model/resources-config/ask-states'); +const AbstractConfigFile = require("../../../../lib/model/abstract-config-file"); +const AskStates = require("../../../../lib/model/resources-config/ask-states"); -describe('Model test resources config - ask states test', () => { - const FIXTURE_PATH = path.join(process.cwd(), 'test', 'unit', 'fixture', 'model'); - const RESOURCS_CONFIG_PATH = path.join(FIXTURE_PATH, 'resources-config.json'); - const YAML_RESOURCES_CONFIG_PATH = path.join(FIXTURE_PATH, 'resources-config.yaml'); +describe("Model test resources config - ask states test", () => { + const FIXTURE_PATH = path.join(process.cwd(), "test", "unit", "fixture", "model"); + const RESOURCS_CONFIG_PATH = path.join(FIXTURE_PATH, "resources-config.json"); + const YAML_RESOURCES_CONFIG_PATH = path.join(FIXTURE_PATH, "resources-config.yaml"); - describe('# inspect correctness for constructor, getInstance and dispose', () => { - const NOT_EXISTING_PROJECT_CONFIG_PATH = path.join(FIXTURE_PATH, 'out-of-noWhere.json'); - const INVALID_JSON_PROJECT_CONFIG_PATH = path.join(FIXTURE_PATH, 'invalid-json.json'); + describe("# inspect correctness for constructor, getInstance and dispose", () => { + const NOT_EXISTING_PROJECT_CONFIG_PATH = path.join(FIXTURE_PATH, "out-of-noWhere.json"); + const INVALID_JSON_PROJECT_CONFIG_PATH = path.join(FIXTURE_PATH, "invalid-json.json"); - it('| initiate as an AskStates class', () => { - const projConfig = new AskStates(RESOURCS_CONFIG_PATH); - expect(projConfig).to.be.instanceof(AskStates); - }); + it("| initiate as an AskStates class", () => { + const projConfig = new AskStates(RESOURCS_CONFIG_PATH); + expect(projConfig).to.be.instanceof(AskStates); + }); - it('| make sure AskStates class is singleton', () => { - const config1 = new AskStates(RESOURCS_CONFIG_PATH); - const config2 = new AskStates(RESOURCS_CONFIG_PATH); - expect(config1 === config2).equal(true); - }); + it("| make sure AskStates class is singleton", () => { + const config1 = new AskStates(RESOURCS_CONFIG_PATH); + const config2 = new AskStates(RESOURCS_CONFIG_PATH); + expect(config1 === config2).equal(true); + }); - it('| make sure YAML and JSON resources config can both be created well', () => { - const yamlConfig = new AskStates(YAML_RESOURCES_CONFIG_PATH); - const jsonConfig = fs.readJSONSync(RESOURCS_CONFIG_PATH); - expect(yamlConfig.content).deep.equal(jsonConfig); - }); + it("| make sure YAML and JSON resources config can both be created well", () => { + const yamlConfig = new AskStates(YAML_RESOURCES_CONFIG_PATH); + const jsonConfig = fs.readJSONSync(RESOURCS_CONFIG_PATH); + expect(yamlConfig.content).deep.equal(jsonConfig); + }); - it('| get instance function return the instance constructed before', () => { - const projConfig = new AskStates(RESOURCS_CONFIG_PATH); - expect(AskStates.getInstance() === projConfig).equal(true); - }); + it("| get instance function return the instance constructed before", () => { + const projConfig = new AskStates(RESOURCS_CONFIG_PATH); + expect(AskStates.getInstance() === projConfig).equal(true); + }); - it('| dispose the instance correctly', () => { - new AskStates(RESOURCS_CONFIG_PATH); - AskStates.dispose(); - expect(AskStates.getInstance()).equal(null); - }); + it("| dispose the instance correctly", () => { + new AskStates(RESOURCS_CONFIG_PATH); + AskStates.dispose(); + expect(AskStates.getInstance()).equal(null); + }); - it('| init with a file path not existing, expect correct error message thrown', () => { - try { - new AskStates(NOT_EXISTING_PROJECT_CONFIG_PATH); - throw new Error('No error caught but supposed to throw an error when new.'); - } catch (err) { - const expectedError = `File ${NOT_EXISTING_PROJECT_CONFIG_PATH} not exists.`; - expect(err.message.indexOf(expectedError) !== -1).equal(true); - } - }); + it("| init with a file path not existing, expect correct error message thrown", () => { + try { + new AskStates(NOT_EXISTING_PROJECT_CONFIG_PATH); + throw new Error("No error caught but supposed to throw an error when new."); + } catch (err) { + const expectedError = `File ${NOT_EXISTING_PROJECT_CONFIG_PATH} not exists.`; + expect(err.message.indexOf(expectedError) !== -1).equal(true); + } + }); - it('| init with a file path without access permission, expect correct error message thrown', () => { - // setup - fs.chmodSync(RESOURCS_CONFIG_PATH, 0o111); - try { - // call - new AskStates(RESOURCS_CONFIG_PATH); - throw new Error('No error caught but supposed to throw an error when new.'); - } catch (err) { - // verify - const expectedError = `No access to read/write file ${RESOURCS_CONFIG_PATH}.`; - expect(err.message.indexOf(expectedError) !== -1).equal(true); - } finally { - // clear - fs.chmodSync(RESOURCS_CONFIG_PATH, 0o644); - } - }); + it("| init with a file path without access permission, expect correct error message thrown", () => { + // setup + fs.chmodSync(RESOURCS_CONFIG_PATH, 0o111); + try { + // call + new AskStates(RESOURCS_CONFIG_PATH); + throw new Error("No error caught but supposed to throw an error when new."); + } catch (err) { + // verify + const expectedError = `No access to read/write file ${RESOURCS_CONFIG_PATH}.`; + expect(err.message.indexOf(expectedError) !== -1).equal(true); + } finally { + // clear + fs.chmodSync(RESOURCS_CONFIG_PATH, 0o644); + } + }); - it('| init with a invalid json file, expect correct error message thrown', () => { - try { - new AskStates(INVALID_JSON_PROJECT_CONFIG_PATH); - throw new Error('No error caught but supposed to throw an error when new.'); - } catch (err) { - const expectedError = `Failed to parse JSON file ${INVALID_JSON_PROJECT_CONFIG_PATH}.`; - expect(err.message.indexOf(expectedError) !== -1).equal(true); - } - }); + it("| init with a invalid json file, expect correct error message thrown", () => { + try { + new AskStates(INVALID_JSON_PROJECT_CONFIG_PATH); + throw new Error("No error caught but supposed to throw an error when new."); + } catch (err) { + const expectedError = `Failed to parse JSON file ${INVALID_JSON_PROJECT_CONFIG_PATH}.`; + expect(err.message.indexOf(expectedError) !== -1).equal(true); + } + }); - afterEach(() => { - AskStates.dispose(); - }); + afterEach(() => { + AskStates.dispose(); }); + }); - describe('# inspect class static property', () => { - it('| check BASE correctness', () => { - expect(AskStates.BASE).deep.equal({ - askcliStatesVersion: '2020-03-31', - profiles: {} - }); - }); + describe("# inspect class static property", () => { + it("| check BASE correctness", () => { + expect(AskStates.BASE).deep.equal({ + askcliStatesVersion: "2020-03-31", + profiles: {}, + }); }); + }); - describe('# verify method withContent', () => { - afterEach(() => { - sinon.restore(); - }); + describe("# verify method withContent", () => { + afterEach(() => { + sinon.restore(); + }); - it('| expect AbstractConfigFile withContent gets called and return AskResources instance', () => { - // setup - sinon.stub(AbstractConfigFile, 'withContent'); - sinon.stub(AbstractConfigFile.prototype, '_validateFilePath'); - sinon.stub(AbstractConfigFile.prototype, 'read'); - // call - AskStates.withContent(RESOURCS_CONFIG_PATH); - // expect - expect(AskStates.getInstance()).to.be.instanceof(AskStates); - }); + it("| expect AbstractConfigFile withContent gets called and return AskResources instance", () => { + // setup + sinon.stub(AbstractConfigFile, "withContent"); + sinon.stub(AbstractConfigFile.prototype, "_validateFilePath"); + sinon.stub(AbstractConfigFile.prototype, "read"); + // call + AskStates.withContent(RESOURCS_CONFIG_PATH); + // expect + expect(AskStates.getInstance()).to.be.instanceof(AskStates); }); + }); }); diff --git a/test/unit/model/resources-config/resources-config-test.js b/test/unit/model/resources-config/resources-config-test.js index 6af45ad2..a1208a34 100644 --- a/test/unit/model/resources-config/resources-config-test.js +++ b/test/unit/model/resources-config/resources-config-test.js @@ -1,265 +1,262 @@ -const { expect } = require('chai'); -const sinon = require('sinon'); -const path = require('path'); -const fs = require('fs-extra'); +const {expect} = require("chai"); +const sinon = require("sinon"); +const path = require("path"); +const fs = require("fs-extra"); -const ResourcesConfig = require('@src/model/resources-config'); -const AskStates = require('@src/model/resources-config/ask-states'); +const ResourcesConfig = require("../../../../lib/model/resources-config"); +const AskStates = require("../../../../lib/model/resources-config/ask-states"); -describe('Model test - resources config test', () => { - const FIXTURE_PATH = path.join(process.cwd(), 'test', 'unit', 'fixture', 'model'); - const FIXTURE_RESOURCES_CONFIG_FILE_PATH = path.join(FIXTURE_PATH, 'regular-proj', 'ask-resources.json'); - const FIXTURE_STATES_FILE_PATH = path.join(FIXTURE_PATH, 'regular-proj', '.ask', 'ask-states.json'); - const NOT_EXISTING_PROJECT_CONFIG_PATH = 'out-of-no-where.json'; - const TEST_PROFILE = 'default'; +describe("Model test - resources config test", () => { + const FIXTURE_PATH = path.join(process.cwd(), "test", "unit", "fixture", "model"); + const FIXTURE_RESOURCES_CONFIG_FILE_PATH = path.join(FIXTURE_PATH, "regular-proj", "ask-resources.json"); + const FIXTURE_STATES_FILE_PATH = path.join(FIXTURE_PATH, "regular-proj", ".ask", "ask-states.json"); + const NOT_EXISTING_PROJECT_CONFIG_PATH = "out-of-no-where.json"; + const TEST_PROFILE = "default"; - describe('# inspect correctness for constructor, getInstance and dispose', () => { - it('| initiate as a ResourcesConfig class', () => { - const projConfig = new ResourcesConfig(FIXTURE_RESOURCES_CONFIG_FILE_PATH); - expect(projConfig).to.be.instanceof(ResourcesConfig); - }); + describe("# inspect correctness for constructor, getInstance and dispose", () => { + it("| initiate as a ResourcesConfig class", () => { + const projConfig = new ResourcesConfig(FIXTURE_RESOURCES_CONFIG_FILE_PATH); + expect(projConfig).to.be.instanceof(ResourcesConfig); + }); - it('| make sure ResourcesConfig class is singleton', () => { - const config1 = new ResourcesConfig(FIXTURE_RESOURCES_CONFIG_FILE_PATH); - const config2 = new ResourcesConfig(FIXTURE_RESOURCES_CONFIG_FILE_PATH); - expect(config1 === config2).equal(true); - }); + it("| make sure ResourcesConfig class is singleton", () => { + const config1 = new ResourcesConfig(FIXTURE_RESOURCES_CONFIG_FILE_PATH); + const config2 = new ResourcesConfig(FIXTURE_RESOURCES_CONFIG_FILE_PATH); + expect(config1 === config2).equal(true); + }); - it('| get instance function return the instance constructed before', () => { - const projConfig = new ResourcesConfig(FIXTURE_RESOURCES_CONFIG_FILE_PATH); - expect(ResourcesConfig.getInstance() === projConfig).equal(true); - }); + it("| get instance function return the instance constructed before", () => { + const projConfig = new ResourcesConfig(FIXTURE_RESOURCES_CONFIG_FILE_PATH); + expect(ResourcesConfig.getInstance() === projConfig).equal(true); + }); - it('| dispose the instance correctly', () => { - new ResourcesConfig(FIXTURE_RESOURCES_CONFIG_FILE_PATH); - ResourcesConfig.dispose(); - expect(ResourcesConfig.getInstance()).equal(null); - }); + it("| dispose the instance correctly", () => { + new ResourcesConfig(FIXTURE_RESOURCES_CONFIG_FILE_PATH); + ResourcesConfig.dispose(); + expect(ResourcesConfig.getInstance()).equal(null); + }); - it('| init with a file path not existing, expect correct error message thrown', () => { - try { - new ResourcesConfig(NOT_EXISTING_PROJECT_CONFIG_PATH); - throw new Error('No error caught but supposed to throw an error when new.'); - } catch (err) { - const expectedError = `File ${NOT_EXISTING_PROJECT_CONFIG_PATH} not exists.`; - expect(err.message.indexOf(expectedError) !== -1).equal(true); - } - }); + it("| init with a file path not existing, expect correct error message thrown", () => { + try { + new ResourcesConfig(NOT_EXISTING_PROJECT_CONFIG_PATH); + throw new Error("No error caught but supposed to throw an error when new."); + } catch (err) { + const expectedError = `File ${NOT_EXISTING_PROJECT_CONFIG_PATH} not exists.`; + expect(err.message.indexOf(expectedError) !== -1).equal(true); + } + }); - it('| .ask/ask-states.json file does not exist, expect withContent called', () => { - // setup - sinon.stub(fs, 'existsSync'); - fs.existsSync.withArgs(FIXTURE_STATES_FILE_PATH).returns(false); - fs.existsSync.callThrough(); - sinon.stub(AskStates, 'withContent'); - // call - try { - new ResourcesConfig(FIXTURE_RESOURCES_CONFIG_FILE_PATH); - } catch (err) { - expect(err).equal(undefined); - } - // expect - expect(AskStates.withContent.args[0][0]).equal(FIXTURE_STATES_FILE_PATH); - }); + it("| .ask/ask-states.json file does not exist, expect withContent called", () => { + // setup + sinon.stub(fs, "existsSync"); + fs.existsSync.withArgs(FIXTURE_STATES_FILE_PATH).returns(false); + fs.existsSync.callThrough(); + sinon.stub(AskStates, "withContent"); + // call + try { + new ResourcesConfig(FIXTURE_RESOURCES_CONFIG_FILE_PATH); + } catch (err) { + expect(err).equal(undefined); + } + // expect + expect(AskStates.withContent.args[0][0]).equal(FIXTURE_STATES_FILE_PATH); + }); - afterEach(() => { - ResourcesConfig.dispose(); - }); + afterEach(() => { + ResourcesConfig.dispose(); }); + }); - describe('# inspect special methods in resources config model', () => { - describe('| getCodeRegions', () => { - beforeEach(() => { - new ResourcesConfig(FIXTURE_RESOURCES_CONFIG_FILE_PATH); - }); + describe("# inspect special methods in resources config model", () => { + describe("| getCodeRegions", () => { + beforeEach(() => { + new ResourcesConfig(FIXTURE_RESOURCES_CONFIG_FILE_PATH); + }); - afterEach(() => { - ResourcesConfig.dispose(); - sinon.restore(); - }); + afterEach(() => { + ResourcesConfig.dispose(); + sinon.restore(); + }); - it('| return code regions correctly based on the fixture data', () => { - expect(ResourcesConfig.getInstance().getCodeRegions(TEST_PROFILE)).deep.equal(['default', 'NA', 'EU']); - }); - }); + it("| return code regions correctly based on the fixture data", () => { + expect(ResourcesConfig.getInstance().getCodeRegions(TEST_PROFILE)).deep.equal(["default", "NA", "EU"]); + }); + }); - describe('| method getCodeBuildByRegion', () => { - beforeEach(() => { - new ResourcesConfig(FIXTURE_RESOURCES_CONFIG_FILE_PATH); - }); + describe("| method getCodeBuildByRegion", () => { + beforeEach(() => { + new ResourcesConfig(FIXTURE_RESOURCES_CONFIG_FILE_PATH); + }); - afterEach(() => { - ResourcesConfig.dispose(); - sinon.restore(); - }); + afterEach(() => { + ResourcesConfig.dispose(); + sinon.restore(); + }); - it('| return null when codeSrc does not exist', () => { - // setup - sinon.stub(ResourcesConfig.prototype, 'getCodeSrcByRegion').returns(null); - expect(ResourcesConfig.getInstance().getCodeBuildByRegion(TEST_PROFILE, 'default')).equal(null); - }); + it("| return null when codeSrc does not exist", () => { + // setup + sinon.stub(ResourcesConfig.prototype, "getCodeSrcByRegion").returns(null); + expect(ResourcesConfig.getInstance().getCodeBuildByRegion(TEST_PROFILE, "default")).equal(null); + }); - it('| return correct result when codeSrc is a file', () => { - // setup - const TEST_SRC = path.join(FIXTURE_PATH, 'regular-proj', 'folder1', 'file1.json'); - ResourcesConfig.getInstance().setCodeSrcByRegion(TEST_PROFILE, 'default', TEST_SRC); - sinon.stub(fs, 'statSync').withArgs(TEST_SRC).returns({ - isDirectory: () => false - }); - // call - const build = ResourcesConfig.getInstance().getCodeBuildByRegion(TEST_PROFILE, 'default'); - // verify - expect(build.folder.endsWith(`.ask${path.sep}folder1`)).equal(true); - expect(build.file.endsWith(`.ask${path.sep}folder1${path.sep}build.zip`)).equal(true); - }); + it("| return correct result when codeSrc is a file", () => { + // setup + const TEST_SRC = path.join(FIXTURE_PATH, "regular-proj", "folder1", "file1.json"); + ResourcesConfig.getInstance().setCodeSrcByRegion(TEST_PROFILE, "default", TEST_SRC); + sinon + .stub(fs, "statSync") + .withArgs(TEST_SRC) + .returns({ + isDirectory: () => false, + }); + // call + const build = ResourcesConfig.getInstance().getCodeBuildByRegion(TEST_PROFILE, "default"); + // verify + expect(build.folder.endsWith(`.ask${path.sep}folder1`)).equal(true); + expect(build.file.endsWith(`.ask${path.sep}folder1${path.sep}build.zip`)).equal(true); + }); - it('| return correct result when codeSrc is a directory', () => { - // setup - const TEST_SRC = path.join(FIXTURE_PATH, 'regular-proj', 'folder1', 'folder2'); - ResourcesConfig.getInstance().setCodeSrcByRegion(TEST_PROFILE, 'default', TEST_SRC); - sinon.stub(fs, 'statSync').withArgs(TEST_SRC).returns({ - isDirectory: () => true - }); - // call - const build = ResourcesConfig.getInstance().getCodeBuildByRegion(TEST_PROFILE, 'default'); - // verify - expect(build.folder.endsWith(`.ask${path.sep}folder1${path.sep}folder2`)).equal(true); - expect(build.file.endsWith(`.ask${path.sep}folder1${path.sep}folder2${path.sep}build.zip`)).equal(true); - }); - }); + it("| return correct result when codeSrc is a directory", () => { + // setup + const TEST_SRC = path.join(FIXTURE_PATH, "regular-proj", "folder1", "folder2"); + ResourcesConfig.getInstance().setCodeSrcByRegion(TEST_PROFILE, "default", TEST_SRC); + sinon + .stub(fs, "statSync") + .withArgs(TEST_SRC) + .returns({ + isDirectory: () => true, + }); + // call + const build = ResourcesConfig.getInstance().getCodeBuildByRegion(TEST_PROFILE, "default"); + // verify + expect(build.folder.endsWith(`.ask${path.sep}folder1${path.sep}folder2`)).equal(true); + expect(build.file.endsWith(`.ask${path.sep}folder1${path.sep}folder2${path.sep}build.zip`)).equal(true); + }); }); + }); - describe('# inspect correctness for getter and setter for different fields', () => { - const TEST_ASK_RESOURCES = fs.readJSONSync(FIXTURE_RESOURCES_CONFIG_FILE_PATH); - const TEST_ASK_STATES = fs.readJSONSync(FIXTURE_STATES_FILE_PATH); + describe("# inspect correctness for getter and setter for different fields", () => { + const TEST_ASK_RESOURCES = fs.readJSONSync(FIXTURE_RESOURCES_CONFIG_FILE_PATH); + const TEST_ASK_STATES = fs.readJSONSync(FIXTURE_STATES_FILE_PATH); - describe('# inspect skillMetadata', () => { - beforeEach(() => { - new ResourcesConfig(FIXTURE_RESOURCES_CONFIG_FILE_PATH); - }); + describe("# inspect skillMetadata", () => { + beforeEach(() => { + new ResourcesConfig(FIXTURE_RESOURCES_CONFIG_FILE_PATH); + }); - afterEach(() => { - ResourcesConfig.dispose(); - }); + afterEach(() => { + ResourcesConfig.dispose(); + }); - [{ - field: 'SkillId', - params: [TEST_PROFILE], - newValue: 'skillId new', - oldValue: TEST_ASK_STATES.profiles[TEST_PROFILE].skillId - }, - { - field: 'SkillMetaSrc', - params: [TEST_PROFILE], - newValue: 'new skillMetadata src', - oldValue: TEST_ASK_RESOURCES.profiles[TEST_PROFILE].skillMetadata.src - }, - { - field: 'SkillMetaLastDeployHash', - params: [TEST_PROFILE], - newValue: '==hash', - oldValue: TEST_ASK_STATES.profiles[TEST_PROFILE].skillMetadata.lastDeployHash - }].forEach(({ - field, - params, - newValue, - oldValue - }) => { - it(`| test get${field} function successfully`, () => { - expect(ResourcesConfig.getInstance()[`get${field}`](...params)).deep.equal(oldValue); - }); + [ + { + field: "SkillId", + params: [TEST_PROFILE], + newValue: "skillId new", + oldValue: TEST_ASK_STATES.profiles[TEST_PROFILE].skillId, + }, + { + field: "SkillMetaSrc", + params: [TEST_PROFILE], + newValue: "new skillMetadata src", + oldValue: TEST_ASK_RESOURCES.profiles[TEST_PROFILE].skillMetadata.src, + }, + { + field: "SkillMetaLastDeployHash", + params: [TEST_PROFILE], + newValue: "==hash", + oldValue: TEST_ASK_STATES.profiles[TEST_PROFILE].skillMetadata.lastDeployHash, + }, + ].forEach(({field, params, newValue, oldValue}) => { + it(`| test get${field} function successfully`, () => { + expect(ResourcesConfig.getInstance()[`get${field}`](...params)).deep.equal(oldValue); + }); - it(`| test set${field} function successfully`, () => { - const setParams = params; - setParams.push(newValue); - ResourcesConfig.getInstance()[`set${field}`](...setParams); - expect(ResourcesConfig.getInstance()[`get${field}`](...params)).equal(newValue); - }); - }); + it(`| test set${field} function successfully`, () => { + const setParams = params; + setParams.push(newValue); + ResourcesConfig.getInstance()[`set${field}`](...setParams); + expect(ResourcesConfig.getInstance()[`get${field}`](...params)).equal(newValue); }); + }); + }); - describe('# inspect code', () => { - beforeEach(() => { - new ResourcesConfig(FIXTURE_RESOURCES_CONFIG_FILE_PATH); - }); + describe("# inspect code", () => { + beforeEach(() => { + new ResourcesConfig(FIXTURE_RESOURCES_CONFIG_FILE_PATH); + }); - afterEach(() => { - ResourcesConfig.dispose(); - }); + afterEach(() => { + ResourcesConfig.dispose(); + }); - [{ - field: 'CodeSrcByRegion', - params: [TEST_PROFILE, 'NA'], - newValue: 'new code src', - oldValue: TEST_ASK_RESOURCES.profiles[TEST_PROFILE].code.NA.src - }, - { - field: 'CodeLastDeployHashByRegion', - params: [TEST_PROFILE, 'FE'], - newValue: 'new code hash', - oldValue: TEST_ASK_STATES.profiles[TEST_PROFILE].code.FE.lastDeployHash - }].forEach(({ - field, - params, - newValue, - oldValue - }) => { - it(`| test get${field} function successfully`, () => { - expect(ResourcesConfig.getInstance()[`get${field}`](...params)).deep.equal(oldValue); - }); + [ + { + field: "CodeSrcByRegion", + params: [TEST_PROFILE, "NA"], + newValue: "new code src", + oldValue: TEST_ASK_RESOURCES.profiles[TEST_PROFILE].code.NA.src, + }, + { + field: "CodeLastDeployHashByRegion", + params: [TEST_PROFILE, "FE"], + newValue: "new code hash", + oldValue: TEST_ASK_STATES.profiles[TEST_PROFILE].code.FE.lastDeployHash, + }, + ].forEach(({field, params, newValue, oldValue}) => { + it(`| test get${field} function successfully`, () => { + expect(ResourcesConfig.getInstance()[`get${field}`](...params)).deep.equal(oldValue); + }); - it(`| test set${field} function successfully`, () => { - const setParams = params; - setParams.push(newValue); - ResourcesConfig.getInstance()[`set${field}`](...setParams); - expect(ResourcesConfig.getInstance()[`get${field}`](...params)).equal(newValue); - }); - }); + it(`| test set${field} function successfully`, () => { + const setParams = params; + setParams.push(newValue); + ResourcesConfig.getInstance()[`set${field}`](...setParams); + expect(ResourcesConfig.getInstance()[`get${field}`](...params)).equal(newValue); }); + }); + }); - describe('# inspect skillInfrastructure', () => { - beforeEach(() => { - new ResourcesConfig(FIXTURE_RESOURCES_CONFIG_FILE_PATH); - }); + describe("# inspect skillInfrastructure", () => { + beforeEach(() => { + new ResourcesConfig(FIXTURE_RESOURCES_CONFIG_FILE_PATH); + }); - afterEach(() => { - ResourcesConfig.dispose(); - }); + afterEach(() => { + ResourcesConfig.dispose(); + }); - [{ - field: 'SkillInfraType', - params: [TEST_PROFILE], - newValue: 'new type', - oldValue: TEST_ASK_RESOURCES.profiles[TEST_PROFILE].skillInfrastructure.type - }, - { - field: 'SkillInfraUserConfig', - params: [TEST_PROFILE], - newValue: 'new user config', - oldValue: TEST_ASK_RESOURCES.profiles[TEST_PROFILE].skillInfrastructure.userConfig - }, - { - field: 'SkillInfraDeployState', - params: [TEST_PROFILE], - newValue: 'new deploy state', - oldValue: TEST_ASK_STATES.profiles[TEST_PROFILE].skillInfrastructure['@ask-cli/cfn-deployer'].deployState - }].forEach(({ - field, - params, - newValue, - oldValue - }) => { - it(`| test get${field} function successfully`, () => { - expect(ResourcesConfig.getInstance()[`get${field}`](...params)).deep.equal(oldValue); - }); + [ + { + field: "SkillInfraType", + params: [TEST_PROFILE], + newValue: "new type", + oldValue: TEST_ASK_RESOURCES.profiles[TEST_PROFILE].skillInfrastructure.type, + }, + { + field: "SkillInfraUserConfig", + params: [TEST_PROFILE], + newValue: "new user config", + oldValue: TEST_ASK_RESOURCES.profiles[TEST_PROFILE].skillInfrastructure.userConfig, + }, + { + field: "SkillInfraDeployState", + params: [TEST_PROFILE], + newValue: "new deploy state", + oldValue: TEST_ASK_STATES.profiles[TEST_PROFILE].skillInfrastructure["@ask-cli/cfn-deployer"].deployState, + }, + ].forEach(({field, params, newValue, oldValue}) => { + it(`| test get${field} function successfully`, () => { + expect(ResourcesConfig.getInstance()[`get${field}`](...params)).deep.equal(oldValue); + }); - it(`| test set${field} function successfully`, () => { - const setParams = params; - setParams.push(newValue); - ResourcesConfig.getInstance()[`set${field}`](...setParams); - expect(ResourcesConfig.getInstance()[`get${field}`](...params)).equal(newValue); - }); - }); + it(`| test set${field} function successfully`, () => { + const setParams = params; + setParams.push(newValue); + ResourcesConfig.getInstance()[`set${field}`](...setParams); + expect(ResourcesConfig.getInstance()[`get${field}`](...params)).equal(newValue); }); + }); }); + }); }); diff --git a/test/unit/model/sample-template-test.ts b/test/unit/model/sample-template-test.ts new file mode 100644 index 00000000..26c9ac6e --- /dev/null +++ b/test/unit/model/sample-template-test.ts @@ -0,0 +1,84 @@ +import {expect} from "chai"; +import { + SampleTemplate, + SampleTemplatesFilter, + SampleTemplateFilterValues, +} from "../../../lib/model/sample-template"; + +describe("Sample Templates", () => { + const SAMPLE_1: SampleTemplate = { + stack: "ac", + deploy: "lambda", + lang: "node", + name: "sample1", + url: "http://www.smaple1.com/repo.git", + desc: "describe sample 1", + }; + const SAMPLE_2: SampleTemplate = { + stack: "im", + deploy: "hosted", + lang: "python", + name: "sample_2", + url: "http://www.smaple2.com/repo.git", + desc: "describe sample 2", + }; + const SAMPLE_3: SampleTemplate = { + stack: "im", + deploy: "cfn", + lang: "java", + name: "sample 3", + url: "http://www.smaple3.com/repo.git", + desc: "describe sample 3", + }; + const SAMPLE_4: SampleTemplate = { + stack: "im", + deploy: "self", + lang: "node", + name: "sample 4", + url: "http://www.smaple4.com/repo.git", + desc: "describe sample 4", + }; + + let testSampleTemplates: SampleTemplate[]; + + + beforeEach(() => { + testSampleTemplates = [SAMPLE_1, SAMPLE_2, SAMPLE_3, SAMPLE_4]; + }); + + describe("SampleTemplateFilter class", () => { + it("filters SampleTemplates by skill type", () => { + expect(filter(testSampleTemplates, "stack", "im")).deep.equal([SAMPLE_2, SAMPLE_3, SAMPLE_4]); + expect(filter(testSampleTemplates, "stack", "ac")).deep.equal([SAMPLE_1]); + }); + + it("filters SampleTemplates by deployment type", () => { + expect(filter(testSampleTemplates, "deploy", "lambda")).deep.equal([SAMPLE_1]); + expect(filter(testSampleTemplates, "deploy", "hosted")).deep.equal([SAMPLE_2]); + expect(filter(testSampleTemplates, "deploy", "cfn")).deep.equal([SAMPLE_3]); + expect(filter(testSampleTemplates, "deploy", "self")).deep.equal([SAMPLE_4]); + }); + + it("filters SampleTemplates by language type", () => { + expect(filter(testSampleTemplates, "lang", "node")).deep.equal([SAMPLE_1, SAMPLE_4]); + expect(filter(testSampleTemplates, "lang", "python")).deep.equal([SAMPLE_2]); + expect(filter(testSampleTemplates, "lang", "java")).deep.equal([SAMPLE_3]); + }); + + it("filters all SampleTemplates when there are no matches", () => { + expect(filter([SAMPLE_1], "stack", "im")).deep.equal([]); + expect(filter([SAMPLE_1], "deploy", "hosted")).deep.equal([]); + expect(filter([SAMPLE_1], "lang", "java")).deep.equal([]); + }); + + function filter( + samples: SampleTemplate[], + filter_key: keyof SampleTemplate, + filter_value: SampleTemplateFilterValues, + ): SampleTemplate[] { + const sampleTemplatesFilter: SampleTemplatesFilter = new SampleTemplatesFilter(samples); + sampleTemplatesFilter.filter(filter_key, filter_value); + return sampleTemplatesFilter.getSampleTemplates(); + } + }); +}); diff --git a/test/unit/model/skill-status-test.ts b/test/unit/model/skill-status-test.ts new file mode 100644 index 00000000..2f3d4fe5 --- /dev/null +++ b/test/unit/model/skill-status-test.ts @@ -0,0 +1,77 @@ +import {expect} from "chai"; +import { + BuildDetailStep, + SkillStatus +} from "../../../lib/model/skill-status"; + +describe("Model - Skill Status ", () => { + describe("SkillStatus", () => { + const SMAPI_RESPONSE = { + body: { + interactionModel: { + "en-US": { + lastUpdateRequest: { + status: "IN_PROGRESS", + buildDetails: { + steps: [ + { + name: "LANGUAGE_MODEL_QUICK_BUILD", + status: "SUCCEEDED" + }, + { + name: "LANGUAGE_MODEL_FULL_BUILD", + status: "SUCCEEDED" + }, + { + name: "ALEXA_CONVERSATIONS_QUICK_BUILD", + status: "FAILED" + }, + { + name: "ALEXA_CONVERSATIONS_FULL_BUILD", + status: "IN_PROGRESS" + } + ] + } + } + } + } + } + } + + it("constructor initializes a SkillStatus object", () => { + const obj: SkillStatus = new SkillStatus(SMAPI_RESPONSE); + expect(obj).to.be.instanceOf(SkillStatus); + // exposes an Interaction Model + expect(obj.interactionModel).not.equal(null); + expect(obj.interactionModel.lastUpdateRequests).not.equal(null); + expect(obj.interactionModel.lastUpdateRequests[0]).not.equal(undefined); + expect(obj.interactionModel.lastUpdateRequests[0].locale).equal("en-US"); + expect(obj.interactionModel.lastUpdateRequests[0].buildDetailSteps).not.equal(undefined); + expect(Object.keys(obj.interactionModel.lastUpdateRequests[0].buildDetailSteps).length).equal(4); + + let buildDetailStep: BuildDetailStep = obj.interactionModel.lastUpdateRequests[0].getBuildDetailStep("LANGUAGE_MODEL_QUICK_BUILD"); + expect(buildDetailStep).not.equal(undefined); + expect(buildDetailStep.buildType).equal("LANGUAGE_MODEL_QUICK_BUILD"); + expect(buildDetailStep.buildStatus).equal("SUCCEEDED"); + expect(buildDetailStep.isACBuildType).to.be.false; + + buildDetailStep = obj.interactionModel.lastUpdateRequests[0].getBuildDetailStep("LANGUAGE_MODEL_FULL_BUILD"); + expect(buildDetailStep).not.equal(undefined); + expect(buildDetailStep.buildType).equal("LANGUAGE_MODEL_FULL_BUILD"); + expect(buildDetailStep.buildStatus).equal("SUCCEEDED"); + expect(buildDetailStep.isACBuildType).to.be.false; + + buildDetailStep = obj.interactionModel.lastUpdateRequests[0].getBuildDetailStep("ALEXA_CONVERSATIONS_QUICK_BUILD"); + expect(buildDetailStep).not.equal(undefined); + expect(buildDetailStep.buildType).equal("ALEXA_CONVERSATIONS_QUICK_BUILD"); + expect(buildDetailStep.buildStatus).equal("FAILED"); + expect(buildDetailStep.isACBuildType).to.be.true; + + buildDetailStep = obj.interactionModel.lastUpdateRequests[0].getBuildDetailStep("ALEXA_CONVERSATIONS_FULL_BUILD"); + expect(buildDetailStep).not.equal(undefined); + expect(buildDetailStep.buildType).equal("ALEXA_CONVERSATIONS_FULL_BUILD"); + expect(buildDetailStep.buildStatus).equal("IN_PROGRESS"); + expect(buildDetailStep.isACBuildType).to.be.true; + }); + }); +}); diff --git a/test/unit/model/skill-status.test.ts b/test/unit/model/skill-status.test.ts new file mode 100644 index 00000000..2f3d4fe5 --- /dev/null +++ b/test/unit/model/skill-status.test.ts @@ -0,0 +1,77 @@ +import {expect} from "chai"; +import { + BuildDetailStep, + SkillStatus +} from "../../../lib/model/skill-status"; + +describe("Model - Skill Status ", () => { + describe("SkillStatus", () => { + const SMAPI_RESPONSE = { + body: { + interactionModel: { + "en-US": { + lastUpdateRequest: { + status: "IN_PROGRESS", + buildDetails: { + steps: [ + { + name: "LANGUAGE_MODEL_QUICK_BUILD", + status: "SUCCEEDED" + }, + { + name: "LANGUAGE_MODEL_FULL_BUILD", + status: "SUCCEEDED" + }, + { + name: "ALEXA_CONVERSATIONS_QUICK_BUILD", + status: "FAILED" + }, + { + name: "ALEXA_CONVERSATIONS_FULL_BUILD", + status: "IN_PROGRESS" + } + ] + } + } + } + } + } + } + + it("constructor initializes a SkillStatus object", () => { + const obj: SkillStatus = new SkillStatus(SMAPI_RESPONSE); + expect(obj).to.be.instanceOf(SkillStatus); + // exposes an Interaction Model + expect(obj.interactionModel).not.equal(null); + expect(obj.interactionModel.lastUpdateRequests).not.equal(null); + expect(obj.interactionModel.lastUpdateRequests[0]).not.equal(undefined); + expect(obj.interactionModel.lastUpdateRequests[0].locale).equal("en-US"); + expect(obj.interactionModel.lastUpdateRequests[0].buildDetailSteps).not.equal(undefined); + expect(Object.keys(obj.interactionModel.lastUpdateRequests[0].buildDetailSteps).length).equal(4); + + let buildDetailStep: BuildDetailStep = obj.interactionModel.lastUpdateRequests[0].getBuildDetailStep("LANGUAGE_MODEL_QUICK_BUILD"); + expect(buildDetailStep).not.equal(undefined); + expect(buildDetailStep.buildType).equal("LANGUAGE_MODEL_QUICK_BUILD"); + expect(buildDetailStep.buildStatus).equal("SUCCEEDED"); + expect(buildDetailStep.isACBuildType).to.be.false; + + buildDetailStep = obj.interactionModel.lastUpdateRequests[0].getBuildDetailStep("LANGUAGE_MODEL_FULL_BUILD"); + expect(buildDetailStep).not.equal(undefined); + expect(buildDetailStep.buildType).equal("LANGUAGE_MODEL_FULL_BUILD"); + expect(buildDetailStep.buildStatus).equal("SUCCEEDED"); + expect(buildDetailStep.isACBuildType).to.be.false; + + buildDetailStep = obj.interactionModel.lastUpdateRequests[0].getBuildDetailStep("ALEXA_CONVERSATIONS_QUICK_BUILD"); + expect(buildDetailStep).not.equal(undefined); + expect(buildDetailStep.buildType).equal("ALEXA_CONVERSATIONS_QUICK_BUILD"); + expect(buildDetailStep.buildStatus).equal("FAILED"); + expect(buildDetailStep.isACBuildType).to.be.true; + + buildDetailStep = obj.interactionModel.lastUpdateRequests[0].getBuildDetailStep("ALEXA_CONVERSATIONS_FULL_BUILD"); + expect(buildDetailStep).not.equal(undefined); + expect(buildDetailStep.buildType).equal("ALEXA_CONVERSATIONS_FULL_BUILD"); + expect(buildDetailStep.buildStatus).equal("IN_PROGRESS"); + expect(buildDetailStep.isACBuildType).to.be.true; + }); + }); +}); diff --git a/test/unit/model/yaml-parser-test.js b/test/unit/model/yaml-parser-test.js index 71a1879c..1f16bc0e 100644 --- a/test/unit/model/yaml-parser-test.js +++ b/test/unit/model/yaml-parser-test.js @@ -1,61 +1,61 @@ -const { expect } = require('chai'); -const sinon = require('sinon'); -const jsonfile = require('jsonfile'); -const path = require('path'); -const fs = require('fs'); -const yamlLibrary = require('js-yaml'); +const {expect} = require("chai"); +const sinon = require("sinon"); +const jsonfile = require("jsonfile"); +const path = require("path"); +const fs = require("fs"); +const yamlLibrary = require("js-yaml"); -const yaml = require('@src/model/yaml-parser'); +const yaml = require("../../../lib/model/yaml-parser"); -describe('Model test - yaml parser', () => { - const FIXTURE_PATH = path.join(process.cwd(), 'test', 'unit', 'fixture', 'model'); - const YAML_FILE_PATH = path.join(FIXTURE_PATH, 'yaml-config.yaml'); - const YAML_JSON_RESULT_PATH = path.join(FIXTURE_PATH, 'yaml-json-result.json'); - const YAML_JSON_RESULT = jsonfile.readFileSync(YAML_JSON_RESULT_PATH); +describe("Model test - yaml parser", () => { + const FIXTURE_PATH = path.join(process.cwd(), "test", "unit", "fixture", "model"); + const YAML_FILE_PATH = path.join(FIXTURE_PATH, "yaml-config.yaml"); + const YAML_JSON_RESULT_PATH = path.join(FIXTURE_PATH, "yaml-json-result.json"); + const YAML_JSON_RESULT = jsonfile.readFileSync(YAML_JSON_RESULT_PATH); - describe('# test yaml load function', () => { - it('| load yaml file correctly', () => { - const content = yaml.load(YAML_FILE_PATH); - expect(content).deep.equal(YAML_JSON_RESULT); - }); + describe("# test yaml load function", () => { + it("| load yaml file correctly", () => { + const content = yaml.load(YAML_FILE_PATH); + expect(content).deep.equal(YAML_JSON_RESULT); + }); - it('| load yaml file throws error', () => { - // setup - sinon.stub(yamlLibrary, 'load').throws(new Error('load error')); - try { - // call - yaml.load(YAML_FILE_PATH); - } catch (e) { - // verify - expect(e.message).to.equal('load error'); - } - // clear - sinon.restore(); - }); + it("| load yaml file throws error", () => { + // setup + sinon.stub(yamlLibrary, "load").throws(new Error("load error")); + try { + // call + yaml.load(YAML_FILE_PATH); + } catch (e) { + // verify + expect(e.message).to.equal("load error"); + } + // clear + sinon.restore(); }); + }); - describe('# test yaml dump function', () => { - if (process.platform !== 'win32') { - it('| dump yaml file correctly', () => { - const FROM_JSON_PATH = path.join(FIXTURE_PATH, 'yaml-from-json-result.yaml'); - yaml.dump(FROM_JSON_PATH, YAML_JSON_RESULT); - expect(fs.readFileSync(FROM_JSON_PATH, 'utf8')).equal(fs.readFileSync(YAML_FILE_PATH, 'utf8')); - }); - } + describe("# test yaml dump function", () => { + if (process.platform !== "win32") { + it("| dump yaml file correctly", () => { + const FROM_JSON_PATH = path.join(FIXTURE_PATH, "yaml-from-json-result.yaml"); + yaml.dump(FROM_JSON_PATH, YAML_JSON_RESULT); + expect(fs.readFileSync(FROM_JSON_PATH, "utf8")).equal(fs.readFileSync(YAML_FILE_PATH, "utf8")); + }); + } - it('| dump yaml file throws error', () => { - // setup - sinon.stub(yamlLibrary, 'dump').throws(new Error('dump error')); - const FROM_JSON_PATH = path.join(FIXTURE_PATH, 'yaml-from-json-result.yaml'); - try { - // call - yaml.dump(FROM_JSON_PATH, YAML_JSON_RESULT); - } catch (e) { - // verify - expect(e.message).to.equal('dump error'); - } - // clear - sinon.restore(); - }); + it("| dump yaml file throws error", () => { + // setup + sinon.stub(yamlLibrary, "dump").throws(new Error("dump error")); + const FROM_JSON_PATH = path.join(FIXTURE_PATH, "yaml-from-json-result.yaml"); + try { + // call + yaml.dump(FROM_JSON_PATH, YAML_JSON_RESULT); + } catch (e) { + // verify + expect(e.message).to.equal("dump error"); + } + // clear + sinon.restore(); }); + }); }); diff --git a/test/unit/run-test.js b/test/unit/run-test.js index b8cdcc52..9eea081d 100644 --- a/test/unit/run-test.js +++ b/test/unit/run-test.js @@ -1,136 +1,10 @@ -require('module-alias/register'); +const path = require("path"); +const chai = require("chai"); +const fs = require("fs-extra"); +const sinonChai = require("sinon-chai"); +const chaiAsPromised = require("chai-as-promised"); -process.env.ASK_SHARE_USAGE = false; - -/** - * This list manages all the files we want to cover during the refactor. - * Please also include the test-ready module in package.json's "nyc.include" list. - * Make sure test coverage meets the bar. - */ -[ - // UNIT TEST - // builtins - '@test/unit/builtins/lambda-deployer/index-test.js', - '@test/unit/builtins/lambda-deployer/helper-test.js', - '@test/unit/builtins/cfn-deployer/index-test.js', - '@test/unit/builtins/cfn-deployer/helper-test.js', - '@test/unit/builtins/build-flows/abstract-build-flow-test.js', - '@test/unit/builtins/build-flows/custom-test.js', - '@test/unit/builtins/build-flows/java-mvn-test.js', - '@test/unit/builtins/build-flows/nodejs-npm-test.js', - '@test/unit/builtins/build-flows/python-pip-test.js', - '@test/unit/builtins/build-flows/zip-only-test.js', - // commands - '@test/unit/commands/option-validator-test', - '@test/unit/commands/abstract-command-test', - // command - util - '@test/unit/commands/util/git-credentials-helper/index-test', - '@test/unit/commands/util/generate-lwa-tokens/index-test', - // command - new - '@test/unit/commands/new/index-test', - '@test/unit/commands/new/ui-test', - '@test/unit/commands/new/helper-test', - '@test/unit/commands/new/wizard-helper-test', - '@test/unit/commands/new/hosted-skill-helper-test', - // command - configure - '@test/unit/commands/configure/index-test', - '@test/unit/commands/configure/ui-test', - '@test/unit/commands/configure/helper-test', - '@test/unit/commands/configure/questions-test', - '@test/unit/commands/configure/ask-profile-setup-helper-test', - '@test/unit/commands/configure/aws-profile-setup-helper-test', - // command - init - '@test/unit/commands/init/index-test', - '@test/unit/commands/init/ui-test', - '@test/unit/commands/init/helper-test', - // command - dialog - '@test/unit/commands/dialog/index-test', - '@test/unit/commands/dialog/helper-test', - '@test/unit/commands/dialog/replay-mode-test', - '@test/unit/commands/dialog/interactive-mode-test', - // command - deploy - '@test/unit/commands/deploy/index-test', - '@test/unit/commands/deploy/helper-test', - // command - skill - '@test/unit/commands/skill/add-locales/index-test', - '@test/unit/commands/skill/add-locales/helper-test', - '@test/unit/commands/skill/add-locales/ui-test', - // command - smapi - '@test/unit/commands/smapi/cli-customization-processor-test.js', - '@test/unit/commands/smapi/smapi-command-handler-test.js', - '@test/unit/commands/smapi/smapi-commander-test.js', - '@test/unit/commands/smapi/smapi-docs-test.js', - '@test/unit/commands/smapi/before-send-processor-test.js', - // command - smapi - export-package - '@test/unit/commands/smapi/appended-commands/export-package/index-test.js', - '@test/unit/commands/smapi/appended-commands/export-package/helper-test.js', - // command - smapi - get-task - '@test/unit/commands/smapi/appended-commands/get-task/index-test.js', - // command - smapi - search-task - '@test/unit/commands/smapi/appended-commands/search-task/index-test.js', +chai.use(chaiAsPromised); +chai.use(sinonChai); - // command - util - '@test/unit/commands/util/upgrade-project/index-test', - '@test/unit/commands/util/upgrade-project/ui-test', - '@test/unit/commands/util/upgrade-project/helper-test', - '@test/unit/commands/util/upgrade-project/hosted-skill-helper-test', - // clients - '@test/unit/clients/http-client-test', - '@test/unit/clients/metric-client-test', - '@test/unit/clients/smapi-client-test', - '@test/unit/clients/git-client-test', - '@test/unit/clients/lwa-auth-code-client-test', - '@test/unit/clients/aws-client/abstract-aws-client-test', - '@test/unit/clients/aws-client/s3-client-test', - '@test/unit/clients/aws-client/cloudformation-client-test', - '@test/unit/clients/aws-client/aws-util-test', - '@test/unit/clients/aws-client/iam-client-test', - '@test/unit/clients/aws-client/lambda-client-test', - // model - '@test/unit/model/abstract-config-file-test', - '@test/unit/model/app-config-test', - '@test/unit/model/dialog-save-skill-io-file-test', - '@test/unit/model/manifest-test', - '@test/unit/model/resources-config/resources-config-test', - '@test/unit/model/resources-config/ask-resources-test', - '@test/unit/model/resources-config/ask-states-test', - '@test/unit/model/yaml-parser-test', - '@test/unit/model/regional-stack-file-test', - '@test/unit/model/dialog-replay-file-test', - // controller - '@test/unit/controller/authorization-controller/index-test', - '@test/unit/controller/dialog-controller/index-test', - '@test/unit/controller/dialog-controller/simulation-response-parser-test', - '@test/unit/controller/skill-metadata-controller-test', - '@test/unit/controller/skill-code-controller-test', - '@test/unit/controller/skill-simulation-controller-test', - '@test/unit/controller/code-builder-test', - '@test/unit/controller/skill-infrastructure-controller-test', - '@test/unit/controller/deploy-delegate-test', - '@test/unit/controller/hosted-skill-controller/index-test', - '@test/unit/controller/hosted-skill-controller/clone-flow-test', - // view - '@test/unit/view/messenger-test', - '@test/unit/view/json-view-test', - '@test/unit/view/prompt-view-test', - '@test/unit/view/spinner-view-test', - '@test/unit/view/multi-tasks-view-test', - '@test/unit/view/cli-repl-view-test', - '@test/unit/view/dialog-repl-view-test', - // utils - '@test/unit/utils/url-utils-test', - '@test/unit/utils/string-utils-test', - '@test/unit/utils/zip-utils-test', - '@test/unit/utils/hash-utils-test', - '@test/unit/utils/retry-utility-test', - '@test/unit/utils/local-host-server-test', - // command - run - '@test/unit/commands/run/index-test', - '@test/unit/commands/run/helper-test', - '@test/unit/commands/run/run-flow/java-run-test', - '@test/unit/commands/run/run-flow/nodejs-run-test', - '@test/unit/commands/run/run-flow/python-run-test' -].forEach((testFile) => { - // eslint-disable-next-line global-require - require(testFile); -}); +process.env.ASK_SHARE_USAGE = false; diff --git a/test/unit/utils/hash-utils-test.js b/test/unit/utils/hash-utils-test.js index 128add8e..1c519ac3 100644 --- a/test/unit/utils/hash-utils-test.js +++ b/test/unit/utils/hash-utils-test.js @@ -1,53 +1,53 @@ -const folderHash = require('folder-hash'); -const sinon = require('sinon'); -const { expect } = require('chai'); +const folderHash = require("folder-hash"); +const sinon = require("sinon"); +const {expect} = require("chai"); -const hashUtils = require('@src/utils/hash-utils'); +const hashUtils = require("../../../lib/utils/hash-utils"); -describe('Utils test - hash utility', () => { - describe('# getHash function tests', () => { - const TEST_DIR_PATH = 'DIR_PATH'; - const expectedOptions = { - algo: 'sha1', - encoding: 'base64', - folders: { - exclude: ['.*', 'node_modules', 'test_coverage', 'dist', 'build'], - ignoreRootName: true - }, - }; +describe("Utils test - hash utility", () => { + describe("# getHash function tests", () => { + const TEST_DIR_PATH = "DIR_PATH"; + const expectedOptions = { + algo: "sha1", + encoding: "base64", + folders: { + exclude: [".*", "node_modules", "test_coverage", "dist", "build"], + ignoreRootName: true, + }, + }; - it('| can correctly callback hash code', (done) => { - const TEST_HASH_CODE = 'HASH_CODE'; - const TEST_RESULT = { - hash: TEST_HASH_CODE - }; - // setup - sinon.stub(folderHash, 'hashElement').withArgs(TEST_DIR_PATH, expectedOptions).callsArgWith(2, null, TEST_RESULT); + it("| can correctly callback hash code", (done) => { + const TEST_HASH_CODE = "HASH_CODE"; + const TEST_RESULT = { + hash: TEST_HASH_CODE, + }; + // setup + sinon.stub(folderHash, "hashElement").withArgs(TEST_DIR_PATH, expectedOptions).callsArgWith(2, null, TEST_RESULT); - // call - hashUtils.getHash(TEST_DIR_PATH, (error, response) => { - // verify - expect(error).equal(null); - expect(response).equal(TEST_HASH_CODE); - done(); - }); - }); + // call + hashUtils.getHash(TEST_DIR_PATH, (error, response) => { + // verify + expect(error).equal(null); + expect(response).equal(TEST_HASH_CODE); + done(); + }); + }); - it('| can correctly callback error', (done) => { - const TEST_ERROR = 'ERROR'; - // setup - sinon.stub(folderHash, 'hashElement').withArgs(TEST_DIR_PATH, expectedOptions).callsArgWith(2, TEST_ERROR); + it("| can correctly callback error", (done) => { + const TEST_ERROR = "ERROR"; + // setup + sinon.stub(folderHash, "hashElement").withArgs(TEST_DIR_PATH, expectedOptions).callsArgWith(2, TEST_ERROR); - // call - hashUtils.getHash(TEST_DIR_PATH, (error) => { - // verify - expect(error).equal(TEST_ERROR); - done(); - }); - }); + // call + hashUtils.getHash(TEST_DIR_PATH, (error) => { + // verify + expect(error).equal(TEST_ERROR); + done(); + }); + }); - afterEach(() => { - sinon.restore(); - }); + afterEach(() => { + sinon.restore(); }); + }); }); diff --git a/test/unit/utils/local-host-server-test.js b/test/unit/utils/local-host-server-test.js index f23aca23..1a0c8b15 100644 --- a/test/unit/utils/local-host-server-test.js +++ b/test/unit/utils/local-host-server-test.js @@ -1,46 +1,46 @@ -const { expect } = require('chai'); -const http = require('http'); -const sinon = require('sinon'); +const {expect} = require("chai"); +const http = require("http"); +const sinon = require("sinon"); -const CONSTANTS = require('@src/utils/constants'); -const LocalServer = require('@src/utils/local-host-server'); +const CONSTANTS = require("../../../lib/utils/constants"); +const LocalServer = require("../../../lib/utils/local-host-server"); -describe('# Server test - Local host server test', () => { - const TEST_PORT = CONSTANTS.LWA.LOCAL_PORT; - const TEST_EVENT = 'testEvent'; - const listenStub = sinon.stub(); - const onStub = sinon.stub(); - const closeStub = sinon.stub(); - const unrefStub = sinon.stub(); +describe("# Server test - Local host server test", () => { + const TEST_PORT = CONSTANTS.LWA.LOCAL_PORT; + const TEST_EVENT = "testEvent"; + const listenStub = sinon.stub(); + const onStub = sinon.stub(); + const closeStub = sinon.stub(); + const unrefStub = sinon.stub(); - const TEST_SERVER = { - listen: listenStub, - on: onStub, - close: closeStub, - unref: unrefStub - }; + const TEST_SERVER = { + listen: listenStub, + on: onStub, + close: closeStub, + unref: unrefStub, + }; - afterEach(() => { - sinon.restore(); - }); + afterEach(() => { + sinon.restore(); + }); - it('| test server methods', () => { - // setup - const httpStub = sinon.stub(http, 'createServer').returns(TEST_SERVER); - const localServer = new LocalServer(TEST_PORT); + it("| test server methods", () => { + // setup + const httpStub = sinon.stub(http, "createServer").returns(TEST_SERVER); + const localServer = new LocalServer(TEST_PORT); - // call - localServer.create(() => {}); - localServer.listen(() => {}); - localServer.registerEvent(TEST_EVENT, () => {}); - localServer.destroy(); + // call + localServer.create(() => {}); + localServer.listen(() => {}); + localServer.registerEvent(TEST_EVENT, () => {}); + localServer.destroy(); - // verify - expect(httpStub.callCount).eq(1); - expect(listenStub.callCount).eq(1); - expect(onStub.callCount).eq(1); - expect(closeStub.callCount).eq(1); - expect(unrefStub.callCount).eq(1); - expect(localServer.server).to.deep.eq(TEST_SERVER); - }); + // verify + expect(httpStub.callCount).eq(1); + expect(listenStub.callCount).eq(1); + expect(onStub.callCount).eq(1); + expect(closeStub.callCount).eq(1); + expect(unrefStub.callCount).eq(1); + expect(localServer.server).to.deep.eq(TEST_SERVER); + }); }); diff --git a/test/unit/utils/retry-utility-test.js b/test/unit/utils/retry-utility-test.js index 97a61c56..f2befdf4 100644 --- a/test/unit/utils/retry-utility-test.js +++ b/test/unit/utils/retry-utility-test.js @@ -1,7 +1,7 @@ -const { assert } = require('chai'); -const sinon = require('sinon'); -const retryUtils = require('@src/utils/retry-utility'); - +const {assert, expect} = require("chai"); +const sinon = require("sinon"); +const retryUtils = require("../../../lib/utils/retry-utility"); +const CONSTANTS = require("../../../lib/utils/constants"); /** * The test input description are as follows * testCase: description of the test case @@ -13,183 +13,207 @@ const retryUtils = require('@src/utils/retry-utility'); * pollCount: The retry count that determines the termination condition * testResponse: Contains either a default response or an array of responses or both. This is fed to the sinon stub */ -describe('Utils test - retry utility', () => { - describe('# test function retry', () => { - const SUCCESS_RESPONSE = 'Complete'; - const PROGRESS_RESPONSE = 'In Progress'; - [ - { - testCase: 'null retry config value', - retryConfig: null, - expectedResult: { - error: '[Error]: Invalid retry configuration. Retry configuration with values - base, factor and maxRetry needs to be specified', - response: undefined, - callCount: 0 - } - }, - { - testCase: 'undefined retry config value', - retryConfig: undefined, - expectedResult: { - error: '[Error]: Invalid retry configuration. Retry configuration with values - base, factor and maxRetry needs to be specified', - response: undefined, - callCount: 0 - } - }, - { - testCase: 'invalid string value in retry config', - retryConfig: 'foobar', - expectedResult: { - error: '[Error]: Invalid retry configuration: base. Base is a required configuration and its value needs to be greater than 0', - response: undefined, - callCount: 0 - } - }, - { - testCase: 'empty base value in retry config', - retryConfig: { - }, - expectedResult: { - error: '[Error]: Invalid retry configuration: base. Base is a required configuration and its value needs to be greater than 0', - response: undefined, - callCount: 0 - } - }, - { - testCase: 'invalid base value in retry config', - retryConfig: { - base: -1, - factor: -1 - }, - expectedResult: { - error: '[Error]: Invalid retry configuration: base. Base is a required configuration and its value needs to be greater than 0', - response: undefined, - callCount: 0 - } - }, - { - testCase: 'empty factor value in retry config', - retryConfig: { - base: 1 - }, - expectedResult: { - error: '[Error]: Invalid retry configuration: factor. Factor is a required ' - + 'configuration and its value needs to be greater than 0', - response: undefined, - callCount: 0 - } - }, - { - testCase: 'invalid factor value in retry config', - retryConfig: { - base: 1, - factor: -1 - }, - expectedResult: { - error: '[Error]: Invalid retry configuration: factor. ' - + 'Factor is a required configuration and its value needs to be greater than 0', - response: undefined, - callCount: 0 - } - }, - { - testCase: 'invalid factor value in retry config', - retryConfig: { - base: 1, - factor: 1 - }, - expectedResult: { - error: '[Error]: Invalid retry configuration: maxRetry. ' - + 'MaxRetry is a required configuration and its value needs to be greater than 0', - response: undefined, - callCount: 0 - } - }, - { - testCase: 'invalid maxRetry value in retry config', - retryConfig: { - base: 1, - factor: 1, - maxRetry: -1 - }, - expectedResult: { - error: '[Error]: Invalid retry configuration: maxRetry. Value needs to be an integer and greater than 0', - response: undefined, - callCount: 0 - } - }, - { - testCase: 'Valid retry configurations. Exceeds maximum retry attempts.', - retryConfig: { - base: 1, - factor: 1, - maxRetry: 2 - }, - pollCount: 5, - testResponse: { - defaultResponse: PROGRESS_RESPONSE - }, - expectedResult: { - error: '[Error]: Retry attempt exceeded.', - response: PROGRESS_RESPONSE, - callCount: 3 - } - }, - { - testCase: 'Valid retry configurations. 3 requests are made. Service returns ' - + '"In Progress" for first 2 requests. Final retry attempt succeeds with response "Complete"', - retryConfig: { - base: 1, - factor: 1, - maxRetry: 3 - }, - pollCount: 2, - testResponse: { - defaultResponse: PROGRESS_RESPONSE, - responseMap: [ - PROGRESS_RESPONSE, - PROGRESS_RESPONSE, - SUCCESS_RESPONSE, - ], - }, - expectedResult: { - error: null, - response: SUCCESS_RESPONSE, - callCount: 3 - }, - } - ].forEach(({ testCase, retryConfig, expectedResult, pollCount, testResponse }) => { - const stub = sinon.stub(); - if (testResponse) { - if (testResponse.defaultResponse) { - stub.returns(testResponse.defaultResponse); - } - if (testResponse.responseMap) { - for (const [index, response] of testResponse.responseMap.entries()) { - stub.onCall(index).returns(response); - } - } +describe("Utils test - retry utility", () => { + describe("# test function retry", () => { + const SUCCESS_RESPONSE = "Complete"; + const PROGRESS_RESPONSE = "In Progress"; + [ + { + testCase: "null retry config value", + retryConfig: null, + expectedResult: { + error: "[Error]: Invalid retry configuration. Retry configuration with values - base, factor and maxRetry needs to be specified", + response: undefined, + callCount: 0, + }, + }, + { + testCase: "undefined retry config value", + retryConfig: undefined, + expectedResult: { + error: "[Error]: Invalid retry configuration. Retry configuration with values - base, factor and maxRetry needs to be specified", + response: undefined, + callCount: 0, + }, + }, + { + testCase: "invalid string value in retry config", + retryConfig: "foobar", + expectedResult: { + error: "[Error]: Invalid retry configuration: base. Base is a required configuration and its value needs to be greater than 0", + response: undefined, + callCount: 0, + }, + }, + { + testCase: "empty base value in retry config", + retryConfig: {}, + expectedResult: { + error: "[Error]: Invalid retry configuration: base. Base is a required configuration and its value needs to be greater than 0", + response: undefined, + callCount: 0, + }, + }, + { + testCase: "invalid base value in retry config", + retryConfig: { + base: -1, + factor: -1, + }, + expectedResult: { + error: "[Error]: Invalid retry configuration: base. Base is a required configuration and its value needs to be greater than 0", + response: undefined, + callCount: 0, + }, + }, + { + testCase: "empty factor value in retry config", + retryConfig: { + base: 1, + }, + expectedResult: { + error: + "[Error]: Invalid retry configuration: factor. Factor is a required " + + "configuration and its value needs to be greater than 0", + response: undefined, + callCount: 0, + }, + }, + { + testCase: "invalid factor value in retry config", + retryConfig: { + base: 1, + factor: -1, + }, + expectedResult: { + error: + "[Error]: Invalid retry configuration: factor. " + + "Factor is a required configuration and its value needs to be greater than 0", + response: undefined, + callCount: 0, + }, + }, + { + testCase: "invalid factor value in retry config", + retryConfig: { + base: 1, + factor: 1, + }, + expectedResult: { + error: + "[Error]: Invalid retry configuration: maxRetry. " + + "MaxRetry is a required configuration and its value needs to be greater than 0", + response: undefined, + callCount: 0, + }, + }, + { + testCase: "invalid maxRetry value in retry config", + retryConfig: { + base: 1, + factor: 1, + maxRetry: -1, + }, + expectedResult: { + error: "[Error]: Invalid retry configuration: maxRetry. Value needs to be an integer and greater than 0", + response: undefined, + callCount: 0, + }, + }, + { + testCase: "Valid retry configurations. Exceeds maximum retry attempts.", + retryConfig: { + base: 1, + factor: 1, + maxRetry: 2, + }, + pollCount: 5, + testResponse: { + defaultResponse: PROGRESS_RESPONSE, + }, + expectedResult: { + error: "[Error]: Retry attempt exceeded.", + response: PROGRESS_RESPONSE, + callCount: 3, + }, + }, + { + testCase: + "Valid retry configurations. 3 requests are made. Service returns " + + '"In Progress" for first 2 requests. Final retry attempt succeeds with response "Complete"', + retryConfig: { + base: 1, + factor: 1, + maxRetry: 3, + }, + pollCount: 2, + testResponse: { + defaultResponse: PROGRESS_RESPONSE, + responseMap: [PROGRESS_RESPONSE, PROGRESS_RESPONSE, SUCCESS_RESPONSE], + }, + expectedResult: { + error: null, + response: SUCCESS_RESPONSE, + callCount: 3, + }, + }, + ].forEach(({testCase, retryConfig, expectedResult, pollCount, testResponse}) => { + const stub = sinon.stub(); + if (testResponse) { + if (testResponse.defaultResponse) { + stub.returns(testResponse.defaultResponse); + } + if (testResponse.responseMap) { + for (const [index, response] of testResponse.responseMap.entries()) { + stub.onCall(index).returns(response); + } + } + } + const retryCall = (cb) => cb(null, stub()); + it(`| ${testCase}`, (done) => { + const shouldRetryCondition = (res) => { + if (res) { + if (pollCount > 0) { + pollCount--; + assert.strictEqual(res, PROGRESS_RESPONSE); + return true; } - const retryCall = cb => cb(null, stub()); - it(`| ${testCase}`, (done) => { - const shouldRetryCondition = (res) => { - if (res) { - if (pollCount > 0) { - pollCount--; - assert.strictEqual(res, PROGRESS_RESPONSE); - return true; - } - } - return false; - }; - // call - retryUtils.retry(retryConfig, retryCall, shouldRetryCondition, (err, res) => { - assert.strictEqual(err, expectedResult.error); - assert.strictEqual(res, expectedResult.response); - sinon.assert.callCount(stub, expectedResult.callCount); - done(); - }); - }); + } + return false; + }; + // call + retryUtils.retry(retryConfig, retryCall, shouldRetryCondition, (err, res) => { + assert.strictEqual(err, expectedResult.error); + assert.strictEqual(res, expectedResult.response); + sinon.assert.callCount(stub, expectedResult.callCount); + done(); }); + }); + }); + + it("| retry doesn't exceed max interval limit",async ()=>{ + let retryConfig = { + base: 2000, + factor: 500, + maxRetry: 3, + }; + let pollCount = 2; + const stub = sinon.stub(); + const retryCall = (cb) => cb(null, stub()); + const shouldRetryCondition = (res) =>{ + if (pollCount > 0) { + pollCount--; + return true; + } + return false + }; + const clock = sinon.useFakeTimers(); + const spy = sinon.spy(global, "setTimeout"); + retryUtils.retry(retryConfig, retryCall, shouldRetryCondition, (err, res) => { + expect(spy.lastCall.args[1]).to.be.eq(CONSTANTS.CONFIGURATION.RETRY.MAX_RETRY_INTERVAL) + done(); + }); + clock.tick(CONSTANTS.CONFIGURATION.RETRY.MAX_RETRY_INTERVAL); }); + }); }); diff --git a/test/unit/utils/string-utils-test.js b/test/unit/utils/string-utils-test.js index c2c96afc..912fb1d7 100644 --- a/test/unit/utils/string-utils-test.js +++ b/test/unit/utils/string-utils-test.js @@ -1,468 +1,468 @@ -const { expect } = require('chai'); -const stringUtils = require('@src/utils/string-utils'); +const {expect} = require("chai"); +const stringUtils = require("../../../lib/utils/string-utils"); -describe('Utils test - string utility', () => { - describe('# test function getParamNames', () => { - [{ - testCase: 'provide a no param function', - input: function test() { - return true; - }, - expectation: [] - }, { - testCase: 'provide a single param function', - input: function test(param1) { - return param1; - }, - expectation: ['param1'] - }, { - testCase: 'provide a single param with a default value function', - input: function test(param1 = true) { - return param1; - }, - expectation: ['param1', '=', 'true'] - }, { - testCase: 'provide a multiple param with a several default value function', - input: function test(param1, param2, param3 = 0, param4 = true) { - return { param1, param2, param3, param4 }; - }, - expectation: ['param1', 'param2', 'param3', '=', '0', 'param4', '=', 'true'] - - }, { - testCase: 'provide a spreded params function', - input: function test(...params) { - return params; - }, - expectation: ['...params'] - - }].forEach(({ testCase, input, expectation }) => { - it(`| ${testCase}, expect returns ${JSON.stringify(expectation)}`, () => { - const callResult = stringUtils.getParamNames(input); - expect(callResult).deep.equal(expectation); - }); - }); +describe("Utils test - string utility", () => { + describe("# test function getParamNames", () => { + [ + { + testCase: "provide a no param function", + input: function test() { + return true; + }, + expectation: [], + }, + { + testCase: "provide a single param function", + input: function test(param1) { + return param1; + }, + expectation: ["param1"], + }, + { + testCase: "provide a single param with a default value function", + input: function test(param1 = true) { + return param1; + }, + expectation: ["param1", "=", "true"], + }, + { + testCase: "provide a multiple param with a several default value function", + input: function test(param1, param2, param3 = 0, param4 = true) { + return {param1, param2, param3, param4}; + }, + expectation: ["param1", "param2", "param3", "=", "0", "param4", "=", "true"], + }, + { + testCase: "provide a spreded params function", + input: function test(...params) { + return params; + }, + expectation: ["...params"], + }, + ].forEach(({testCase, input, expectation}) => { + it(`| ${testCase}, expect returns ${JSON.stringify(expectation)}`, () => { + const callResult = stringUtils.getParamNames(input); + expect(callResult).deep.equal(expectation); + }); }); - describe('# test function kebabCase', () => { - [ - { - input: 'hello', - expectation: 'hello' - }, - { - input: 'hello-world', - expectation: 'hello-world' - }, - { - input: 'Hello World', - expectation: 'hello-world' - }, - { - input: 'HelloWorld', - expectation: 'hello-world' - } - ].forEach(({ input, expectation }) => { - it(`| input is ${input}, expect kebabCase ${expectation}`, () => { - // call - const callResult = stringUtils.kebabCase(input); - // verify - expect(callResult).equal(expectation); - }); - }); + }); + describe("# test function kebabCase", () => { + [ + { + input: "hello", + expectation: "hello", + }, + { + input: "hello-world", + expectation: "hello-world", + }, + { + input: "Hello World", + expectation: "hello-world", + }, + { + input: "HelloWorld", + expectation: "hello-world", + }, + ].forEach(({input, expectation}) => { + it(`| input is ${input}, expect kebabCase ${expectation}`, () => { + // call + const callResult = stringUtils.kebabCase(input); + // verify + expect(callResult).equal(expectation); + }); }); - describe('# test function camelCase', () => { - [ - { - input: 'hello', - expectation: 'hello' - }, - { - input: 'hello-world', - expectation: 'helloWorld' - }, - { - input: 'Hello World', - expectation: 'helloWorld' - }, - { - input: 'HelloWorld', - expectation: 'helloWorld' - } - ].forEach(({ input, expectation }) => { - it(`| input is ${input}, expect camelCase ${expectation}`, () => { - // call - const callResult = stringUtils.camelCase(input); - // verify - expect(callResult).equal(expectation); - }); - }); + }); + describe("# test function camelCase", () => { + [ + { + input: "hello", + expectation: "hello", + }, + { + input: "hello-world", + expectation: "helloWorld", + }, + { + input: "Hello World", + expectation: "helloWorld", + }, + { + input: "HelloWorld", + expectation: "helloWorld", + }, + ].forEach(({input, expectation}) => { + it(`| input is ${input}, expect camelCase ${expectation}`, () => { + // call + const callResult = stringUtils.camelCase(input); + // verify + expect(callResult).equal(expectation); + }); }); - describe('# test function isNonEmptyString', () => { - [ - { - testCase: 'input is an object', - str: {}, - expectation: false - }, - { - testCase: 'input is an array', - str: [1, 2, 3], - expectation: false - }, - { - testCase: 'input is a boolean', - str: true, - expectation: false - }, - { - testCase: 'input is an empty string', - str: '', - expectation: false - }, - { - testCase: 'input is a blank string', - str: ' ', - expectation: true - }, - { - testCase: 'input is a string with actual content', - str: ' test string ', - expectation: true - }, - ].forEach(({ testCase, str, expectation }) => { - it(`| ${testCase}, expect isNonEmptyString ${expectation}`, () => { - // call - const callResult = stringUtils.isNonEmptyString(str); - // verify - expect(callResult).equal(expectation); - }); - }); + }); + describe("# test function isNonEmptyString", () => { + [ + { + testCase: "input is an object", + str: {}, + expectation: false, + }, + { + testCase: "input is an array", + str: [1, 2, 3], + expectation: false, + }, + { + testCase: "input is a boolean", + str: true, + expectation: false, + }, + { + testCase: "input is an empty string", + str: "", + expectation: false, + }, + { + testCase: "input is a blank string", + str: " ", + expectation: true, + }, + { + testCase: "input is a string with actual content", + str: " test string ", + expectation: true, + }, + ].forEach(({testCase, str, expectation}) => { + it(`| ${testCase}, expect isNonEmptyString ${expectation}`, () => { + // call + const callResult = stringUtils.isNonEmptyString(str); + // verify + expect(callResult).equal(expectation); + }); }); + }); - describe('# test function standardize', () => { - [ - { - testCase: 'camel case to lower', - str: 'testTest', - expectation: 'testtest' - }, - { - testCase: 'capital case to lower', - str: 'TestTest', - expectation: 'testtest' - }, - { - testCase: 'non alphanumeric', - str: 'test.test', - expectation: 'testtest' - }, - ].forEach(({ testCase, str, expectation }) => { - it(`| ${testCase}, expect standardize ${str}`, () => { - // call - const callResult = stringUtils.standardize(str); - // verify - expect(callResult).equal(expectation); - }); - }); + describe("# test function standardize", () => { + [ + { + testCase: "camel case to lower", + str: "testTest", + expectation: "testtest", + }, + { + testCase: "capital case to lower", + str: "TestTest", + expectation: "testtest", + }, + { + testCase: "non alphanumeric", + str: "test.test", + expectation: "testtest", + }, + ].forEach(({testCase, str, expectation}) => { + it(`| ${testCase}, expect standardize ${str}`, () => { + // call + const callResult = stringUtils.standardize(str); + // verify + expect(callResult).equal(expectation); + }); }); + }); - describe('# test function canParseAsJson', () => { - [ - { - testCase: 'parse non json', - str: 'some non json string', - expectation: false - }, - { - testCase: 'parse json string', - str: JSON.stringify({ x: 'x' }), - expectation: true - }, - ].forEach(({ testCase, str, expectation }) => { - it(`| ${testCase}, expect standardize ${str}`, () => { - // call - const callResult = stringUtils.canParseAsJson(str); - // verify - expect(callResult).equal(expectation); - }); - }); + describe("# test function canParseAsJson", () => { + [ + { + testCase: "parse non json", + str: "some non json string", + expectation: false, + }, + { + testCase: "parse json string", + str: JSON.stringify({x: "x"}), + expectation: true, + }, + ].forEach(({testCase, str, expectation}) => { + it(`| ${testCase}, expect standardize ${str}`, () => { + // call + const callResult = stringUtils.canParseAsJson(str); + // verify + expect(callResult).equal(expectation); + }); }); + }); - describe('# test function isNonBlankString', () => { - [ - { - testCase: 'input is an object', - str: {}, - expectation: false - }, - { - testCase: 'input is an array', - str: [1, 2, 3], - expectation: false - }, - { - testCase: 'input is a boolean', - str: true, - expectation: false - }, - { - testCase: 'input is an empty string', - str: '', - expectation: false - }, - { - testCase: 'input is a blank string', - str: ' ', - expectation: false - }, - { - testCase: 'input is a string with actual content', - str: ' test string ', - expectation: true - }, - ].forEach(({ testCase, str, expectation }) => { - it(`| ${testCase}, expect isNonBlankString ${expectation}`, () => { - // call - const callResult = stringUtils.isNonBlankString(str); - // verify - expect(callResult).equal(expectation); - }); - }); + describe("# test function isNonBlankString", () => { + [ + { + testCase: "input is an object", + str: {}, + expectation: false, + }, + { + testCase: "input is an array", + str: [1, 2, 3], + expectation: false, + }, + { + testCase: "input is a boolean", + str: true, + expectation: false, + }, + { + testCase: "input is an empty string", + str: "", + expectation: false, + }, + { + testCase: "input is a blank string", + str: " ", + expectation: false, + }, + { + testCase: "input is a string with actual content", + str: " test string ", + expectation: true, + }, + ].forEach(({testCase, str, expectation}) => { + it(`| ${testCase}, expect isNonBlankString ${expectation}`, () => { + // call + const callResult = stringUtils.isNonBlankString(str); + // verify + expect(callResult).equal(expectation); + }); }); + }); - describe('# test function isLambdaFunctionName', () => { - [ - { - testCase: 'input url string is null', - str: null, - expectation: false - }, - { - testCase: 'input url string is undefined', - str: undefined, - expectation: false - }, - { - testCase: 'input url string is empty', - str: '', - expectation: false - }, - { - testCase: 'input url string is blank', - str: ' ', - expectation: false - }, - { - testCase: 'input url string is valid function name', - str: 'ask-custom-cityGuide-default', - expectation: true - }, - { - testCase: 'input url string is http', - str: 'http://lambda.arn.com', - expectation: false - }, - { - testCase: 'input url string is https', - str: 'https://test.com', - expectation: false - }, - { - testCase: 'input url is random string', - str: 'abc:A:/invoke', - expectation: false - } - - ].forEach(({ testCase, str, expectation }) => { - it(`| ${testCase}, expect isLambdaFunctionName ${expectation}`, () => { - // call - const callResult = stringUtils.isLambdaFunctionName(str); - // verify - expect(callResult).equal(expectation); - }); - }); + describe("# test function isLambdaFunctionName", () => { + [ + { + testCase: "input url string is null", + str: null, + expectation: false, + }, + { + testCase: "input url string is undefined", + str: undefined, + expectation: false, + }, + { + testCase: "input url string is empty", + str: "", + expectation: false, + }, + { + testCase: "input url string is blank", + str: " ", + expectation: false, + }, + { + testCase: "input url string is valid function name", + str: "ask-custom-cityGuide-default", + expectation: true, + }, + { + testCase: "input url string is http", + str: "http://lambda.arn.com", + expectation: false, + }, + { + testCase: "input url string is https", + str: "https://test.com", + expectation: false, + }, + { + testCase: "input url is random string", + str: "abc:A:/invoke", + expectation: false, + }, + ].forEach(({testCase, str, expectation}) => { + it(`| ${testCase}, expect isLambdaFunctionName ${expectation}`, () => { + // call + const callResult = stringUtils.isLambdaFunctionName(str); + // verify + expect(callResult).equal(expectation); + }); }); + }); - describe('# test function filterNonAlphanumeric', () => { - [ - { - testCase: 'input string is null', - str: null, - expectation: null - }, - { - testCase: 'input string is undefined', - str: undefined, - expectation: undefined - }, - { - testCase: 'input string is empty', - str: '', - expectation: '' - }, - { - testCase: 'input string is blank', - str: ' ', - expectation: '' - }, - { - testCase: 'input string is with non alphanumeric characters', - str: 'default-!!!???09', - expectation: 'default-09' - }, - { - testCase: 'input string is with non alphanumeric characters test 2', - str: 'http://lambda.arn.com', - expectation: 'httplambdaarncom' - }, - { - testCase: 'input string is all consisted of non alphanumeric characters', - str: '://!@#$%^&*()<>?_', - expectation: '' - }, - { - testCase: 'input string includes non-latin character', - str: '中文 にほんご', - expectation: '' - } - - ].forEach(({ testCase, str, expectation }) => { - it(`| ${testCase}, expect isLambdaFunctionName ${expectation}`, () => { - // call - const callResult = stringUtils.filterNonAlphanumeric(str); - // verify - expect(callResult).equal(expectation); - }); - }); + describe("# test function filterNonAlphanumeric", () => { + [ + { + testCase: "input string is null", + str: null, + expectation: null, + }, + { + testCase: "input string is undefined", + str: undefined, + expectation: undefined, + }, + { + testCase: "input string is empty", + str: "", + expectation: "", + }, + { + testCase: "input string is blank", + str: " ", + expectation: "", + }, + { + testCase: "input string is with non alphanumeric characters", + str: "default-!!!???09", + expectation: "default-09", + }, + { + testCase: "input string is with non alphanumeric characters test 2", + str: "http://lambda.arn.com", + expectation: "httplambdaarncom", + }, + { + testCase: "input string is all consisted of non alphanumeric characters", + str: "://!@#$%^&*()<>?_", + expectation: "", + }, + { + testCase: "input string includes non-latin character", + str: "中文 にほんご", + expectation: "", + }, + ].forEach(({testCase, str, expectation}) => { + it(`| ${testCase}, expect isLambdaFunctionName ${expectation}`, () => { + // call + const callResult = stringUtils.filterNonAlphanumeric(str); + // verify + expect(callResult).equal(expectation); + }); }); + }); - describe('# test function splitStringFilterAndMapTo', () => { - [ - { - testCase: 'input string is empty', - str: '', - delimiter: '/n', - filterBy: null, - mapper: null, - expectation: [] - }, - { - testCase: 'input string is null', - str: null, - delimiter: '/n', - filterBy: null, - mapper: null, - expectation: [] - }, - { - testCase: 'input string is valid', - str: 'abc,xyz', - delimiter: ',', - filterBy: null, - mapper: null, - expectation: ['abc', 'xyz'] - }, - { - testCase: 'filterBy is not provided', - str: 'abc,xyz', - delimiter: ',', - filterBy: null, - mapper: item => item.toUpperCase(), - expectation: ['ABC', 'XYZ'] - }, - { - testCase: 'mapper is not provided', - str: 'abc,xyz', - delimiter: ',', - filterBy: item => item !== 'xyz', - mapper: null, - expectation: ['abc'] - }, - { - testCase: 'all parameters are valid', - str: 'abc,xyz', - delimiter: ',', - filterBy: item => item !== 'xyz', - mapper: item => item.toUpperCase(), - expectation: ['ABC'] - } - ].forEach(({ testCase, str, delimiter, filterBy, mapper, expectation }) => { - it(`| ${testCase}, expect splitStringFilterAndMapTo returns ${expectation}`, () => { - // call - const callResult = stringUtils.splitStringFilterAndMapTo(str, delimiter, filterBy, mapper); - // verify - expect(JSON.stringify(callResult)).equal(JSON.stringify(expectation)); - }); - }); + describe("# test function splitStringFilterAndMapTo", () => { + [ + { + testCase: "input string is empty", + str: "", + delimiter: "/n", + filterBy: null, + mapper: null, + expectation: [], + }, + { + testCase: "input string is null", + str: null, + delimiter: "/n", + filterBy: null, + mapper: null, + expectation: [], + }, + { + testCase: "input string is valid", + str: "abc,xyz", + delimiter: ",", + filterBy: null, + mapper: null, + expectation: ["abc", "xyz"], + }, + { + testCase: "filterBy is not provided", + str: "abc,xyz", + delimiter: ",", + filterBy: null, + mapper: (item) => item.toUpperCase(), + expectation: ["ABC", "XYZ"], + }, + { + testCase: "mapper is not provided", + str: "abc,xyz", + delimiter: ",", + filterBy: (item) => item !== "xyz", + mapper: null, + expectation: ["abc"], + }, + { + testCase: "all parameters are valid", + str: "abc,xyz", + delimiter: ",", + filterBy: (item) => item !== "xyz", + mapper: (item) => item.toUpperCase(), + expectation: ["ABC"], + }, + ].forEach(({testCase, str, delimiter, filterBy, mapper, expectation}) => { + it(`| ${testCase}, expect splitStringFilterAndMapTo returns ${expectation}`, () => { + // call + const callResult = stringUtils.splitStringFilterAndMapTo(str, delimiter, filterBy, mapper); + // verify + expect(JSON.stringify(callResult)).equal(JSON.stringify(expectation)); + }); }); + }); - describe('# test function validateSyntax', () => { - [ - { - testCase: 'input value is null', - value: null, - expectation: false - }, - { - testCase: 'input value is undefined', - value: undefined, - expectation: false - }, - { - testCase: 'input value is empty', - value: '', - expectation: false - } - - ].forEach(({ testCase, value, expectation }) => { - it(`| ${testCase}, is a valid profile: ${expectation}`, () => { - // call - const callResult = stringUtils.validateSyntax('PROFILE_NAME', value); - // verify - expect(callResult).equal(expectation); - }); - }); - - describe('# test syntax for profile name', () => { - [ - { - testCase: 'input value is with non alphanumeric characters', - value: 'default-!!!???09', - expectation: false - }, - { - testCase: 'input value is with non alphanumeric characters test 2', - value: 'http://lambda.arn.com', - expectation: false - }, - { - testCase: 'input value is all consisted of non alphanumeric characters', - value: '://!@#$%^&*()<>?_', - expectation: false - }, - { - testCase: 'input value includes non-latin character', - value: '中文 にほんご', - expectation: false - }, - { - testCase: 'input value is a valid profile name', - value: 'askProfile', - expectation: true - }, - { - testCase: 'input value is environment profile name', - value: '__ENVIRONMENT_ASK_PROFILE__', - expectation: false - } + describe("# test function validateSyntax", () => { + [ + { + testCase: "input value is null", + value: null, + expectation: false, + }, + { + testCase: "input value is undefined", + value: undefined, + expectation: false, + }, + { + testCase: "input value is empty", + value: "", + expectation: false, + }, + ].forEach(({testCase, value, expectation}) => { + it(`| ${testCase}, is a valid profile: ${expectation}`, () => { + // call + const callResult = stringUtils.validateSyntax("PROFILE_NAME", value); + // verify + expect(callResult).equal(expectation); + }); + }); - ].forEach(({ testCase, value, expectation }) => { - it(`| ${testCase}, is a valid profile: ${expectation}`, () => { - // call - const callResult = stringUtils.validateSyntax('PROFILE_NAME', value); - // verify - expect(callResult).equal(expectation); - }); - }); + describe("# test syntax for profile name", () => { + [ + { + testCase: "input value is with non alphanumeric characters", + value: "default-!!!???09", + expectation: false, + }, + { + testCase: "input value is with non alphanumeric characters test 2", + value: "http://lambda.arn.com", + expectation: false, + }, + { + testCase: "input value is all consisted of non alphanumeric characters", + value: "://!@#$%^&*()<>?_", + expectation: false, + }, + { + testCase: "input value includes non-latin character", + value: "中文 にほんご", + expectation: false, + }, + { + testCase: "input value is a valid profile name", + value: "askProfile", + expectation: true, + }, + { + testCase: "input value is environment profile name", + value: "__ENVIRONMENT_ASK_PROFILE__", + expectation: false, + }, + ].forEach(({testCase, value, expectation}) => { + it(`| ${testCase}, is a valid profile: ${expectation}`, () => { + // call + const callResult = stringUtils.validateSyntax("PROFILE_NAME", value); + // verify + expect(callResult).equal(expectation); }); + }); }); + }); }); diff --git a/test/unit/utils/url-utils-test.js b/test/unit/utils/url-utils-test.js index 616b97bf..3ef00a17 100644 --- a/test/unit/utils/url-utils-test.js +++ b/test/unit/utils/url-utils-test.js @@ -1,295 +1,300 @@ -const { expect } = require('chai'); +const {expect} = require("chai"); -const urlUtility = require('@src/utils/url-utils'); +const urlUtility = require("../../../lib/utils/url-utils"); -describe('Utils test - url utility', () => { - describe('# test function isValidUrl', () => { - [ - { - testCase: 'input url string is null', - urlString: null, - expectation: false - }, - { - testCase: 'input url string is undefined', - urlString: undefined, - expectation: false - }, - { - testCase: 'input url string is empty', - urlString: '', - expectation: false - }, - { - testCase: 'input url string is blank', - urlString: ' ', - expectation: false - }, - { - testCase: 'input url is not a string', - urlString: 12323, - expectation: false - }, - { - testCase: 'input url string is random string', - urlString: 'aaaaaaaaaaaaabbbbbbbbbbbsssssssssssssss', - expectation: false - }, - { - testCase: 'input url string does not have protocol', - urlString: 'www.abc.com', - expectation: false - }, - { - testCase: 'input url string is http', - urlString: 'http://test.tail', - expectation: true - }, - { - testCase: 'input url string is https', - urlString: 'https://test.safe', - expectation: true - } - ].forEach(({ testCase, urlString, expectation }) => { - it(`| ${testCase}, expect isValidResult ${expectation}`, () => { - // call - const callResult = urlUtility.isValidUrl(urlString); - // verify - expect(callResult).equal(expectation); - }); - }); +describe("Utils test - url utility", () => { + describe("# test function isValidUrl", () => { + [ + { + testCase: "input url string is null", + urlString: null, + expectation: false, + }, + { + testCase: "input url string is undefined", + urlString: undefined, + expectation: false, + }, + { + testCase: "input url string is empty", + urlString: "", + expectation: false, + }, + { + testCase: "input url string is blank", + urlString: " ", + expectation: false, + }, + { + testCase: "input url is not a string", + urlString: 12323, + expectation: false, + }, + { + testCase: "input url string is random string", + urlString: "aaaaaaaaaaaaabbbbbbbbbbbsssssssssssssss", + expectation: false, + }, + { + testCase: "input url string does not have protocol", + urlString: "www.abc.com", + expectation: false, + }, + { + testCase: "input url string is http", + urlString: "http://test.tail", + expectation: true, + }, + { + testCase: "input url string is https", + urlString: "https://test.safe", + expectation: true, + }, + ].forEach(({testCase, urlString, expectation}) => { + it(`| ${testCase}, expect isValidResult ${expectation}`, () => { + // call + const callResult = urlUtility.isValidUrl(urlString); + // verify + expect(callResult).equal(expectation); + }); }); + }); - describe('# test function isLambdaArn', () => { - [ - { - testCase: 'input url string is null', - urlString: null, - expectation: false - }, - { - testCase: 'input url string is undefined', - urlString: undefined, - expectation: false - }, - { - testCase: 'input url string is empty', - urlString: '', - expectation: false - }, - { - testCase: 'input url string is blank', - urlString: ' ', - expectation: false - }, - { - testCase: 'input url string is random string', - urlString: 'aaaaaaaaaaaaabbbbbbbbbbbsssssssssssssss', - expectation: false - }, - { - testCase: 'input url string is http', - urlString: 'http://lambda.arn.com', - expectation: false - }, - { - testCase: 'input url string is https', - urlString: 'https://test.com', - expectation: false - }, - { - testCase: 'input url string is invalid ARN1', - urlString: 'arn:aws:lambda:function:', - expectation: false - }, - { - testCase: 'input url string is invalid ARN2', - urlString: 'arns:lambda:ap-southeast-2:123456789012:function:Cadsfase:1.0', - expectation: false - }, - { - testCase: 'input url string is invalid ARN3', - urlString: 'arn:aws:lambda:ap-southeast-2:function:Cadsfase:1.0', - expectation: false - }, - { - testCase: 'input string is a valid lambda ARN1', - urlString: 'arn:aws:lambda:us-east-1:359620628909:function:ask-custom-skill-sample-nodejs-fact-default', - expectation: true - }, - { - testCase: 'input string is a valid lambda ARN2', - urlString: 'arn:aws:lambda:eu-west-1:359620628909:function:ask-custom-S3Sleep', - expectation: true - }, - { - testCase: 'input string is a valid lambda ARN3 with version', - urlString: 'arn:aws:lambda:ap-southeast-2:123456789012:function:Cadsfase:1.0', - expectation: true - } - ].forEach(({ testCase, urlString, expectation }) => { - it(`| ${testCase}, expect isLambdaArn ${expectation}`, () => { - // call - const callResult = urlUtility.isLambdaArn(urlString); - // verify - expect(callResult).equal(expectation); - }); - }); + describe("# test function isLambdaArn", () => { + [ + { + testCase: "input url string is null", + urlString: null, + expectation: false, + }, + { + testCase: "input url string is undefined", + urlString: undefined, + expectation: false, + }, + { + testCase: "input url string is empty", + urlString: "", + expectation: false, + }, + { + testCase: "input url string is blank", + urlString: " ", + expectation: false, + }, + { + testCase: "input url string is random string", + urlString: "aaaaaaaaaaaaabbbbbbbbbbbsssssssssssssss", + expectation: false, + }, + { + testCase: "input url string is http", + urlString: "http://lambda.arn.com", + expectation: false, + }, + { + testCase: "input url string is https", + urlString: "https://test.com", + expectation: false, + }, + { + testCase: "input url string is invalid ARN1", + urlString: "arn:aws:lambda:function:", + expectation: false, + }, + { + testCase: "input url string is invalid ARN2", + urlString: "arns:lambda:ap-southeast-2:123456789012:function:Cadsfase:1.0", + expectation: false, + }, + { + testCase: "input url string is invalid ARN3", + urlString: "arn:aws:lambda:ap-southeast-2:function:Cadsfase:1.0", + expectation: false, + }, + { + testCase: "input string is a valid lambda ARN1", + urlString: "arn:aws:lambda:us-east-1:359620628909:function:ask-custom-skill-sample-nodejs-fact-default", + expectation: true, + }, + { + testCase: "input string is a valid lambda ARN2", + urlString: "arn:aws:lambda:eu-west-1:359620628909:function:ask-custom-S3Sleep", + expectation: true, + }, + { + testCase: "input string is a valid lambda ARN3 with version", + urlString: "arn:aws:lambda:ap-southeast-2:123456789012:function:Cadsfase:1.0", + expectation: true, + }, + ].forEach(({testCase, urlString, expectation}) => { + it(`| ${testCase}, expect isLambdaArn ${expectation}`, () => { + // call + const callResult = urlUtility.isLambdaArn(urlString); + // verify + expect(callResult).equal(expectation); + }); }); + }); - describe('# test function isHttpsUrl', () => { - [ - { - testCase: 'input url string is null', - urlString: null, - expectation: false - }, - { - testCase: 'input url string is undefined', - urlString: undefined, - expectation: false - }, - { - testCase: 'input url string is empty', - urlString: '', - expectation: false - }, - { - testCase: 'input url string is blank', - urlString: ' ', - expectation: false - }, - { - testCase: 'input url string is random string', - urlString: 'aaaaaaaaaaaaabbbbbbbbbbbsssssssssssssss', - expectation: false - }, - { - testCase: 'input url string is http', - urlString: 'http://lambda.arn.com', - expectation: false - }, - { - testCase: 'input url string is https', - urlString: 'https://test.com', - expectation: true - }, - { - testCase: 'input string is a valid lambda ARN1', - urlString: 'arn:aws:lambda:us-east-1:359620628909:function:ask-custom-skill-sample-nodejs-fact-default', - expectation: false - } - ].forEach(({ testCase, urlString, expectation }) => { - it(`| ${testCase}, expect isHttpsUrl ${expectation}`, () => { - // call - const callResult = urlUtility.isHttpsUrl(urlString); - // verify - expect(callResult).equal(expectation); - }); - }); + describe("# test function isHttpsUrl", () => { + [ + { + testCase: "input url string is null", + urlString: null, + expectation: false, + }, + { + testCase: "input url string is undefined", + urlString: undefined, + expectation: false, + }, + { + testCase: "input url string is empty", + urlString: "", + expectation: false, + }, + { + testCase: "input url string is blank", + urlString: " ", + expectation: false, + }, + { + testCase: "input url string is random string", + urlString: "aaaaaaaaaaaaabbbbbbbbbbbsssssssssssssss", + expectation: false, + }, + { + testCase: "input url string is http", + urlString: "http://lambda.arn.com", + expectation: false, + }, + { + testCase: "input url string is https", + urlString: "https://test.com", + expectation: true, + }, + { + testCase: "input string is a valid lambda ARN1", + urlString: "arn:aws:lambda:us-east-1:359620628909:function:ask-custom-skill-sample-nodejs-fact-default", + expectation: false, + }, + ].forEach(({testCase, urlString, expectation}) => { + it(`| ${testCase}, expect isHttpsUrl ${expectation}`, () => { + // call + const callResult = urlUtility.isHttpsUrl(urlString); + // verify + expect(callResult).equal(expectation); + }); }); + }); - describe('# test function isUrlOfficialTemplate', () => { - [ - { - testCase: 'input url string is null', - urlString: null, - expectation: false - }, - { - testCase: 'input url string is undefined', - urlString: undefined, - expectation: false - }, - { - testCase: 'input url string is empty', - urlString: '', - expectation: false - }, - { - testCase: 'input url string is blank', - urlString: ' ', - expectation: false - }, - { - testCase: 'input url string is random string', - urlString: 'aaaaaaaaaaaaabbbbbbbbbbbsssssssssssssss', - expectation: false - }, - { - testCase: 'input url is git url but is not an alexa url', - urlString: 'https://github.com/airbnb/javascript.git', - expectation: false - }, - { - testCase: 'input url string is not an alexa url', - urlString: 'https://github.com/airbnb/javascript', - expectation: false - }, - { - testCase: 'input url string is an alexa github url', - urlString: 'https://github.com/alexa/skill-sample-nodejs-hello-world.git', - expectation: true - } - ].forEach(({ testCase, urlString, expectation }) => { - it(`| ${testCase}, expect isUrlOfficialTemplate ${expectation}`, () => { - // call - const callResult = urlUtility.isUrlOfficialTemplate(urlString); - // verify - expect(callResult).equal(expectation); - }); - }); + describe("# test function isUrlOfficialTemplate", () => { + [ + { + testCase: "input url string is null", + urlString: null, + expectation: false, + }, + { + testCase: "input url string is undefined", + urlString: undefined, + expectation: false, + }, + { + testCase: "input url string is empty", + urlString: "", + expectation: false, + }, + { + testCase: "input url string is blank", + urlString: " ", + expectation: false, + }, + { + testCase: "input url string is random string", + urlString: "aaaaaaaaaaaaabbbbbbbbbbbsssssssssssssss", + expectation: false, + }, + { + testCase: "input url is git url but is not an alexa url", + urlString: "https://github.com/airbnb/javascript.git", + expectation: false, + }, + { + testCase: "input url string is not an alexa url", + urlString: "https://github.com/airbnb/javascript", + expectation: false, + }, + { + testCase: "input url string is an alexa github url", + urlString: "https://github.com/alexa/skill-sample-nodejs-hello-world.git", + expectation: true, + }, + { + testCase: "input url is not git url but has an alexa in the path", + urlString: "https://maliciousurl.com/alexa/javascript.git", + expectation: false, + }, + ].forEach(({testCase, urlString, expectation}) => { + it(`| ${testCase}, expect isUrlOfficialTemplate ${expectation}`, () => { + // call + const callResult = urlUtility.isUrlOfficialTemplate(urlString); + // verify + expect(callResult).equal(expectation); + }); }); + }); - describe('# test function isUrlWithJsonExtension', () => { - [ - { - testCase: 'input url string is null', - urlString: null, - expectation: false - }, - { - testCase: 'input url string is undefined', - urlString: undefined, - expectation: false - }, - { - testCase: 'input url string is empty', - urlString: '', - expectation: false - }, - { - testCase: 'input url string is blank', - urlString: ' ', - expectation: false - }, - { - testCase: 'input url string is random string', - urlString: 'aaaaaaaaaaaaabbbbbbbbbbbsssssssssssssss', - expectation: false - }, - { - testCase: 'input url is git url', - urlString: 'https://github.com/airbnb/javascript.git', - expectation: false - }, - { - testCase: 'input url is url with querry params', - urlString: 'https://github.com/airbnb/javascript.git?d=y&w=n', - expectation: false - }, - { - testCase: 'input url string is json url', - urlString: 'https://github.com/airbnb/javascript.json', - expectation: true - } - ].forEach(({ testCase, urlString, expectation }) => { - it(`| ${testCase}, expect isUrlWithJsonExtension ${expectation}`, () => { - // call - const callResult = urlUtility.isUrlWithJsonExtension(urlString); - // verify - expect(callResult).equal(expectation); - }); - }); + describe("# test function isUrlWithJsonExtension", () => { + [ + { + testCase: "input url string is null", + urlString: null, + expectation: false, + }, + { + testCase: "input url string is undefined", + urlString: undefined, + expectation: false, + }, + { + testCase: "input url string is empty", + urlString: "", + expectation: false, + }, + { + testCase: "input url string is blank", + urlString: " ", + expectation: false, + }, + { + testCase: "input url string is random string", + urlString: "aaaaaaaaaaaaabbbbbbbbbbbsssssssssssssss", + expectation: false, + }, + { + testCase: "input url is git url", + urlString: "https://github.com/airbnb/javascript.git", + expectation: false, + }, + { + testCase: "input url is url with querry params", + urlString: "https://github.com/airbnb/javascript.git?d=y&w=n", + expectation: false, + }, + { + testCase: "input url string is json url", + urlString: "https://github.com/airbnb/javascript.json", + expectation: true, + }, + ].forEach(({testCase, urlString, expectation}) => { + it(`| ${testCase}, expect isUrlWithJsonExtension ${expectation}`, () => { + // call + const callResult = urlUtility.isUrlWithJsonExtension(urlString); + // verify + expect(callResult).equal(expectation); + }); }); + }); }); diff --git a/test/unit/utils/zip-utils-test.js b/test/unit/utils/zip-utils-test.js index 4624a5ed..dcba5e2c 100644 --- a/test/unit/utils/zip-utils-test.js +++ b/test/unit/utils/zip-utils-test.js @@ -1,253 +1,244 @@ -const fs = require('fs'); -const tmp = require('tmp'); -const sinon = require('sinon'); -const proxyquire = require('proxyquire'); -const { expect } = require('chai'); - -const zipUtils = require('@src/utils/zip-utils'); -const httpClient = require('@src/clients/http-client'); -const Messenger = require('@src/view/messenger'); -const CONSTANTS = require('@src/utils/constants'); - -describe('Utils test - zip utility', () => { - const TEST_SRC = 'TEST_SRC'; - const TEST_OUTPUT_DIR = 'TEST_OUTPUT_DIR'; - const TEST_ERROR = 'TEST_ERROR'; - const TEST_ZIP_FILE_PATH = 'TEST_ZIP_FILE_PATH'; - const TEST_REMOTE_ZIP_URL = 'TEST_REMOTE_ZIP_URL'; - const TEST_REMOTE_ZIP_RESPONSE = { body: 'TEST_REMOTE_ZIP_RESPONSE' }; - - describe('# test function createTempZip', () => { - beforeEach(() => { - sinon.stub(tmp, 'tmpNameSync').withArgs({ - prefix: 'askcli_temp_', - postfix: '.zip', - dir: TEST_OUTPUT_DIR - }).callsFake(() => TEST_ZIP_FILE_PATH); - - new Messenger({}); - }); +const fs = require("fs"); +const tmp = require("tmp"); +const sinon = require("sinon"); +const proxyquire = require("proxyquire"); +const {expect} = require("chai"); + +const zipUtils = require("../../../lib/utils/zip-utils"); +const httpClient = require("../../../lib/clients/http-client"); +const Messenger = require("../../../lib/view/messenger"); +const CONSTANTS = require("../../../lib/utils/constants"); + +describe("Utils test - zip utility", () => { + const TEST_SRC = "TEST_SRC"; + const TEST_ERROR = "TEST_ERROR"; + const TEST_ZIP_FILE_PATH = "TEST_ZIP_FILE_PATH"; + const TEST_REMOTE_ZIP_URL = "TEST_REMOTE_ZIP_URL"; + const TEST_REMOTE_ZIP_RESPONSE = {body: "TEST_REMOTE_ZIP_RESPONSE"}; + + describe("# test function createTempZip", () => { + beforeEach(() => { + sinon + .stub(tmp, "tmpNameSync") + .withArgs({ + prefix: "askcli_temp_", + postfix: ".zip", + }) + .callsFake(() => TEST_ZIP_FILE_PATH); + + new Messenger({}); + }); - afterEach(() => { - sinon.restore(); - Messenger.getInstance().dispose(); - }); + afterEach(() => { + sinon.restore(); + Messenger.getInstance().dispose(); + }); - it('| call back error when src file is not set', (done) => { - // call - zipUtils.createTempZip(null, TEST_OUTPUT_DIR, (error) => { - // verify - expect(error).equal('Zip file path must be set.'); - done(); - }); - }); + it("| call back error when src file is not set", (done) => { + // call + zipUtils.createTempZip(null, (error) => { + // verify + expect(error).equal("Zip file path must be set."); + done(); + }); + }); - it('| call back error when outputDir is not set', (done) => { - // call - zipUtils.createTempZip(TEST_SRC, null, (error) => { - // verify - expect(error).equal('Zip file output path must be set.'); - done(); - }); - }); + it("| call back error when access file fail", (done) => { + // setup + sinon.stub(fs, "access").callsArgWith(2, TEST_ERROR); - it('| call back error when access file fail', (done) => { - // setup - sinon.stub(fs, 'access').callsArgWith(2, TEST_ERROR); + // call + zipUtils.createTempZip(TEST_SRC, (error) => { + // verify + expect(error).equal(`File access error. ${TEST_ERROR}`); + done(); + }); + }); - // call - zipUtils.createTempZip(TEST_SRC, TEST_OUTPUT_DIR, (error) => { - // verify - expect(error).equal(`File access error. ${TEST_ERROR}`); - done(); - }); - }); + it("| when input file is a zip, callback original filePath and warn skip message", (done) => { + const src = "test.zip"; + + // setup + sinon.stub(fs, "access").callsArgWith(2); + sinon.stub(Messenger.getInstance(), "debug"); + + // call + zipUtils.createTempZip(src, (error, response) => { + // verify + expect(Messenger.getInstance().debug.args[0][0]).equal(`The source file ${src} has already been compressed. Skip the zipping`); + expect(error).equal(null); + expect(response).equal(src); + done(); + }); + }); - it('| when input file is a zip, callback original filePath and warn skip message', (done) => { - const src = 'test.zip'; - - // setup - sinon.stub(fs, 'access').callsArgWith(2); - sinon.stub(Messenger.getInstance(), 'debug'); - - // call - zipUtils.createTempZip(src, TEST_OUTPUT_DIR, (error, response) => { - // verify - expect(Messenger.getInstance().debug.args[0][0]).equal(`The source file ${src} has already been compressed. Skip the zipping`); - expect(error).equal(null); - expect(response).equal(src); - done(); - }); - }); + it("| when input file is a jar, callback original filePath and warn skip message", (done) => { + const src = "test.jar"; + + // setup + sinon.stub(fs, "access").callsArgWith(2); + sinon.stub(Messenger.getInstance(), "debug"); + + // call + zipUtils.createTempZip(src, (error, response) => { + // verify + expect(Messenger.getInstance().debug.args[0][0]).equal(`The source file ${src} has already been compressed. Skip the zipping`); + expect(error).equal(null); + expect(response).equal(src); + done(); + }); + }); - it('| when input file is a jar, callback original filePath and warn skip message', (done) => { - const src = 'test.jar'; - - // setup - sinon.stub(fs, 'access').callsArgWith(2); - sinon.stub(Messenger.getInstance(), 'debug'); - - // call - zipUtils.createTempZip(src, TEST_OUTPUT_DIR, (error, response) => { - // verify - expect(Messenger.getInstance().debug.args[0][0]).equal(`The source file ${src} has already been compressed. Skip the zipping`); - expect(error).equal(null); - expect(response).equal(src); - done(); - }); + describe("# test archive inside the createTempZip function", () => { + let proxyZipUtils; + let archiveOnStub, archiveFileStub, archiveGlobStub; + let writeStreamOnStub; + + beforeEach(() => { + archiveOnStub = sinon.stub(); + archiveFileStub = sinon.stub(); + archiveGlobStub = sinon.stub(); + const archiveStubObj = { + on: archiveOnStub, + pipe: () => {}, + file: archiveFileStub, + glob: archiveGlobStub, + finalize: () => {}, + }; + proxyZipUtils = proxyquire("../../../lib/utils/zip-utils", { + archiver: () => archiveStubObj, + }); + sinon.stub(fs, "access").callsArgWith(2); + sinon.stub(Messenger.getInstance(), "debug"); + writeStreamOnStub = sinon.stub(); + sinon.stub(fs, "createWriteStream").returns({ + on: writeStreamOnStub, }); + }); - describe('# test archive inside the createTempZip function', () => { - let proxyZipUtils; - let archiveOnStub, archiveFileStub, archiveGlobStub; - let writeStreamOnStub; - - beforeEach(() => { - archiveOnStub = sinon.stub(); - archiveFileStub = sinon.stub(); - archiveGlobStub = sinon.stub(); - const archiveStubObj = { - on: archiveOnStub, - pipe: () => {}, - file: archiveFileStub, - glob: archiveGlobStub, - finalize: () => {} - }; - proxyZipUtils = proxyquire('@src/utils/zip-utils', { - archiver: () => archiveStubObj - }); - sinon.stub(fs, 'access').callsArgWith(2); - sinon.stub(Messenger.getInstance(), 'debug'); - writeStreamOnStub = sinon.stub(); - sinon.stub(fs, 'createWriteStream').returns({ - on: writeStreamOnStub - }); - }); - - it('| when input src is folder and archive error occurs, expect callback archive error', (done) => { - // setup - sinon.stub(fs, 'statSync').returns({ - isFile: () => false, - isDirectory: () => false - }); - archiveOnStub.callsArgWith(1, 'error'); - // call - proxyZipUtils.createTempZip(TEST_SRC, TEST_OUTPUT_DIR, (error, response) => { - // verify - expect(fs.createWriteStream.args[0][0]).equal(TEST_ZIP_FILE_PATH); - expect(error).equal('Archive error. error'); - expect(response).equal(undefined); - done(); - }); - }); - - it('| when input src is folder and src is file, expect zip file and callback when wrtieStream close', (done) => { - // setup - sinon.stub(fs, 'statSync').returns({ - isFile: () => true, - isDirectory: () => false - }); - writeStreamOnStub.callsArgWith(1); - // call - proxyZipUtils.createTempZip(TEST_SRC, TEST_OUTPUT_DIR, (error, response) => { - // verify - expect(fs.createWriteStream.args[0][0]).equal(TEST_ZIP_FILE_PATH); - expect(archiveFileStub.args[0][0]).equal(TEST_SRC); - expect(archiveFileStub.args[0][1]).deep.equal({ name: TEST_SRC }); - expect(error).equal(null); - expect(response).equal(TEST_ZIP_FILE_PATH); - done(); - }); - }); - - it('| when input src is folder and src is directory, expect zip file and callback when wrtieStream close', (done) => { - // setup - sinon.stub(fs, 'statSync').returns({ - isFile: () => false, - isDirectory: () => true - }); - writeStreamOnStub.callsArgWith(1); - // call - proxyZipUtils.createTempZip(TEST_SRC, TEST_OUTPUT_DIR, (error, response) => { - // verify - expect(fs.createWriteStream.args[0][0]).equal(TEST_ZIP_FILE_PATH); - expect(archiveGlobStub.args[0][0]).equal('**/*'); - expect(archiveGlobStub.args[0][1]).deep.equal({ - cwd: TEST_SRC, - ignore: TEST_ZIP_FILE_PATH - }); - expect(error).equal(null); - expect(response).equal(TEST_ZIP_FILE_PATH); - done(); - }); - }); + it("| when input src is folder and archive error occurs, expect callback archive error", (done) => { + // setup + sinon.stub(fs, "statSync").returns({ + isFile: () => false, + isDirectory: () => false, }); + archiveOnStub.callsArgWith(1, "error"); + // call + proxyZipUtils.createTempZip(TEST_SRC, (error, response) => { + // verify + expect(fs.createWriteStream.args[0][0]).equal(TEST_ZIP_FILE_PATH); + expect(error).equal("Archive error. error"); + expect(response).equal(undefined); + done(); + }); + }); + it("| when input src is folder and src is file, expect zip file and callback when wrtieStream close", (done) => { + // setup + sinon.stub(fs, "statSync").returns({ + isFile: () => true, + isDirectory: () => false, + }); + writeStreamOnStub.callsArgWith(1); + // call + proxyZipUtils.createTempZip(TEST_SRC, (error, response) => { + // verify + expect(fs.createWriteStream.args[0][0]).equal(TEST_ZIP_FILE_PATH); + expect(archiveFileStub.args[0][0]).equal(TEST_SRC); + expect(archiveFileStub.args[0][1]).deep.equal({name: TEST_SRC}); + expect(error).equal(null); + expect(response).equal(TEST_ZIP_FILE_PATH); + done(); + }); + }); - afterEach(() => { - sinon.restore(); - Messenger.getInstance().dispose(); + it("| when input src is folder and src is directory, expect zip file and callback when wrtieStream close", (done) => { + // setup + sinon.stub(fs, "statSync").returns({ + isFile: () => false, + isDirectory: () => true, + }); + writeStreamOnStub.callsArgWith(1); + // call + proxyZipUtils.createTempZip(TEST_SRC, (error, response) => { + // verify + expect(fs.createWriteStream.args[0][0]).equal(TEST_ZIP_FILE_PATH); + expect(archiveGlobStub.args[0][0]).equal("**/*"); + expect(archiveGlobStub.args[0][1]).deep.equal({ + cwd: TEST_SRC, + ignore: TEST_ZIP_FILE_PATH, + }); + expect(error).equal(null); + expect(response).equal(TEST_ZIP_FILE_PATH); + done(); }); + }); }); - describe('# test function unzipRemoteZipFile', () => { - const stubRequest = sinon.stub(); - const mockAdmZip = function Mock() { - return { - extractAllTo: stubRequest - }; - }; - const proxyZipUtil = proxyquire('@src/utils/zip-utils', { 'adm-zip': mockAdmZip }); - - afterEach(() => { - sinon.restore(); - }); + afterEach(() => { + sinon.restore(); + Messenger.getInstance().dispose(); + }); + }); + + describe("# test function unzipRemoteZipFile", () => { + const stubRequest = sinon.stub(); + const mockAdmZip = function Mock() { + return { + extractAllTo: stubRequest, + }; + }; + const proxyZipUtil = proxyquire("../../../lib/utils/zip-utils", {"adm-zip": mockAdmZip}); + + afterEach(() => { + sinon.restore(); + }); - it('| get through httpClient fails, expect error callback', (done) => { - // setup - sinon.stub(httpClient, 'request').callsArgWith(3, 'get error'); - // test - zipUtils.unzipRemoteZipFile(TEST_REMOTE_ZIP_URL, TEST_ZIP_FILE_PATH, false, (err) => { - // verify - expect(httpClient.request.args[0][0].url).equal(TEST_REMOTE_ZIP_URL); - expect(httpClient.request.args[0][0].method).equal(CONSTANTS.HTTP_REQUEST.VERB.GET); - expect(httpClient.request.args[0][0].encoding).equal(null); - expect(httpClient.request.args[0][1]).equal('get-zip-file'); - expect(httpClient.request.args[0][2]).equal(false); - expect(err).equal('get error'); - done(); - }); - }); + it("| get through httpClient fails, expect error callback", (done) => { + // setup + sinon.stub(httpClient, "request").callsArgWith(3, "get error"); + // test + zipUtils.unzipRemoteZipFile(TEST_REMOTE_ZIP_URL, TEST_ZIP_FILE_PATH, false, (err) => { + // verify + expect(httpClient.request.args[0][0].url).equal(TEST_REMOTE_ZIP_URL); + expect(httpClient.request.args[0][0].method).equal(CONSTANTS.HTTP_REQUEST.VERB.GET); + expect(httpClient.request.args[0][0].encoding).equal(null); + expect(httpClient.request.args[0][1]).equal("get-zip-file"); + expect(httpClient.request.args[0][2]).equal(false); + expect(err).equal("get error"); + done(); + }); + }); - it('| admZip extract failure, expect error callback', (done) => { - // setup - sinon.stub(httpClient, 'request').callsArgWith(3, null, TEST_REMOTE_ZIP_RESPONSE); - stubRequest.throws('extract error'); - // test - proxyZipUtil.unzipRemoteZipFile(TEST_REMOTE_ZIP_URL, TEST_ZIP_FILE_PATH, false, (err) => { - // verify - expect(httpClient.request.args[0][0].url).equal(TEST_REMOTE_ZIP_URL); - expect(httpClient.request.args[0][0].method).equal(CONSTANTS.HTTP_REQUEST.VERB.GET); - expect(httpClient.request.args[0][0].encoding).equal(null); - expect(httpClient.request.args[0][1]).equal('get-zip-file'); - expect(httpClient.request.args[0][2]).equal(false); - expect(stubRequest.args[0][0]).deep.equal(TEST_ZIP_FILE_PATH); - expect(err.name).equal('extract error'); - done(); - }); - }); + it("| admZip extract failure, expect error callback", (done) => { + // setup + sinon.stub(httpClient, "request").callsArgWith(3, null, TEST_REMOTE_ZIP_RESPONSE); + stubRequest.throws("extract error"); + // test + proxyZipUtil.unzipRemoteZipFile(TEST_REMOTE_ZIP_URL, TEST_ZIP_FILE_PATH, false, (err) => { + // verify + expect(httpClient.request.args[0][0].url).equal(TEST_REMOTE_ZIP_URL); + expect(httpClient.request.args[0][0].method).equal(CONSTANTS.HTTP_REQUEST.VERB.GET); + expect(httpClient.request.args[0][0].encoding).equal(null); + expect(httpClient.request.args[0][1]).equal("get-zip-file"); + expect(httpClient.request.args[0][2]).equal(false); + expect(stubRequest.args[0][0]).deep.equal(TEST_ZIP_FILE_PATH); + expect(err.name).equal("extract error"); + done(); + }); + }); - it('| admZip extract success, expect no error callback', (done) => { - // setup - sinon.stub(httpClient, 'request').callsArgWith(3, null, TEST_REMOTE_ZIP_RESPONSE); - stubRequest.returns(null); - // test - proxyZipUtil.unzipRemoteZipFile(TEST_REMOTE_ZIP_URL, TEST_ZIP_FILE_PATH, false, (err) => { - // verify - expect(stubRequest.args[0][0]).deep.equal(TEST_ZIP_FILE_PATH); - expect(err).equal(undefined); - done(); - }); - }); + it("| admZip extract success, expect no error callback", (done) => { + // setup + sinon.stub(httpClient, "request").callsArgWith(3, null, TEST_REMOTE_ZIP_RESPONSE); + stubRequest.returns(null); + // test + proxyZipUtil.unzipRemoteZipFile(TEST_REMOTE_ZIP_URL, TEST_ZIP_FILE_PATH, false, (err) => { + // verify + expect(stubRequest.args[0][0]).deep.equal(TEST_ZIP_FILE_PATH); + expect(err).equal(undefined); + done(); + }); }); + }); }); diff --git a/test/unit/view/cli-repl-view-test.js b/test/unit/view/cli-repl-view-test.js deleted file mode 100644 index d2d6eef5..00000000 --- a/test/unit/view/cli-repl-view-test.js +++ /dev/null @@ -1,297 +0,0 @@ -const { expect } = require('chai'); -const proxyquire = require('proxyquire'); -const sinon = require('sinon'); - -const Messenger = require('@src/view/messenger'); -const SpinnerView = require('@src/view/spinner-view'); - -describe('View test - cli repl view test', () => { - const TEST_MESSAGE = 'TEST_MESSAGE'; - let infoStub; - let removeListenersStub; - let defineCommandStub; - let onStub; - let replStub; - let closeStub; - - beforeEach(() => { - infoStub = sinon.stub(); - removeListenersStub = sinon.stub(); - defineCommandStub = sinon.stub(); - onStub = sinon.stub(); - closeStub = sinon.stub(); - replStub = { - start: () => ({ - removeAllListeners: removeListenersStub, - commands: { - help: 'help' - }, - defineCommand: defineCommandStub, - on: onStub, - close: closeStub - }) - }; - sinon.stub(Messenger, 'getInstance').returns({ - info: infoStub - }); - }); - - afterEach(() => { - sinon.restore(); - }); - - describe('# inspect correctness of the constructor', () => { - it('| initialize CliReplView with custom prompt', () => { - // setup - const ProxyCliReplView = proxyquire('@src/view/cli-repl-view', { - repl: replStub - }); - - // call - new ProxyCliReplView({ prompt: TEST_MESSAGE }); - - // verify - expect(removeListenersStub.callCount).equal(3); - expect(defineCommandStub.callCount).equal(1); - expect(onStub.callCount).equal(1); - }); - - it('| initialize with custom headers array', () => { - // setup - const header = TEST_MESSAGE; - const ProxyCliReplView = proxyquire('@src/view/cli-repl-view', { - repl: replStub - }); - - // call - const cliReplView = new ProxyCliReplView({ header }); - - // verify - expect(cliReplView.header).equal(header); - }); - - it('| initialize with custom eval function', () => { - // setup - const ProxyCliReplView = proxyquire('@src/view/cli-repl-view', { - repl: replStub - }); - const evalFunc = (cmd, context, filename, callback) => { - callback(null, 'Hello'); - }; - - // call - const cliReplView = new ProxyCliReplView({ evalFunc }); - - // verify - expect(cliReplView.eval).equal(evalFunc); - }); - - it('| initialize with custom footer array', () => { - // setup - const footer = TEST_MESSAGE; - const ProxyCliReplView = proxyquire('@src/view/cli-repl-view', { - repl: replStub - }); - - // call - const cliReplView = new ProxyCliReplView({ footer }); - - // verify - expect(cliReplView.footer).equal(footer); - }); - - it('| throw error if configuration is undefined', () => { - // setup - const ProxyCliReplView = proxyquire('@src/view/cli-repl-view', { - repl: replStub - }); - try { - // call - new ProxyCliReplView(); - } catch (err) { - // verify - expect(err).to.match(new RegExp('Cannot have an undefined configuration.')); - } - }); - - it('| throw error if invalid prompt is passed', () => { - // setup - const ProxyCliReplView = proxyquire('@src/view/cli-repl-view', { - repl: replStub - }); - const prompt = 1234; - try { - // call - new ProxyCliReplView({ prompt }); - } catch (err) { - // verify - expect(err).to.match(new RegExp('Prompt must be a non-empty string.')); - } - }); - }); - - describe('# inspect correctness of methods', () => { - afterEach(() => { - sinon.restore(); - }); - - it('| printHeaderFooter call with default options okay.', () => { - // setup - const ProxyCliReplView = proxyquire('@src/view/cli-repl-view', { - repl: replStub - }); - const cliReplView = new ProxyCliReplView({}); - - // call - cliReplView.printHeaderFooter(cliReplView.header); - - // verify - expect(infoStub.callCount).equal(0); - }); - - it('| printHeaderFooter call with custom header option okay.', () => { - // setup - const ProxyCliReplView = proxyquire('@src/view/cli-repl-view', { - repl: replStub - }); - const cliReplView = new ProxyCliReplView({ header: TEST_MESSAGE }); - - // call - cliReplView.printHeaderFooter(cliReplView.header); - - // verify - expect(infoStub.callCount).equal(2); - }); - - it('| printHeaderFooter call with invalid header does print.', () => { - // setup - const header = () => {}; - const ProxyCliReplView = proxyquire('@src/view/cli-repl-view', { - repl: replStub - }); - const cliReplView = new ProxyCliReplView({ header }); - - // call - cliReplView.printHeaderFooter(cliReplView.header); - - // verify - expect(infoStub.callCount).equal(0); - }); - - it('| registerCommand successful', () => { - // setup - const ProxyCliReplView = proxyquire('@src/view/cli-repl-view', { - repl: replStub - }); - const cliReplView = new ProxyCliReplView({}); - const command = { help: TEST_MESSAGE, action: () => {} }; - - // call - cliReplView.registerSpecialCommand(TEST_MESSAGE, command.help, command.action); - - // verify - expect(defineCommandStub.callCount).equal(2); - expect(defineCommandStub.args[0][0]).equal('quit'); - expect(defineCommandStub.args[0][1].help).equal('Quit repl session.'); - expect(defineCommandStub.args[1][0]).equal(TEST_MESSAGE); - }); - - it('| test close method', () => { - // setup - const ProxyCliReplView = proxyquire('@src/view/cli-repl-view', { - repl: replStub - }); - const cliReplView = new ProxyCliReplView({}); - const spinnerStartStub = sinon.stub(SpinnerView.prototype, 'start'); - - // call - cliReplView.startProgressSpinner(TEST_MESSAGE); - cliReplView.close(); - - // verify - expect(spinnerStartStub.calledOnce).equal(true); - expect(closeStub.calledOnce).equal(true); - }); - - it('| test registerQuitFunction method', () => { - // setup - const ProxyCliReplView = proxyquire('@src/view/cli-repl-view', { - repl: replStub - }); - const spinnerTerminateStub = sinon.stub(SpinnerView.prototype, 'terminate'); - const cliReplView = new ProxyCliReplView({}); - replStub.start().on.callsArgWith(1, ''); - const closeEventListener = sinon.stub(); - - // call - cliReplView.registerQuitCommand(closeEventListener); - - // verify - expect(onStub.callCount).equal(2); - expect(removeListenersStub.callCount).equal(4); - expect(defineCommandStub.callCount).equal(2); - expect(defineCommandStub.args[0][1].help).equal('Quit repl session.'); - expect(defineCommandStub.args[1][0]).equal('quit'); - expect(closeEventListener.callCount).equal(1); - expect(spinnerTerminateStub.callCount).equal(1); - }); - - it('| test clearSpecialCommands method', () => { - // setup - const ProxyCliReplView = proxyquire('@src/view/cli-repl-view', { - repl: replStub - }); - const cliReplView = new ProxyCliReplView({}); - - // call - cliReplView.clearSpecialCommands(); - - // verify - expect(removeListenersStub.callCount).equal(4); - expect(removeListenersStub.args[0][0]).equal('SIGINT'); - expect(removeListenersStub.args[1][0]).equal('close'); - }); - }); - - describe('# inspect correctness of spinner view wrapper methods', () => { - it('| updateProgressSpinner okay.', () => { - // setup - const UPDATE_MESSAGE = 'UPDATE_MESSAGE'; - const ProxyCliReplView = proxyquire('@src/view/cli-repl-view', { - repl: replStub - }); - const cliReplView = new ProxyCliReplView({}); - const spinnerStartStub = sinon.stub(SpinnerView.prototype, 'start'); - const spinnerUpdateStub = sinon.stub(SpinnerView.prototype, 'update'); - - // call - cliReplView.startProgressSpinner(TEST_MESSAGE); - cliReplView.updateProgressSpinner(UPDATE_MESSAGE); - - // verify - expect(spinnerStartStub.calledOnce).equal(true); - expect(spinnerStartStub.args[0][0]).equal(TEST_MESSAGE); - expect(spinnerUpdateStub.calledOnce).equal(true); - expect(spinnerUpdateStub.args[0][0]).equal(UPDATE_MESSAGE); - }); - - it('| terminateProgressSpinner okay.', () => { - // setup - const ProxyCliReplView = proxyquire('@src/view/cli-repl-view', { - repl: replStub - }); - const cliReplView = new ProxyCliReplView({}); - - // call - const spinnerStartStub = sinon.stub(SpinnerView.prototype, 'start'); - const spinnerTerminateStub = sinon.stub(SpinnerView.prototype, 'terminate'); - cliReplView.startProgressSpinner(TEST_MESSAGE); - cliReplView.terminateProgressSpinner(); - - // verify - expect(spinnerStartStub.callCount).equal(1); - expect(spinnerStartStub.args[0][0]).equal(TEST_MESSAGE); - expect(spinnerTerminateStub.callCount).equal(1); - }); - }); -}); diff --git a/test/unit/view/cli-repl-view.spec.ts b/test/unit/view/cli-repl-view.spec.ts new file mode 100644 index 00000000..6d47569d --- /dev/null +++ b/test/unit/view/cli-repl-view.spec.ts @@ -0,0 +1,298 @@ +import {expect} from "chai"; +import proxyquire from "proxyquire"; +import sinon from "sinon"; +import path from "path"; + +import Messenger from "../../../lib/view/messenger"; +import SpinnerView from "../../../lib/view/spinner-view"; + +describe("View test - cli repl view test", () => { + const TEST_MESSAGE = "TEST_MESSAGE"; + let infoStub: sinon.SinonStub; + let removeListenersStub: sinon.SinonStub; + let defineCommandStub: sinon.SinonStub; + let onStub: sinon.SinonStub; + let replStub: any; + let closeStub: sinon.SinonStub; + + beforeEach(() => { + infoStub = sinon.stub(); + removeListenersStub = sinon.stub(); + defineCommandStub = sinon.stub(); + onStub = sinon.stub(); + closeStub = sinon.stub(); + replStub = { + start: () => ({ + removeAllListeners: removeListenersStub, + commands: { + help: "help", + }, + defineCommand: defineCommandStub, + on: onStub, + close: closeStub, + }), + }; + sinon.stub(Messenger, "getInstance").returns({ + info: infoStub, + }); + }); + + afterEach(() => { + sinon.restore(); + }); + + describe("# inspect correctness of the constructor", () => { + it("| initialize CliReplView with custom prompt", () => { + // setup + const ProxyCliReplView = proxyquire.noCallThru().load(path.join(__dirname, "..", "..", "..", "lib", "view", "cli-repl-view"), { + repl: replStub, + }); + + // call + new ProxyCliReplView.CliReplView({prompt: TEST_MESSAGE}); + + // verify + expect(removeListenersStub.callCount).equal(3); + expect(defineCommandStub.callCount).equal(1); + expect(onStub.callCount).equal(1); + }); + + it("| initialize with custom headers array", () => { + // setup + const header = TEST_MESSAGE; + const ProxyCliReplView = proxyquire.noCallThru().load(path.join(__dirname, "..", "..", "..", "lib", "view", "cli-repl-view"), { + repl: replStub, + }); + + // call + const cliReplView = new ProxyCliReplView.CliReplView({header}); + + // verify + expect(cliReplView.header).equal(header); + }); + + it("| initialize with custom eval function", () => { + // setup + const ProxyCliReplView = proxyquire.noCallThru().load(path.join(__dirname, "..", "..", "..", "lib", "view", "cli-repl-view"), { + repl: replStub, + }); + const evalFunc = (_cmd: string, _context: any, _filename: any, callback: (error: any, resp: any) => void) => { + callback(null, "Hello"); + }; + + // call + const cliReplView = new ProxyCliReplView.CliReplView({evalFunc}); + + // verify + expect(cliReplView.eval).equal(evalFunc); + }); + + it("| initialize with custom footer array", () => { + // setup + const footer = TEST_MESSAGE; + const ProxyCliReplView = proxyquire.noCallThru().load(path.join(__dirname, "..", "..", "..", "lib", "view", "cli-repl-view"), { + repl: replStub, + }); + + // call + const cliReplView = new ProxyCliReplView.CliReplView({footer}); + + // verify + expect(cliReplView.footer).equal(footer); + }); + + it("| throw error if configuration is undefined", () => { + // setup + const ProxyCliReplView = proxyquire.noCallThru().load(path.join(__dirname, "..", "..", "..", "lib", "view", "cli-repl-view"), { + repl: replStub, + }); + try { + // call + new ProxyCliReplView.CliReplView(); + } catch (err) { + // verify + expect(err).to.match(new RegExp("Cannot have an undefined configuration.")); + } + }); + + it("| throw error if invalid prompt is passed", () => { + // setup + const ProxyCliReplView = proxyquire.noCallThru().load(path.join(__dirname, "..", "..", "..", "lib", "view", "cli-repl-view"), { + repl: replStub, + }); + const prompt = 1234; + try { + // call + new ProxyCliReplView.CliReplView({prompt}); + } catch (err) { + // verify + expect(err).to.match(new RegExp("Prompt must be a non-empty string.")); + } + }); + }); + + describe("# inspect correctness of methods", () => { + afterEach(() => { + sinon.restore(); + }); + + it("| printHeaderFooter call with default options okay.", () => { + // setup + const ProxyCliReplView = proxyquire.noCallThru().load(path.join(__dirname, "..", "..", "..", "lib", "view", "cli-repl-view"), { + repl: replStub, + }); + const cliReplView = new ProxyCliReplView.CliReplView({}); + + // call + cliReplView.printHeaderFooter(cliReplView.header); + + // verify + expect(infoStub.callCount).equal(0); + }); + + it("| printHeaderFooter call with custom header option okay.", () => { + // setup + const ProxyCliReplView = proxyquire.noCallThru().load(path.join(__dirname, "..", "..", "..", "lib", "view", "cli-repl-view"), { + repl: replStub, + }); + const cliReplView = new ProxyCliReplView.CliReplView({header: TEST_MESSAGE}); + + // call + cliReplView.printHeaderFooter(cliReplView.header); + + // verify + expect(infoStub.callCount).equal(2); + }); + + it("| printHeaderFooter call with invalid header does print.", () => { + // setup + const header = () => {}; + const ProxyCliReplView = proxyquire.noCallThru().load(path.join(__dirname, "..", "..", "..", "lib", "view", "cli-repl-view"), { + repl: replStub, + }); + const cliReplView = new ProxyCliReplView.CliReplView({header}); + + // call + cliReplView.printHeaderFooter(cliReplView.header); + + // verify + expect(infoStub.callCount).equal(0); + }); + + it("| registerCommand successful", () => { + // setup + const ProxyCliReplView = proxyquire.noCallThru().load(path.join(__dirname, "..", "..", "..", "lib", "view", "cli-repl-view"), { + repl: replStub, + }); + const cliReplView = new ProxyCliReplView.CliReplView({}); + const command = {help: TEST_MESSAGE, action: () => {}}; + + // call + cliReplView.registerSpecialCommand(TEST_MESSAGE, command.help, command.action); + + // verify + expect(defineCommandStub.callCount).equal(2); + expect(defineCommandStub.args[0][0]).equal("quit"); + expect(defineCommandStub.args[0][1].help).equal("Quit repl session."); + expect(defineCommandStub.args[1][0]).equal(TEST_MESSAGE); + }); + + it("| test close method", () => { + // setup + const ProxyCliReplView = proxyquire.noCallThru().load(path.join(__dirname, "..", "..", "..", "lib", "view", "cli-repl-view"), { + repl: replStub, + }); + const cliReplView = new ProxyCliReplView.CliReplView({}); + const spinnerStartStub = sinon.stub(SpinnerView.prototype, "start"); + + // call + cliReplView.startProgressSpinner(TEST_MESSAGE); + cliReplView.close(); + + // verify + expect(spinnerStartStub.calledOnce).equal(true); + expect(closeStub.calledOnce).equal(true); + }); + + it("| test registerQuitFunction method", () => { + // setup + const ProxyCliReplView = proxyquire.noCallThru().load(path.join(__dirname, "..", "..", "..", "lib", "view", "cli-repl-view"), { + repl: replStub, + }); + const spinnerTerminateStub = sinon.stub(SpinnerView.prototype, "terminate"); + const cliReplView = new ProxyCliReplView.CliReplView({}); + replStub.start().on.callsArgWith(1, ""); + const closeEventListener = sinon.stub(); + + // call + cliReplView.registerQuitCommand(closeEventListener); + + // verify + expect(onStub.callCount).equal(2); + expect(removeListenersStub.callCount).equal(4); + expect(defineCommandStub.callCount).equal(2); + expect(defineCommandStub.args[0][1].help).equal("Quit repl session."); + expect(defineCommandStub.args[1][0]).equal("quit"); + expect(closeEventListener.callCount).equal(1); + expect(spinnerTerminateStub.callCount).equal(1); + }); + + it("| test clearSpecialCommands method", () => { + // setup + const ProxyCliReplView = proxyquire.noCallThru().load(path.join(__dirname, "..", "..", "..", "lib", "view", "cli-repl-view"), { + repl: replStub, + }); + const cliReplView = new ProxyCliReplView.CliReplView({}); + + // call + cliReplView.clearSpecialCommands(); + + // verify + expect(removeListenersStub.callCount).equal(4); + expect(removeListenersStub.args[0][0]).equal("SIGINT"); + expect(removeListenersStub.args[1][0]).equal("close"); + }); + }); + + describe("# inspect correctness of spinner view wrapper methods", () => { + it("| updateProgressSpinner okay.", () => { + // setup + const UPDATE_MESSAGE = "UPDATE_MESSAGE"; + const ProxyCliReplView = proxyquire.noCallThru().load(path.join(__dirname, "..", "..", "..", "lib", "view", "cli-repl-view"), { + repl: replStub, + }); + const cliReplView = new ProxyCliReplView.CliReplView({}); + const spinnerStartStub = sinon.stub(SpinnerView.prototype, "start"); + const spinnerUpdateStub = sinon.stub(SpinnerView.prototype, "update"); + + // call + cliReplView.startProgressSpinner(TEST_MESSAGE); + cliReplView.updateProgressSpinner(UPDATE_MESSAGE); + + // verify + expect(spinnerStartStub.calledOnce).equal(true); + expect(spinnerStartStub.args[0][0]).equal(TEST_MESSAGE); + expect(spinnerUpdateStub.calledOnce).equal(true); + expect(spinnerUpdateStub.args[0][0]).equal(UPDATE_MESSAGE); + }); + + it("| terminateProgressSpinner okay.", () => { + // setup + const ProxyCliReplView = proxyquire.noCallThru().load(path.join(__dirname, "..", "..", "..", "lib", "view", "cli-repl-view"), { + repl: replStub, + }); + const cliReplView = new ProxyCliReplView.CliReplView({}); + + // call + const spinnerStartStub = sinon.stub(SpinnerView.prototype, "start"); + const spinnerTerminateStub = sinon.stub(SpinnerView.prototype, "terminate"); + cliReplView.startProgressSpinner(TEST_MESSAGE); + cliReplView.terminateProgressSpinner(); + + // verify + expect(spinnerStartStub.callCount).equal(1); + expect(spinnerStartStub.args[0][0]).equal(TEST_MESSAGE); + expect(spinnerTerminateStub.callCount).equal(1); + }); + }); +}); diff --git a/test/unit/view/cli-repl-view.test.ts b/test/unit/view/cli-repl-view.test.ts new file mode 100644 index 00000000..6d47569d --- /dev/null +++ b/test/unit/view/cli-repl-view.test.ts @@ -0,0 +1,298 @@ +import {expect} from "chai"; +import proxyquire from "proxyquire"; +import sinon from "sinon"; +import path from "path"; + +import Messenger from "../../../lib/view/messenger"; +import SpinnerView from "../../../lib/view/spinner-view"; + +describe("View test - cli repl view test", () => { + const TEST_MESSAGE = "TEST_MESSAGE"; + let infoStub: sinon.SinonStub; + let removeListenersStub: sinon.SinonStub; + let defineCommandStub: sinon.SinonStub; + let onStub: sinon.SinonStub; + let replStub: any; + let closeStub: sinon.SinonStub; + + beforeEach(() => { + infoStub = sinon.stub(); + removeListenersStub = sinon.stub(); + defineCommandStub = sinon.stub(); + onStub = sinon.stub(); + closeStub = sinon.stub(); + replStub = { + start: () => ({ + removeAllListeners: removeListenersStub, + commands: { + help: "help", + }, + defineCommand: defineCommandStub, + on: onStub, + close: closeStub, + }), + }; + sinon.stub(Messenger, "getInstance").returns({ + info: infoStub, + }); + }); + + afterEach(() => { + sinon.restore(); + }); + + describe("# inspect correctness of the constructor", () => { + it("| initialize CliReplView with custom prompt", () => { + // setup + const ProxyCliReplView = proxyquire.noCallThru().load(path.join(__dirname, "..", "..", "..", "lib", "view", "cli-repl-view"), { + repl: replStub, + }); + + // call + new ProxyCliReplView.CliReplView({prompt: TEST_MESSAGE}); + + // verify + expect(removeListenersStub.callCount).equal(3); + expect(defineCommandStub.callCount).equal(1); + expect(onStub.callCount).equal(1); + }); + + it("| initialize with custom headers array", () => { + // setup + const header = TEST_MESSAGE; + const ProxyCliReplView = proxyquire.noCallThru().load(path.join(__dirname, "..", "..", "..", "lib", "view", "cli-repl-view"), { + repl: replStub, + }); + + // call + const cliReplView = new ProxyCliReplView.CliReplView({header}); + + // verify + expect(cliReplView.header).equal(header); + }); + + it("| initialize with custom eval function", () => { + // setup + const ProxyCliReplView = proxyquire.noCallThru().load(path.join(__dirname, "..", "..", "..", "lib", "view", "cli-repl-view"), { + repl: replStub, + }); + const evalFunc = (_cmd: string, _context: any, _filename: any, callback: (error: any, resp: any) => void) => { + callback(null, "Hello"); + }; + + // call + const cliReplView = new ProxyCliReplView.CliReplView({evalFunc}); + + // verify + expect(cliReplView.eval).equal(evalFunc); + }); + + it("| initialize with custom footer array", () => { + // setup + const footer = TEST_MESSAGE; + const ProxyCliReplView = proxyquire.noCallThru().load(path.join(__dirname, "..", "..", "..", "lib", "view", "cli-repl-view"), { + repl: replStub, + }); + + // call + const cliReplView = new ProxyCliReplView.CliReplView({footer}); + + // verify + expect(cliReplView.footer).equal(footer); + }); + + it("| throw error if configuration is undefined", () => { + // setup + const ProxyCliReplView = proxyquire.noCallThru().load(path.join(__dirname, "..", "..", "..", "lib", "view", "cli-repl-view"), { + repl: replStub, + }); + try { + // call + new ProxyCliReplView.CliReplView(); + } catch (err) { + // verify + expect(err).to.match(new RegExp("Cannot have an undefined configuration.")); + } + }); + + it("| throw error if invalid prompt is passed", () => { + // setup + const ProxyCliReplView = proxyquire.noCallThru().load(path.join(__dirname, "..", "..", "..", "lib", "view", "cli-repl-view"), { + repl: replStub, + }); + const prompt = 1234; + try { + // call + new ProxyCliReplView.CliReplView({prompt}); + } catch (err) { + // verify + expect(err).to.match(new RegExp("Prompt must be a non-empty string.")); + } + }); + }); + + describe("# inspect correctness of methods", () => { + afterEach(() => { + sinon.restore(); + }); + + it("| printHeaderFooter call with default options okay.", () => { + // setup + const ProxyCliReplView = proxyquire.noCallThru().load(path.join(__dirname, "..", "..", "..", "lib", "view", "cli-repl-view"), { + repl: replStub, + }); + const cliReplView = new ProxyCliReplView.CliReplView({}); + + // call + cliReplView.printHeaderFooter(cliReplView.header); + + // verify + expect(infoStub.callCount).equal(0); + }); + + it("| printHeaderFooter call with custom header option okay.", () => { + // setup + const ProxyCliReplView = proxyquire.noCallThru().load(path.join(__dirname, "..", "..", "..", "lib", "view", "cli-repl-view"), { + repl: replStub, + }); + const cliReplView = new ProxyCliReplView.CliReplView({header: TEST_MESSAGE}); + + // call + cliReplView.printHeaderFooter(cliReplView.header); + + // verify + expect(infoStub.callCount).equal(2); + }); + + it("| printHeaderFooter call with invalid header does print.", () => { + // setup + const header = () => {}; + const ProxyCliReplView = proxyquire.noCallThru().load(path.join(__dirname, "..", "..", "..", "lib", "view", "cli-repl-view"), { + repl: replStub, + }); + const cliReplView = new ProxyCliReplView.CliReplView({header}); + + // call + cliReplView.printHeaderFooter(cliReplView.header); + + // verify + expect(infoStub.callCount).equal(0); + }); + + it("| registerCommand successful", () => { + // setup + const ProxyCliReplView = proxyquire.noCallThru().load(path.join(__dirname, "..", "..", "..", "lib", "view", "cli-repl-view"), { + repl: replStub, + }); + const cliReplView = new ProxyCliReplView.CliReplView({}); + const command = {help: TEST_MESSAGE, action: () => {}}; + + // call + cliReplView.registerSpecialCommand(TEST_MESSAGE, command.help, command.action); + + // verify + expect(defineCommandStub.callCount).equal(2); + expect(defineCommandStub.args[0][0]).equal("quit"); + expect(defineCommandStub.args[0][1].help).equal("Quit repl session."); + expect(defineCommandStub.args[1][0]).equal(TEST_MESSAGE); + }); + + it("| test close method", () => { + // setup + const ProxyCliReplView = proxyquire.noCallThru().load(path.join(__dirname, "..", "..", "..", "lib", "view", "cli-repl-view"), { + repl: replStub, + }); + const cliReplView = new ProxyCliReplView.CliReplView({}); + const spinnerStartStub = sinon.stub(SpinnerView.prototype, "start"); + + // call + cliReplView.startProgressSpinner(TEST_MESSAGE); + cliReplView.close(); + + // verify + expect(spinnerStartStub.calledOnce).equal(true); + expect(closeStub.calledOnce).equal(true); + }); + + it("| test registerQuitFunction method", () => { + // setup + const ProxyCliReplView = proxyquire.noCallThru().load(path.join(__dirname, "..", "..", "..", "lib", "view", "cli-repl-view"), { + repl: replStub, + }); + const spinnerTerminateStub = sinon.stub(SpinnerView.prototype, "terminate"); + const cliReplView = new ProxyCliReplView.CliReplView({}); + replStub.start().on.callsArgWith(1, ""); + const closeEventListener = sinon.stub(); + + // call + cliReplView.registerQuitCommand(closeEventListener); + + // verify + expect(onStub.callCount).equal(2); + expect(removeListenersStub.callCount).equal(4); + expect(defineCommandStub.callCount).equal(2); + expect(defineCommandStub.args[0][1].help).equal("Quit repl session."); + expect(defineCommandStub.args[1][0]).equal("quit"); + expect(closeEventListener.callCount).equal(1); + expect(spinnerTerminateStub.callCount).equal(1); + }); + + it("| test clearSpecialCommands method", () => { + // setup + const ProxyCliReplView = proxyquire.noCallThru().load(path.join(__dirname, "..", "..", "..", "lib", "view", "cli-repl-view"), { + repl: replStub, + }); + const cliReplView = new ProxyCliReplView.CliReplView({}); + + // call + cliReplView.clearSpecialCommands(); + + // verify + expect(removeListenersStub.callCount).equal(4); + expect(removeListenersStub.args[0][0]).equal("SIGINT"); + expect(removeListenersStub.args[1][0]).equal("close"); + }); + }); + + describe("# inspect correctness of spinner view wrapper methods", () => { + it("| updateProgressSpinner okay.", () => { + // setup + const UPDATE_MESSAGE = "UPDATE_MESSAGE"; + const ProxyCliReplView = proxyquire.noCallThru().load(path.join(__dirname, "..", "..", "..", "lib", "view", "cli-repl-view"), { + repl: replStub, + }); + const cliReplView = new ProxyCliReplView.CliReplView({}); + const spinnerStartStub = sinon.stub(SpinnerView.prototype, "start"); + const spinnerUpdateStub = sinon.stub(SpinnerView.prototype, "update"); + + // call + cliReplView.startProgressSpinner(TEST_MESSAGE); + cliReplView.updateProgressSpinner(UPDATE_MESSAGE); + + // verify + expect(spinnerStartStub.calledOnce).equal(true); + expect(spinnerStartStub.args[0][0]).equal(TEST_MESSAGE); + expect(spinnerUpdateStub.calledOnce).equal(true); + expect(spinnerUpdateStub.args[0][0]).equal(UPDATE_MESSAGE); + }); + + it("| terminateProgressSpinner okay.", () => { + // setup + const ProxyCliReplView = proxyquire.noCallThru().load(path.join(__dirname, "..", "..", "..", "lib", "view", "cli-repl-view"), { + repl: replStub, + }); + const cliReplView = new ProxyCliReplView.CliReplView({}); + + // call + const spinnerStartStub = sinon.stub(SpinnerView.prototype, "start"); + const spinnerTerminateStub = sinon.stub(SpinnerView.prototype, "terminate"); + cliReplView.startProgressSpinner(TEST_MESSAGE); + cliReplView.terminateProgressSpinner(); + + // verify + expect(spinnerStartStub.callCount).equal(1); + expect(spinnerStartStub.args[0][0]).equal(TEST_MESSAGE); + expect(spinnerTerminateStub.callCount).equal(1); + }); + }); +}); diff --git a/test/unit/view/dialog-repl-view-test.js b/test/unit/view/dialog-repl-view-test.js deleted file mode 100644 index d4d5404e..00000000 --- a/test/unit/view/dialog-repl-view-test.js +++ /dev/null @@ -1,82 +0,0 @@ -const { expect } = require('chai'); -const sinon = require('sinon'); - -const DialogReplView = require('@src/view/dialog-repl-view'); -const Messenger = require('@src/view/messenger'); - -describe('View test - dialog repl view test', () => { - const TEST_MESSAGE = 'TEST_MESSAGE'; - - describe('# inspect correctness of the constructor', () => { - const infoStub = sinon.stub(); - beforeEach(() => { - sinon.stub(Messenger, 'getInstance').returns({ - info: infoStub - }); - }); - - afterEach(() => { - sinon.restore(); - }); - - it('| throw exception for initialization with non-String headers arg', () => { - // setup - const header = 123; - try { - // call - new DialogReplView({ header }); - } catch (err) { - // verify - expect(err).to.match(new RegExp('TypeError: arg.split is not a function')); - } - }); - - it('| throw exception for initialization with empty configuration', () => { - // setup - try { - // call - new DialogReplView(); - } catch (err) { - // verify - expect(err).to.match(new RegExp('TypeError: arg.split is not a function')); - } - }); - - it('| test prettifyHeaderFooter returns correct string', () => { - // setup - const header = TEST_MESSAGE; - const dialogReplView = new DialogReplView({ header }); - process.stdout.columns = 20; - - // call - const prettifiedHeader = dialogReplView.prettifyHeaderFooter(header).trim(); - - // verify - expect(prettifiedHeader.length).equal(20); - }); - - it('| test prettifyHeaderFooter returns correct string when terminal is too small', () => { - // setup - const header = TEST_MESSAGE; - const dialogReplView = new DialogReplView({ header }); - process.stdout.columns = 10; - - // call & verify - expect(dialogReplView.prettifyHeaderFooter(header).trim().length).equal(20); - }); - - it('| test record special command registered without error', () => { - // setup - const dialogReplView = new DialogReplView({}); - - // call - dialogReplView.registerRecordCommand(() => {}); - - // verify - expect(dialogReplView.replServer.commands.record.help).deep.equal( - 'Record input utterances to a replay file of a specified name.' - ); - expect(dialogReplView.replServer.commands.record.action).to.be.a('Function'); - }); - }); -}); diff --git a/test/unit/view/dialog-repl-view.spec.ts b/test/unit/view/dialog-repl-view.spec.ts new file mode 100644 index 00000000..2493ad68 --- /dev/null +++ b/test/unit/view/dialog-repl-view.spec.ts @@ -0,0 +1,86 @@ +import {expect} from "chai"; +import sinon from "sinon"; + +import {DialogReplView} from "../../../lib/view/dialog-repl-view"; +import Messenger from "../../../lib/view/messenger"; + +describe("View test - dialog repl view test", () => { + const TEST_MESSAGE = "TEST_MESSAGE"; + + describe("# inspect correctness of the constructor", () => { + const infoStub = sinon.stub(); + beforeEach(() => { + sinon.stub(Messenger, "getInstance").returns({ + info: infoStub, + }); + }); + + afterEach(() => { + sinon.restore(); + }); + + it("| throw exception for initialization with non-String headers arg", () => { + // setup + const header = "123"; + try { + // call + new DialogReplView({header} as any).close(); + } catch (err) { + // verify + expect(err).to.match(new RegExp("TypeError: arg.split is not a function")); + } + }); + + it("| throw exception for initialization with empty configuration", () => { + // setup + try { + // call + new DialogReplView({} as any).close(); + } catch (err) { + // verify + expect(err).to.match(new RegExp("TypeError: arg.split is not a function")); + } + }); + + it("| test prettifyHeaderFooter returns correct string", () => { + // setup + const header = TEST_MESSAGE; + const dialogReplView = new DialogReplView({header} as any); + process.stdout.columns = 20; + + // call + const prettifiedHeader = dialogReplView.prettifyHeaderFooter(header).trim(); + + // verify + expect(prettifiedHeader.length).equal(20); + + dialogReplView.close(); + }); + + it("| test prettifyHeaderFooter returns correct string when terminal is too small", () => { + // setup + const header = TEST_MESSAGE; + const dialogReplView = new DialogReplView({header} as any); + process.stdout.columns = 10; + + // call & verify + expect(dialogReplView.prettifyHeaderFooter(header).trim().length).equal(20); + + dialogReplView.close(); + }); + + it("| test record special command registered without error", () => { + // setup + const dialogReplView = new DialogReplView({} as any); + + // call + dialogReplView.registerRecordCommand(() => {}); + + // verify + expect(dialogReplView.replServer.commands?.record?.help).deep.equal("Record input utterances to a replay file of a specified name."); + expect(dialogReplView.replServer.commands?.record?.action).to.be.a("Function"); + + dialogReplView.close(); + }); + }); +}); diff --git a/test/unit/view/dialog-repl-view.test.ts b/test/unit/view/dialog-repl-view.test.ts new file mode 100644 index 00000000..2493ad68 --- /dev/null +++ b/test/unit/view/dialog-repl-view.test.ts @@ -0,0 +1,86 @@ +import {expect} from "chai"; +import sinon from "sinon"; + +import {DialogReplView} from "../../../lib/view/dialog-repl-view"; +import Messenger from "../../../lib/view/messenger"; + +describe("View test - dialog repl view test", () => { + const TEST_MESSAGE = "TEST_MESSAGE"; + + describe("# inspect correctness of the constructor", () => { + const infoStub = sinon.stub(); + beforeEach(() => { + sinon.stub(Messenger, "getInstance").returns({ + info: infoStub, + }); + }); + + afterEach(() => { + sinon.restore(); + }); + + it("| throw exception for initialization with non-String headers arg", () => { + // setup + const header = "123"; + try { + // call + new DialogReplView({header} as any).close(); + } catch (err) { + // verify + expect(err).to.match(new RegExp("TypeError: arg.split is not a function")); + } + }); + + it("| throw exception for initialization with empty configuration", () => { + // setup + try { + // call + new DialogReplView({} as any).close(); + } catch (err) { + // verify + expect(err).to.match(new RegExp("TypeError: arg.split is not a function")); + } + }); + + it("| test prettifyHeaderFooter returns correct string", () => { + // setup + const header = TEST_MESSAGE; + const dialogReplView = new DialogReplView({header} as any); + process.stdout.columns = 20; + + // call + const prettifiedHeader = dialogReplView.prettifyHeaderFooter(header).trim(); + + // verify + expect(prettifiedHeader.length).equal(20); + + dialogReplView.close(); + }); + + it("| test prettifyHeaderFooter returns correct string when terminal is too small", () => { + // setup + const header = TEST_MESSAGE; + const dialogReplView = new DialogReplView({header} as any); + process.stdout.columns = 10; + + // call & verify + expect(dialogReplView.prettifyHeaderFooter(header).trim().length).equal(20); + + dialogReplView.close(); + }); + + it("| test record special command registered without error", () => { + // setup + const dialogReplView = new DialogReplView({} as any); + + // call + dialogReplView.registerRecordCommand(() => {}); + + // verify + expect(dialogReplView.replServer.commands?.record?.help).deep.equal("Record input utterances to a replay file of a specified name."); + expect(dialogReplView.replServer.commands?.record?.action).to.be.a("Function"); + + dialogReplView.close(); + }); + }); +}); diff --git a/test/unit/view/import-status/import-status-view-observable-test.ts b/test/unit/view/import-status/import-status-view-observable-test.ts new file mode 100644 index 00000000..beb90b38 --- /dev/null +++ b/test/unit/view/import-status/import-status-view-observable-test.ts @@ -0,0 +1,181 @@ +import {assert, expect} from "chai"; +import {Observable} from "rxjs"; +import sinon from "sinon"; +import {EventEmitter} from "stream"; +import { + IMPORT_STATUS_AC_BUILD_FAILED_EVENT, + IMPORT_STATUS_AC_BUILD_SUCCESS_EVENT, + IMPORT_STATUS_BUILDING_AC_FULL_EVENT, + IMPORT_STATUS_BUILDING_AC_LIGHT_EVENT, + IMPORT_STATUS_FETCHING_IMPORT_ID_SUCESS_EVENT, + IMPORT_STATUS_FETCHING_NEW_SKILL_ID_SUCESS_EVENT, + IMPORT_STATUS_FETCHING_SKILL_ID_SUCESS_EVENT, + IMPORT_STATUS_IM_BUILD_FAILED_EVENT, + IMPORT_STATUS_IM_BUILD_SUCCESS_EVENT, +} from "../../../../lib/view/import-status/import-status-view-events"; +import {ImportStatusViewObservable} from "../../../../lib/view/import-status/import-status-view-observable"; + +describe("Import Status View Observable test", () => { + let importStatusViewObservable: ImportStatusViewObservable; + let emitter: EventEmitter; + + const TEST_TASK_ID_1 = "testId1"; + const TEST_TASK_TITLE_1 = "testTitle1"; + const TEST_TASK = { + taskId: TEST_TASK_ID_1, + title: TEST_TASK_TITLE_1, + }; + + beforeEach(() => { + emitter = new EventEmitter(); + importStatusViewObservable = new ImportStatusViewObservable(emitter, TEST_TASK_ID_1); + }); + + afterEach(() => { + sinon.restore(); + }); + + it("contruct the class", () => { + expect(importStatusViewObservable).not.equal(undefined); + expect(importStatusViewObservable).to.be.instanceOf(ImportStatusViewObservable); + }); + + it("listens to SkillId success event and completes the task", (done) => { + const observable: Observable = importStatusViewObservable.getObservable()(undefined, TEST_TASK); + observable.subscribe({ + next(message) { + assert.fail(message); + }, + complete() { + done(); + }, + }); + + emitter.emit(IMPORT_STATUS_FETCHING_SKILL_ID_SUCESS_EVENT); + }); + + it("listens to NEW SkillId success event and completes the task", (done) => { + const observable: Observable = importStatusViewObservable.getObservable()(undefined, TEST_TASK); + observable.subscribe({ + next(message) { + assert.fail(message); + }, + complete() { + done(); + }, + }); + + emitter.emit(IMPORT_STATUS_FETCHING_NEW_SKILL_ID_SUCESS_EVENT); + }); + + it("listens to Import Id success event and completes the task", (done) => { + const observable: Observable = importStatusViewObservable.getObservable()(undefined, TEST_TASK); + observable.subscribe({ + next(message) { + assert.fail(message); + }, + complete() { + done(); + }, + }); + + emitter.emit(IMPORT_STATUS_FETCHING_IMPORT_ID_SUCESS_EVENT); + }); + + it("listens to IM build success event and completes the task", (done) => { + const observable: Observable = importStatusViewObservable.getObservable()(undefined, TEST_TASK); + observable.subscribe({ + next(message) { + assert.fail(message); + }, + complete() { + done(); + }, + }); + + emitter.emit(IMPORT_STATUS_IM_BUILD_SUCCESS_EVENT); + }); + + it("listens to IM build failed event and completes the task with an error", (done) => { + const observable: Observable = importStatusViewObservable.getObservable()(undefined, TEST_TASK); + observable.subscribe({ + next(message) { + assert.fail(message); + }, + complete() { + assert.fail(); + }, + error(error: Error) { + assert.include(error.message, "build has failed", "missing IM build failed error message"); + done(); + }, + }); + + emitter.emit(IMPORT_STATUS_IM_BUILD_FAILED_EVENT); + }); + + it("listens to AC light build starting event and updates the task", (done) => { + const observable: Observable = importStatusViewObservable.getObservable()(undefined, TEST_TASK); + observable.subscribe({ + next(message) { + expect(message).to.equal("Building Alexa Conversations light build"); + done(); + }, + complete() { + assert.fail(); + }, + }); + + emitter.emit(IMPORT_STATUS_BUILDING_AC_LIGHT_EVENT); + }); + + it("listens to AC full build starting event and updates the task", (done) => { + const observable: Observable = importStatusViewObservable.getObservable()(undefined, TEST_TASK); + observable.subscribe({ + next(message) { + expect(message).to.equal( + "You can now test some Alexa Conversations dialogs while we continue to train your model with additional simulated dialogs.", + ); + done(); + }, + complete() { + assert.fail(); + }, + }); + + emitter.emit(IMPORT_STATUS_BUILDING_AC_FULL_EVENT); + }); + + it("listens to AC build success event and completes the task", (done) => { + const observable: Observable = importStatusViewObservable.getObservable()(undefined, TEST_TASK); + observable.subscribe({ + next(message) { + assert.fail(message); + }, + complete() { + done(); + }, + }); + + emitter.emit(IMPORT_STATUS_AC_BUILD_SUCCESS_EVENT); + }); + + it("listens to AC build failed event and completes the task with an error", (done) => { + const observable: Observable = importStatusViewObservable.getObservable()(undefined, TEST_TASK); + const fakeErrorMessage = "foo"; + observable.subscribe({ + next(message) { + assert.fail(message); + }, + complete() { + assert.fail(); + }, + error(error: Error) { + assert.include(error.message, fakeErrorMessage, "missing AC build failed error message"); + done(); + }, + }); + + emitter.emit(IMPORT_STATUS_AC_BUILD_FAILED_EVENT, fakeErrorMessage); + }); +}); diff --git a/test/unit/view/import-status/import-status-view-test.ts b/test/unit/view/import-status/import-status-view-test.ts new file mode 100644 index 00000000..325dade5 --- /dev/null +++ b/test/unit/view/import-status/import-status-view-test.ts @@ -0,0 +1,69 @@ +import {assert, expect} from "chai"; +import Listr from "listr"; +import sinon, {SinonSpy, SinonStub} from "sinon"; +import {EventEmitter} from "stream"; +import {ImportStatusView} from "../../../../lib/view/import-status/import-status-view"; +import { + IMPORT_STATUS_FETCHING_IMPORT_ID_SUCESS_EVENT, + IMPORT_STATUS_FETCHING_NEW_SKILL_ID_SUCESS_EVENT, + IMPORT_STATUS_FETCHING_SKILL_ID_SUCESS_EVENT, +} from "../../../../lib/view/import-status/import-status-view-events"; + +describe("Import Status View test", () => { + let importStatusView: ImportStatusView; + let listrStubRun: SinonStub; + let emitterStubEmit: SinonSpy; + //let listrStubAdd: SinonStub; + let listr: Listr; + const TEST_LOCALE_1 = "firstLocale"; + const TEST_LOCALE_2 = "secondLocale"; + const TEST_SKILL_ID = "MyTestSkillId"; + const TEST_IMPORT_ID = "MyTestImportId"; + const TEST_LOCALES = [TEST_LOCALE_1, TEST_LOCALE_2]; + + beforeEach(() => { + listr = new Listr(); + listrStubRun = sinon.stub(listr, "run").resolves(); + emitterStubEmit = sinon.spy(EventEmitter.prototype, "emit"); + + //listrStubAdd = sinon.stub(listr, 'add'); + importStatusView = new ImportStatusView(TEST_LOCALES, listr); + }); + + afterEach(() => { + sinon.restore(); + }); + + it("contruct the class", () => { + expect(importStatusView).not.equal(undefined); + expect(importStatusView).to.be.instanceOf(ImportStatusView); + expect(listrStubRun.called).to.be.true; + expect(listr.tasks.length).to.be.equal(TEST_LOCALES.length + 2); + assert.include(listr.tasks[0].title, "Retrieving skill id", "Skill id tasks should be the first task"); + assert.include(listr.tasks[1].title, "Retrieving import id", "Import id tasks should be the second task"); + assert.include(listr.tasks[2].title, TEST_LOCALE_1, "tasks 1 should be in the correct order"); + assert.include(listr.tasks[3].title, TEST_LOCALE_2, "tasks 2 should be in the correct order"); + }); + + describe("displaySkillId", () => { + it("From Configuration file updates the task", () => { + importStatusView.displaySkillId(TEST_SKILL_ID, true); + const isEventEmited: boolean = emitterStubEmit.calledWithExactly(IMPORT_STATUS_FETCHING_SKILL_ID_SUCESS_EVENT, TEST_SKILL_ID); + expect(isEventEmited).to.be.true; + }); + + it("From SMAPI service updates the task", () => { + importStatusView.displaySkillId(TEST_SKILL_ID, false); + const isEventEmited: boolean = emitterStubEmit.calledWithExactly(IMPORT_STATUS_FETCHING_NEW_SKILL_ID_SUCESS_EVENT, TEST_SKILL_ID); + expect(isEventEmited).to.be.true; + }); + }); + + describe("displayImportId", () => { + it("updates the task", () => { + importStatusView.displayImportId(TEST_IMPORT_ID); + const isEventEmited: boolean = emitterStubEmit.calledWithExactly(IMPORT_STATUS_FETCHING_IMPORT_ID_SUCESS_EVENT, TEST_IMPORT_ID); + expect(isEventEmited).to.be.true; + }); + }); +}); diff --git a/test/unit/view/json-view-test.js b/test/unit/view/json-view-test.js index 98f76655..882e4244 100644 --- a/test/unit/view/json-view-test.js +++ b/test/unit/view/json-view-test.js @@ -1,41 +1,41 @@ -const { expect } = require('chai'); -const jsonView = require('@src/view/json-view'); +const {expect} = require("chai"); +const jsonView = require("../../../lib/view/json-view"); -describe('View test - JSON view test', () => { - describe('# Test function toString', () => { - it('| convert object to JSON string', () => { - // setup - const TEST_OBJ = { - key: 'value' - }; - const TEST_OBJ_JSON_STRING = '{\n "key": "value"\n}'; - // call - const jsonDisplay = jsonView.toString(TEST_OBJ); - // verify - expect(jsonDisplay).equal(TEST_OBJ_JSON_STRING); - }); +describe("View test - JSON view test", () => { + describe("# Test function toString", () => { + it("| convert object to JSON string", () => { + // setup + const TEST_OBJ = { + key: "value", + }; + const TEST_OBJ_JSON_STRING = '{\n "key": "value"\n}'; + // call + const jsonDisplay = jsonView.toString(TEST_OBJ); + // verify + expect(jsonDisplay).equal(TEST_OBJ_JSON_STRING); + }); - it('| convert error to JSON string', () => { - // setup - const error = new Error(); - error.extraInfo = 'some info'; + it("| convert error to JSON string", () => { + // setup + const error = new Error(); + error.extraInfo = "some info"; - // call - const jsonDisplay = jsonView.toString(error); - // verify - expect(jsonDisplay).includes('"stack"'); - expect(jsonDisplay).includes('"message"'); - expect(jsonDisplay).includes('"extraInfo"'); - }); + // call + const jsonDisplay = jsonView.toString(error); + // verify + expect(jsonDisplay).includes('"stack"'); + expect(jsonDisplay).includes('"message"'); + expect(jsonDisplay).includes('"extraInfo"'); + }); - it('| display error when JSON stringify throws error', () => { - // setup - const TEST_CIRCULAR_OBJ = {}; - TEST_CIRCULAR_OBJ.key = { key2: TEST_CIRCULAR_OBJ }; - // call - const jsonDisplay = jsonView.toString(TEST_CIRCULAR_OBJ); - // verify - expect(jsonDisplay.startsWith('TypeError: Converting circular structure to JSON')).equal(true); - }); + it("| display error when JSON stringify throws error", () => { + // setup + const TEST_CIRCULAR_OBJ = {}; + TEST_CIRCULAR_OBJ.key = {key2: TEST_CIRCULAR_OBJ}; + // call + const jsonDisplay = jsonView.toString(TEST_CIRCULAR_OBJ); + // verify + expect(jsonDisplay.startsWith("TypeError: Converting circular structure to JSON")).equal(true); }); + }); }); diff --git a/test/unit/view/messenger-test.js b/test/unit/view/messenger-test.js index 41710680..38951a6d 100644 --- a/test/unit/view/messenger-test.js +++ b/test/unit/view/messenger-test.js @@ -1,347 +1,398 @@ -const { expect } = require('chai'); -const sinon = require('sinon'); -const chalk = require('chalk'); -const fs = require('fs'); -const path = require('path'); -const Messenger = require('@src/view/messenger'); - -describe('View test - messenger file test', () => { - const TEST_MESSAGE = 'TEST_MESSAGE'; - const TEST_TIME = 'TEST_TIME'; - const TEST_ERROR_OBJ = new Error('TEST_ERROR'); - - describe('# inspect correctness for constructor, getInstance and dispose', () => { - beforeEach(() => { - sinon.stub(fs, 'writeFileSync'); - }); - - it('| initiate as a Messenger class', () => { - const messenger = new Messenger({ doDebug: false }); - expect(messenger).to.be.instanceof(Messenger); - Messenger.getInstance().dispose(); - expect(Messenger.getInstance()).to.be.instanceof(Messenger); - }); - - it('| make sure Messenger class is singleton', () => { - const messenger1 = new Messenger({ doDebug: false }); - const messenger2 = new Messenger({ doDebug: false }); - expect(messenger1 === messenger2).equal(true); - Messenger.getInstance().dispose(); - }); - - it('| get instance function return the instance constructed before', () => { - const messenger = new Messenger({ doDebug: false }); - expect(Messenger.getInstance() === messenger).equal(true); - Messenger.getInstance().dispose(); - }); - - it('| init with doDebug parameter not existing, expect doDebug property equal to false ', () => { - const messenger = new Messenger({ doDebug: false }); - expect(messenger.doDebug).equal(false); - Messenger.getInstance().dispose(); - }); - - it('| init with doDebug parameter equal to true, expect doDebug property equal to true ', () => { - const messenger = new Messenger({ doDebug: true }); - expect(messenger.doDebug).equal(true); - Messenger.getInstance().dispose(); - }); - - afterEach(() => { - sinon.restore(); - }); +const {expect} = require("chai"); +const sinon = require("sinon"); +const chalk = require("chalk"); +const fs = require("fs"); +const path = require("path"); +const Messenger = require("../../../lib/view/messenger"); + +describe("View test - messenger file test", () => { + const TEST_MESSAGE = "TEST_MESSAGE"; + const TEST_TIME = "TEST_TIME"; + const TEST_ERROR_OBJ = new Error("TEST_ERROR"); + + describe("# inspect correctness for constructor, getInstance and dispose", () => { + beforeEach(() => { + sinon.stub(fs, "writeFileSync"); }); - describe('# inspect all log methods and make sure they work well on debug mode', () => { - beforeEach(() => { - // Clear Messenger instance before running each test to ensure test result don't get affected by failures from others - if (Messenger.getInstance()) { - Messenger.getInstance().dispose(); - } - - new Messenger({ doDebug: true }); - sinon.stub(Messenger, 'getTime').callsFake(() => TEST_TIME); - sinon.stub(fs, 'writeFileSync'); - }); - - it('| debug function correctly push message to buffer, and can display message on debug mode', () => { - const stub = sinon.stub(console, 'warn'); - const expectedItem = { - time: TEST_TIME, - operation: 'DEBUG', - level: 20, - msg: TEST_MESSAGE - }; - - // call - Messenger.getInstance().debug(TEST_MESSAGE); - - // verify - expect(Messenger.getInstance()._buffer[0]).deep.equal(expectedItem); - expect(stub.args[0][0]).equal(chalk`{gray [Debug]: ${TEST_MESSAGE}}`); - - // clear - Messenger.getInstance().dispose(); - }); - - it('| debug function correctly push message to buffer, but display nothing when not on debug mode', () => { - Messenger.getInstance().dispose(); - new Messenger({ doDebug: false }); - const stub = sinon.stub(console, 'warn'); - const expectedItem = { - time: TEST_TIME, - operation: 'DEBUG', - level: 20, - msg: TEST_MESSAGE - }; - sinon.spy(Messenger, 'displayWithStyle'); - - // call - Messenger.getInstance().debug(TEST_MESSAGE); - - // verify - expect(Messenger.getInstance()._buffer[0]).deep.equal(expectedItem); - expect(Messenger.displayWithStyle.calledOnce).equal(false); - expect(stub.called).equal(false); - - // clear - Messenger.getInstance().dispose(); - }); - - it('| info function correctly push message to buffer and display', () => { - const stub = sinon.stub(console, 'log'); - const expectedItem = { - time: TEST_TIME, - operation: 'INFO', - level: 30, - msg: TEST_MESSAGE - }; - - // call - Messenger.getInstance().info(TEST_MESSAGE); - - // verify - expect(Messenger.getInstance()._buffer[0]).deep.equal(expectedItem); - expect(stub.args[0][0]).equal(`${TEST_MESSAGE}`); - - // clear - Messenger.getInstance().dispose(); - - // restore console.log first, otherwise cannot print test result to console - console.log.restore(); - }); - - it('| warn function correctly push message to buffer and display', () => { - const stub = sinon.stub(console, 'warn'); - const expectedItem = { - time: TEST_TIME, - operation: 'WARN', - level: 40, - msg: TEST_MESSAGE - }; - - // call - Messenger.getInstance().warn(TEST_MESSAGE); - - // verify - expect(Messenger.getInstance()._buffer[0]).deep.equal(expectedItem); - expect(stub.args[0][0]).equal(chalk`{bold.yellow [Warn]: ${TEST_MESSAGE}}`); - - // clear - Messenger.getInstance().dispose(); - }); - - it('| error function correctly push message to buffer and display', () => { - const stub = sinon.stub(console, 'error'); - const expectedItem = { - time: TEST_TIME, - operation: 'ERROR', - level: 50, - msg: TEST_MESSAGE - }; - - // call - Messenger.getInstance().error(TEST_MESSAGE); - - // verify - expect(Messenger.getInstance()._buffer[0]).deep.equal(expectedItem); - expect(stub.args[0][0]).equal(chalk`{bold.red [Error]: ${TEST_MESSAGE}}`); - - // clear - Messenger.getInstance().dispose(); - }); - - it('| fatal function correctly push message to buffer and display', () => { - const stub = sinon.stub(console, 'error'); - const expectedItem = { - time: TEST_TIME, - operation: 'FATAL', - level: 60, - msg: TEST_MESSAGE - }; - - // call - Messenger.getInstance().fatal(TEST_MESSAGE); - - // verify - expect(Messenger.getInstance()._buffer[0]).deep.equal(expectedItem); - expect(stub.args[0][0]).equal(chalk`{bold.rgb(128, 0, 0) [Fatal]: ${TEST_MESSAGE}}`); - - // clear - Messenger.getInstance().dispose(); - }); - - it('| fatal function correctly push error stack to buffer and display', () => { - const stub = sinon.stub(console, 'error'); - const expectedItem = { - time: TEST_TIME, - operation: 'FATAL', - level: 60, - msg: TEST_ERROR_OBJ.stack.substring(7), - }; - - // call - Messenger.getInstance().fatal(TEST_ERROR_OBJ); - - // verify - expect(Messenger.getInstance()._buffer[0]).deep.equal(expectedItem); - expect(stub.args[0][0]).equal(chalk`{bold.rgb(128, 0, 0) [Fatal]: ${TEST_ERROR_OBJ.stack.substring(7)}}`); - - // clear - Messenger.getInstance().dispose(); - }); - - it('| trace function correctly push message to buffer and write to file with complete message', () => { - const TEST_ACTIVITY = 'TEST_ACTIVITY'; - const TEST_METHOD = 'TEST_METHOD'; - const TEST_URL = 'TEST_URL'; - const TEST_HEADERS = 'TEST_HEADERS'; - const TEST_BODY = 'TEST_BODY'; - const TEST_STATUS_CODE = 'TEST_STATUS_CODE'; - const TEST_STATUS_MESSAGE = 'TEST_STATUS_MESSAGE'; - const TEST_ERROR = 'TEST_ERROR'; - const TEST_REQUEST_ID = 'TEST_REQUEST_ID'; - const message = { - activity: TEST_ACTIVITY, - request: { - method: TEST_METHOD, - url: TEST_URL, - headers: TEST_HEADERS, - body: TEST_BODY - }, - response: { - statusCode: TEST_STATUS_CODE, - statusMessage: TEST_STATUS_MESSAGE, - headers: TEST_HEADERS - }, - error: 'TEST_ERROR', - 'request-id': TEST_REQUEST_ID, - body: TEST_BODY - }; - const expectedItem = { - time: TEST_TIME, - operation: 'TRACE', - level: 10, - msg: message - }; - const expectedContent = [ - `\n[TEST_TIME] - TRACE - ${TEST_ACTIVITY}`, - `\nrequest-id: ${TEST_REQUEST_ID}`, - `\nTEST_METHOD ${TEST_URL}`, - `\nstatus code: ${TEST_STATUS_CODE} ${TEST_STATUS_MESSAGE}`, - `\nerror: ${TEST_ERROR}\n`, - `\nRequest headers: ${JSON.stringify('TEST_HEADERS')}`, - `\nRequest body: ${TEST_BODY}`, - `\nResponse headers: ${JSON.stringify(TEST_HEADERS)}`, - `\nResponse body: ${JSON.stringify(TEST_BODY)}`, - '\n----------------------------------------' - ]; - const filePath = path.join(process.cwd(), `ask-cli-${TEST_TIME}.log`); - sinon.stub(console, 'log'); - - // call - Messenger.getInstance().trace(message); - - // verify - expect(Messenger.getInstance()._buffer[0]).deep.equal(expectedItem); - - // call - Messenger.getInstance().dispose(); - - // verify - expect(fs.writeFileSync.args[0][0]).deep.equal(filePath); - expect(fs.writeFileSync.args[0][1]).deep.equal(expectedContent); - expect(console.log.args[0][0]).equal(`\nDetail log has been recorded at ${filePath}`); - - // restore console.log first, otherwise cannot print test result to console - console.log.restore(); - }); - - it('| trace function correctly push message to buffer and write to file with incomplete message', () => { - const TEST_ACTIVITY = 'TEST_ACTIVITY'; - const TEST_METHOD = 'TEST_METHOD'; - const TEST_URL = 'TEST_URL'; - const TEST_HEADERS = 'TEST_HEADERS'; - const TEST_STATUS_CODE = 'TEST_STATUS_CODE'; - const TEST_STATUS_MESSAGE = 'TEST_STATUS_MESSAGE'; - const message = { - activity: TEST_ACTIVITY, - request: { - method: TEST_METHOD, - url: TEST_URL, - headers: TEST_HEADERS, - }, - response: { - statusCode: TEST_STATUS_CODE, - statusMessage: TEST_STATUS_MESSAGE, - headers: TEST_HEADERS - } - }; - const expectedItem = { - time: TEST_TIME, - operation: 'TRACE', - level: 10, - msg: message - }; - const expectedContent = [ - `\n[TEST_TIME] - TRACE - ${TEST_ACTIVITY}`, - `\nTEST_METHOD ${TEST_URL}`, - `\nstatus code: ${TEST_STATUS_CODE} ${TEST_STATUS_MESSAGE}`, - `\nRequest headers: ${JSON.stringify('TEST_HEADERS')}`, - `\nResponse headers: ${JSON.stringify(TEST_HEADERS)}`, - '\n----------------------------------------' - ]; - const filePath = path.join(process.cwd(), `ask-cli-${TEST_TIME}.log`); - sinon.stub(console, 'log'); - - // call - Messenger.getInstance().trace(message); - - // verify - expect(Messenger.getInstance()._buffer[0]).deep.equal(expectedItem); - - // call - Messenger.getInstance().dispose(); - - // verify - expect(fs.writeFileSync.args[0][0]).deep.equal(filePath); - expect(fs.writeFileSync.args[0][1]).deep.equal(expectedContent); - expect(console.log.args[0][0]).equal(`\nDetail log has been recorded at ${filePath}`); - - // restore console.log first, otherwise cannot print test result to console - console.log.restore(); - }); - - afterEach(() => { - sinon.restore(); - }); + it("| initiate as a Messenger class", () => { + const messenger = new Messenger({doDebug: false}); + expect(messenger).to.be.instanceof(Messenger); + expect(Messenger.getInstance()).to.be.instanceof(Messenger); }); - it('| displayWithStyle can print bold but no color font', () => { - new Messenger({ doDebug: true }); - const stub = sinon.stub(console, 'error'); - Messenger.displayWithStyle(null, 'error', true, TEST_MESSAGE); - expect(stub.args[0][0]).equal(chalk`{bold ${TEST_MESSAGE}}`); - sinon.restore(); + it("| make sure Messenger class is singleton", () => { + const messenger1 = new Messenger({doDebug: false}); + const messenger2 = new Messenger({doDebug: false}); + expect(messenger1 === messenger2).equal(true); }); + + it("| get instance function return the instance constructed before", () => { + const messenger = new Messenger({doDebug: false}); + expect(Messenger.getInstance() === messenger).equal(true); + }); + + it("| init with doDebug parameter not existing, expect doDebug property equal to false ", () => { + const messenger = new Messenger({doDebug: false}); + expect(messenger.doDebug).equal(false); + }); + + it("| init with doDebug parameter equal to true, expect doDebug property equal to true ", () => { + const messenger = new Messenger({doDebug: true}); + expect(messenger.doDebug).equal(true); + }); + + afterEach(() => { + Messenger.getInstance().dispose(); + sinon.restore(); + }); + }); + + describe("# inspect all log methods and make sure they work well on debug mode", () => { + beforeEach(() => { + new Messenger({doDebug: true}); + sinon.stub(Messenger, "getTime").callsFake(() => TEST_TIME); + sinon.stub(fs, "writeFileSync"); + }); + + it("| debug function correctly push message to buffer, and can display message on debug mode", () => { + const stub = sinon.stub(console, "warn"); + const expectedItem = { + time: TEST_TIME, + operation: "DEBUG", + level: 20, + msg: TEST_MESSAGE, + }; + + // call + Messenger.getInstance().debug(TEST_MESSAGE); + + // verify + expect(Messenger.getInstance()._buffer[0]).deep.equal(expectedItem); + expect(stub.args[0][0]).equal(chalk`{gray [Debug]: ${TEST_MESSAGE}}`); + }); + + it("| debug function does not populate the local buffer, and displays nothing when debug mode is not enabled", () => { + Messenger.getInstance().dispose(); + new Messenger({doDebug: false}); + const stub = sinon.stub(console, "warn"); + const expectedItem = { + time: TEST_TIME, + operation: "DEBUG", + level: 20, + msg: TEST_MESSAGE, + }; + sinon.spy(Messenger, "displayWithStyle"); + + // call + Messenger.getInstance().debug(TEST_MESSAGE); + + // verify + expect(Messenger.getInstance()._buffer.length).to.equal(0); + expect(Messenger.displayWithStyle.calledOnce).equal(false); + expect(stub.called).equal(false); + }); + + it("| info function correctly push message to buffer and display", () => { + const stub = sinon.stub(console, "log"); + const expectedItem = { + time: TEST_TIME, + operation: "INFO", + level: 30, + msg: TEST_MESSAGE, + }; + + // call + Messenger.getInstance().info(TEST_MESSAGE); + + // verify + expect(Messenger.getInstance()._buffer[0]).deep.equal(expectedItem); + expect(stub.args[0][0]).equal(`${TEST_MESSAGE}`); + + // restore console.log first, otherwise cannot print test result to console + console.log.restore(); + }); + + it("| warn function correctly push message to buffer and display", () => { + const stub = sinon.stub(console, "warn"); + const expectedItem = { + time: TEST_TIME, + operation: "WARN", + level: 40, + msg: TEST_MESSAGE, + }; + + // call + Messenger.getInstance().warn(TEST_MESSAGE); + + // verify + expect(Messenger.getInstance()._buffer[0]).deep.equal(expectedItem); + expect(stub.args[0][0]).equal(chalk`{bold.yellow [Warn]: ${TEST_MESSAGE}}`); + }); + + it("| error function correctly push message to buffer and display", () => { + const stub = sinon.stub(console, "error"); + const expectedItem = { + time: TEST_TIME, + operation: "ERROR", + level: 50, + msg: TEST_MESSAGE, + }; + + // call + Messenger.getInstance().error(TEST_MESSAGE); + + // verify + expect(Messenger.getInstance()._buffer[0]).deep.equal(expectedItem); + expect(stub.args[0][0]).equal(chalk`{bold.red [Error]: ${TEST_MESSAGE}}`); + }); + + it("| fatal function correctly push message to buffer and display", () => { + const stub = sinon.stub(console, "error"); + const expectedItem = { + time: TEST_TIME, + operation: "FATAL", + level: 60, + msg: TEST_MESSAGE, + }; + + // call + Messenger.getInstance().fatal(TEST_MESSAGE); + + // verify + expect(Messenger.getInstance()._buffer[0]).deep.equal(expectedItem); + expect(stub.args[0][0]).equal(chalk`{bold.rgb(128, 0, 0) [Fatal]: ${TEST_MESSAGE}}`); + }); + + it("| fatal function correctly push error stack to buffer and display", () => { + const stub = sinon.stub(console, "error"); + const expectedItem = { + time: TEST_TIME, + operation: "FATAL", + level: 60, + msg: TEST_ERROR_OBJ.stack.substring(7), + }; + + // call + Messenger.getInstance().fatal(TEST_ERROR_OBJ); + + // verify + expect(Messenger.getInstance()._buffer[0]).deep.equal(expectedItem); + expect(stub.args[0][0]).equal(chalk`{bold.rgb(128, 0, 0) [Fatal]: ${TEST_ERROR_OBJ.stack.substring(7)}}`); + }); + + it("| trace function correctly push message to buffer and write to file with complete message", () => { + const TEST_ACTIVITY = "TEST_ACTIVITY"; + const TEST_METHOD = "TEST_METHOD"; + const TEST_URL = "TEST_URL"; + const TEST_HEADERS = "TEST_HEADERS"; + const TEST_BODY = "TEST_BODY"; + const TEST_STATUS_CODE = "TEST_STATUS_CODE"; + const TEST_STATUS_MESSAGE = "TEST_STATUS_MESSAGE"; + const TEST_ERROR = "TEST_ERROR"; + const TEST_REQUEST_ID = "TEST_REQUEST_ID"; + const message = { + activity: TEST_ACTIVITY, + request: { + method: TEST_METHOD, + url: TEST_URL, + headers: TEST_HEADERS, + body: TEST_BODY, + }, + response: { + statusCode: TEST_STATUS_CODE, + statusMessage: TEST_STATUS_MESSAGE, + headers: TEST_HEADERS, + }, + error: "TEST_ERROR", + "request-id": TEST_REQUEST_ID, + body: TEST_BODY, + }; + const expectedItem = { + time: TEST_TIME, + operation: "TRACE", + level: 10, + msg: message, + }; + const expectedContent = [ + `\n[TEST_TIME] - TRACE - ${TEST_ACTIVITY}`, + `\nrequest-id: ${TEST_REQUEST_ID}`, + `\nTEST_METHOD ${TEST_URL}`, + `\nstatus code: ${TEST_STATUS_CODE} ${TEST_STATUS_MESSAGE}`, + `\nerror: ${TEST_ERROR}\n`, + `\nRequest headers: ${JSON.stringify("TEST_HEADERS")}`, + `\nRequest body: ${TEST_BODY}`, + `\nResponse headers: ${JSON.stringify(TEST_HEADERS)}`, + `\nResponse body: ${JSON.stringify(TEST_BODY)}`, + "\n----------------------------------------", + ]; + const filePath = path.join(process.cwd(), `ask-cli-${TEST_TIME}.log`); + sinon.stub(console, "log"); + + // call + Messenger.getInstance().trace(message); + + // verify + expect(Messenger.getInstance()._buffer[0]).deep.equal(expectedItem); + + // call + Messenger.getInstance().dispose(); + + // verify + expect(fs.writeFileSync.args[0][0]).deep.equal(filePath); + expect(fs.writeFileSync.args[0][1]).deep.equal(expectedContent); + expect(console.log.args[0][0]).equal(`\nDetail log has been recorded at ${filePath}`); + + // restore console.log first, otherwise cannot print test result to console + console.log.restore(); + }); + + it("| trace function correctly push message to buffer and write to file with incomplete message", () => { + const TEST_ACTIVITY = "TEST_ACTIVITY"; + const TEST_METHOD = "TEST_METHOD"; + const TEST_URL = "TEST_URL"; + const TEST_HEADERS = "TEST_HEADERS"; + const TEST_STATUS_CODE = "TEST_STATUS_CODE"; + const TEST_STATUS_MESSAGE = "TEST_STATUS_MESSAGE"; + const message = { + activity: TEST_ACTIVITY, + request: { + method: TEST_METHOD, + url: TEST_URL, + headers: TEST_HEADERS, + }, + response: { + statusCode: TEST_STATUS_CODE, + statusMessage: TEST_STATUS_MESSAGE, + headers: TEST_HEADERS, + }, + }; + const expectedItem = { + time: TEST_TIME, + operation: "TRACE", + level: 10, + msg: message, + }; + const expectedContent = [ + `\n[TEST_TIME] - TRACE - ${TEST_ACTIVITY}`, + `\nTEST_METHOD ${TEST_URL}`, + `\nstatus code: ${TEST_STATUS_CODE} ${TEST_STATUS_MESSAGE}`, + `\nRequest headers: ${JSON.stringify("TEST_HEADERS")}`, + `\nResponse headers: ${JSON.stringify(TEST_HEADERS)}`, + "\n----------------------------------------", + ]; + const filePath = path.join(process.cwd(), `ask-cli-${TEST_TIME}.log`); + sinon.stub(console, "log"); + + // call + Messenger.getInstance().trace(message); + + // verify + expect(Messenger.getInstance()._buffer[0]).deep.equal(expectedItem); + + // call + Messenger.getInstance().dispose(); + + // verify + expect(fs.writeFileSync.args[0][0]).deep.equal(filePath); + expect(fs.writeFileSync.args[0][1]).deep.equal(expectedContent); + expect(console.log.args[0][0]).equal(`\nDetail log has been recorded at ${filePath}`); + + // restore console.log first, otherwise cannot print test result to console + console.log.restore(); + }); + + afterEach(() => { + Messenger.getInstance().dispose(); + sinon.restore(); + }); + }); + + describe("Pause and resume functionality", () => { + let displayWithStyleStub; + + beforeEach(() => { + displayWithStyleStub = sinon.stub(Messenger, "displayWithStyle"); + displayWithStyleStub.returns(); + }); + + afterEach(() => { + Messenger.getInstance().dispose(); + sinon.restore(); + }); + + it("| calling pause(), pauses the display messages", () => { + Messenger.getInstance().pause(); + Messenger.getInstance().info(TEST_MESSAGE); + Messenger.getInstance().warn(TEST_MESSAGE); + Messenger.getInstance().error(TEST_MESSAGE); + expect(displayWithStyleStub).not.be.called; + }); + + it("| calling resume() after pause(), writes all the messages that were received while paused", () => { + Messenger.getInstance().pause(); + Messenger.getInstance().info(TEST_MESSAGE); + Messenger.getInstance().warn(TEST_MESSAGE); + Messenger.getInstance().error(TEST_MESSAGE); + expect(displayWithStyleStub).not.be.called; + Messenger.getInstance().resume(); + expect(displayWithStyleStub).be.calledThrice; + expect(displayWithStyleStub.args[0][0]).to.be.null; + expect(displayWithStyleStub.args[0][1]).to.equal("log"); + expect(displayWithStyleStub.args[0][3]).to.contain(TEST_MESSAGE); + expect(displayWithStyleStub.args[1][0]).to.equal("yellow"); + expect(displayWithStyleStub.args[1][1]).to.equal("warn"); + expect(displayWithStyleStub.args[1][3]).to.contain(TEST_MESSAGE); + expect(displayWithStyleStub.args[2][0]).to.equal("red"); + expect(displayWithStyleStub.args[2][1]).to.equal("error"); + expect(displayWithStyleStub.args[2][3]).to.contain(TEST_MESSAGE); + }); + + it("| resume doesn't write previous messages posted before pause was called", () => { + Messenger.getInstance().info(TEST_MESSAGE); + Messenger.getInstance().pause(); + Messenger.getInstance().warn(TEST_MESSAGE); + Messenger.getInstance().error(TEST_MESSAGE); + expect(displayWithStyleStub).be.calledOnce; + Messenger.getInstance().resume(); + expect(displayWithStyleStub).be.calledThrice; + }); + + it("| resume called multiple times only prints paused messages once", () => { + Messenger.getInstance().pause(); + Messenger.getInstance().info(TEST_MESSAGE); + expect(displayWithStyleStub).not.be.called; + Messenger.getInstance().resume(); + Messenger.getInstance().resume(); + Messenger.getInstance().resume(); + expect(displayWithStyleStub).be.calledOnce; + }); + + it("| messages posted after pause/resume are posted immediately", () => { + Messenger.getInstance().pause(); + Messenger.getInstance().info(TEST_MESSAGE); + expect(displayWithStyleStub).not.be.called; + Messenger.getInstance().resume(); + expect(displayWithStyleStub).be.calledOnce; + Messenger.getInstance().warn(TEST_MESSAGE); + Messenger.getInstance().error(TEST_MESSAGE); + expect(displayWithStyleStub).be.calledThrice; + }); + + it("| resume is called upon disposing", () => { + Messenger.getInstance().pause(); + Messenger.getInstance().info(TEST_MESSAGE); + expect(displayWithStyleStub).not.be.called; + Messenger.getInstance().dispose(); + expect(displayWithStyleStub).be.calledOnce; + }); + }); + + it("| displayWithStyle can print bold but no color font", () => { + new Messenger({doDebug: true}); + const stub = sinon.stub(console, "error"); + Messenger.displayWithStyle(null, "error", true, TEST_MESSAGE); + expect(stub.args[0][0]).equal(chalk`{bold ${TEST_MESSAGE}}`); + sinon.restore(); + }); }); diff --git a/test/unit/view/multi-tasks-view-test.js b/test/unit/view/multi-tasks-view-test.js index 4d3f51ae..fedcb3f3 100644 --- a/test/unit/view/multi-tasks-view-test.js +++ b/test/unit/view/multi-tasks-view-test.js @@ -1,302 +1,323 @@ -const { expect } = require('chai'); -const sinon = require('sinon'); -const Listr = require('listr'); -const { EventEmitter } = require('events'); -const { Observable } = require('rxjs'); -const CliError = require('@src/exceptions/cli-error'); -const MultiTasksView = require('@src/view/multi-tasks-view'); +const {expect} = require("chai"); +const sinon = require("sinon"); +const Listr = require("listr"); +const events = require("events"); +const {Observable} = require("rxjs"); +const CliError = require("../../../lib/exceptions/cli-error"); +const MultiTasksView = require("../../../lib/view/multi-tasks-view"); -const { ListrReactiveTask } = MultiTasksView; +const {ListrReactiveTask} = MultiTasksView; +const {EventEmitter} = events; describe('View test - MultiTasksView test', () => { - const TEST_TASK_HANDLE = () => 'taskHandle'; - const TEST_TASK_ID = 'taskId'; - const TEST_TASK_TITLE = 'taskTitle'; - const TEST_OPTIONS = {}; + const TEST_TASK_HANDLE = () => 'taskHandle'; + const TEST_TASK_ID = 'taskId'; + const TEST_TASK_TITLE = 'taskTitle'; + const TEST_OPTIONS = {}; - describe('# inspect correctness for constructor', () => { - it('| initiate as a MultiTasksView class', () => { - const multiTasks = new MultiTasksView(TEST_OPTIONS); - expect(multiTasks).to.be.instanceOf(MultiTasksView); - expect(multiTasks.taskRunner).to.be.instanceOf(Listr); - }); - }); + describe('# inspect correctness for constructor', () => { + it('| initiate as a MultiTasksView class', () => { + const multiTasks = new MultiTasksView(TEST_OPTIONS); + expect(multiTasks).to.be.instanceOf(MultiTasksView); + expect(multiTasks.taskRunner).to.be.instanceOf(Listr); + }); + }); - describe('# test class method: loadTask', () => { - afterEach(() => { - sinon.restore(); - }); + describe('# test class method: loadTask', () => { + afterEach(() => { + sinon.restore(); + }); - it('| load task instantiate a ListrReactiveTask and add it to taskRunner', () => { - // setup - sinon.stub(Listr.prototype, 'add'); - sinon.stub(ListrReactiveTask.prototype, 'buildObservable').returns('obsv'); - const multiTasks = new MultiTasksView(TEST_OPTIONS); - // call - multiTasks.loadTask(TEST_TASK_HANDLE, TEST_TASK_TITLE, TEST_TASK_ID); - // verify - expect(multiTasks._listrTasks.length).equal(1); - expect(Listr.prototype.add.callCount).equal(2); - expect(Listr.prototype.add.args[1][0]).deep.equal({ title: TEST_TASK_TITLE, task: 'obsv' }); - }); - }); + it('| load task instantiate a ListrReactiveTask and add it to taskRunner', () => { + // setup + sinon.stub(Listr.prototype, 'add'); + sinon.stub(ListrReactiveTask.prototype, 'buildObservable').returns('obsv'); + const multiTasks = new MultiTasksView(TEST_OPTIONS); + // call + multiTasks.loadTask(TEST_TASK_HANDLE, TEST_TASK_TITLE, TEST_TASK_ID); + // verify + expect(multiTasks._listrTasks.length).equal(1); + expect(Listr.prototype.add.callCount).equal(2); + expect(Listr.prototype.add.args[1][0]).deep.equal({ title: TEST_TASK_TITLE, task: 'obsv' }); + }); + }); - describe('# test class method: start', () => { - afterEach(() => { - sinon.restore(); - }); + describe('# test class method: start', () => { + afterEach(() => { + sinon.restore(); + }); - it('| task list is empty but still calls start function, expect callback error', (done) => { - // setup - const multiTasks = new MultiTasksView(TEST_OPTIONS); - // call - multiTasks.start((err, res) => { - // verify - expect(res).equal(undefined); - expect(err.error).equal('No tasks in current multi-tasks runner.'); - done(); - }); - }); + it('| task list is empty but still calls start function, expect callback error', (done) => { + // setup + const multiTasks = new MultiTasksView(TEST_OPTIONS); + // call + multiTasks.start((err, res) => { + // verify + expect(res).equal(undefined); + expect(err.error).equal('No tasks in current multi-tasks runner.'); + done(); + }); + }); - it('| task start trigger execute and taskRunner run fails', (done) => { - // setup - const multiTasks = new MultiTasksView(TEST_OPTIONS); - const newTask = new ListrReactiveTask(TEST_TASK_HANDLE, TEST_TASK_ID); - sinon.stub(Listr.prototype, 'run').rejects({ errors: ['error 1', new Error('error 2')] }); - sinon.stub(ListrReactiveTask.prototype, 'execute'); - multiTasks._listrTasks.push(newTask); - // call - multiTasks.start((err, res) => { - // verify - expect(res).equal(undefined); - expect(err.error).eql(new CliError('error 1\nerror 2')); - expect(ListrReactiveTask.prototype.execute.callCount).equal(1); - done(); - }); + it("| task start trigger execute and taskRunner fails with single error", (done) => { + // setup + const multiTasks = new MultiTasksView(TEST_OPTIONS); + const newTask = new ListrReactiveTask(TEST_TASK_HANDLE, TEST_TASK_ID); + sinon.stub(Listr.prototype, "run").rejects("The task failed to run"); + sinon.stub(ListrReactiveTask.prototype, "execute"); + multiTasks._listrTasks.push(newTask); + + // call + multiTasks.start((err, res) => { + // verify + expect(res).equal(undefined); + expect(err.error).property("message", "The task failed to run"); + expect(ListrReactiveTask.prototype.execute.callCount).equal(1); + done(); }); + }); - it('| task start trigger execute and taskRunner run fails with partial context', (done) => { - // setup - const multiTasks = new MultiTasksView(TEST_OPTIONS); - const newTask = new ListrReactiveTask(TEST_TASK_HANDLE, TEST_TASK_ID); - sinon.stub(Listr.prototype, 'run').rejects({ errors: ['error'], context: { result: 'partial' } }); - sinon.stub(ListrReactiveTask.prototype, 'execute'); - multiTasks._listrTasks.push(newTask); - // call - multiTasks.start((err, res) => { - // verify - expect(res).equal(undefined); - expect(err).deep.equal({ error: new CliError('error'), partialResult: { result: 'partial' } }); - expect(ListrReactiveTask.prototype.execute.callCount).equal(1); - done(); - }); - }); + it('| task start trigger execute and taskRunner run fails', (done) => { + // setup + const multiTasks = new MultiTasksView(TEST_OPTIONS); + const newTask = new ListrReactiveTask(TEST_TASK_HANDLE, TEST_TASK_ID); + sinon.stub(Listr.prototype, 'run').rejects({ errors: ['error 1', new Error('error 2')] }); + sinon.stub(ListrReactiveTask.prototype, 'execute'); + multiTasks._listrTasks.push(newTask); + // call + multiTasks.start((err, res) => { + // verify + console.log(err.error.message); + expect(res).equal(undefined); + expect(ListrReactiveTask.prototype.execute.callCount).equal(1); + expect(err.error.message).equals("error 1\nerror 2"); + done(); + }); + }); - it('| task start trigger execute and taskRunner run succeeds', (done) => { - // setup - const multiTasks = new MultiTasksView(TEST_OPTIONS); - const newTask = new ListrReactiveTask(TEST_TASK_HANDLE, TEST_TASK_ID); - sinon.stub(Listr.prototype, 'run').resolves({ result: 'pass' }); - sinon.stub(ListrReactiveTask.prototype, 'execute'); - multiTasks._listrTasks.push(newTask); - // call - multiTasks.start((err, res) => { - // verify - expect(res).deep.equal({ result: 'pass' }); - expect(err).equal(null); - expect(ListrReactiveTask.prototype.execute.callCount).equal(1); - done(); - }); - }); - }); + it('| task start trigger execute and taskRunner run fails with partial context', (done) => { + // setup + const multiTasks = new MultiTasksView(TEST_OPTIONS); + const newTask = new ListrReactiveTask(TEST_TASK_HANDLE, TEST_TASK_ID); + sinon.stub(Listr.prototype, 'run').rejects({ errors: ['error'], context: { result: 'partial' } }); + sinon.stub(ListrReactiveTask.prototype, 'execute'); + multiTasks._listrTasks.push(newTask); + // call + multiTasks.start((err, res) => { + // verify + expect(res).equal(undefined); + expect(err.error.message).equals('error'); + expect(err.partialResult.result).equals('partial'); + expect(ListrReactiveTask.prototype.execute.callCount).equal(1); + done(); + }); + }); + + it('| task start trigger execute and taskRunner run succeeds', (done) => { + // setup + const multiTasks = new MultiTasksView(TEST_OPTIONS); + const newTask = new ListrReactiveTask(TEST_TASK_HANDLE, TEST_TASK_ID); + sinon.stub(Listr.prototype, 'run').resolves({ result: 'pass' }); + sinon.stub(ListrReactiveTask.prototype, 'execute'); + multiTasks._listrTasks.push(newTask); + // call + multiTasks.start((err, res) => { + // verify + expect(res).deep.equal({ result: 'pass' }); + expect(err).equal(null); + expect(ListrReactiveTask.prototype.execute.callCount).equal(1); + done(); + }); + }); + }); }); describe('View test - ListReactiveTask test', () => { - const TEST_TASK_HANDLE = () => 'taskHandle'; - const TEST_TASK_ID = 'taskId'; + const TEST_TASK_HANDLE = () => 'taskHandle'; + const TEST_TASK_ID = 'taskId'; - afterEach(() => { - sinon.restore(); - }); + afterEach(() => { + sinon.restore(); + }); - describe('# inspect correctness for constructor', () => { - it('| initiate as a ListrReactiveTask class', () => { - const rxTask = new ListrReactiveTask(TEST_TASK_HANDLE, TEST_TASK_ID); - expect(rxTask).to.be.instanceOf(ListrReactiveTask); - expect(rxTask.taskHandle).deep.equal(TEST_TASK_HANDLE); - expect(rxTask.taskId).equal(TEST_TASK_ID); - expect(rxTask._eventEmitter).to.be.instanceOf(EventEmitter); - }); - }); + describe('# inspect correctness for constructor', () => { + it('| initiate as a ListrReactiveTask class', () => { + const rxTask = new ListrReactiveTask(TEST_TASK_HANDLE, TEST_TASK_ID); + expect(rxTask).to.be.instanceOf(ListrReactiveTask); + expect(rxTask.taskHandle).deep.equal(TEST_TASK_HANDLE); + expect(rxTask.taskId).equal(TEST_TASK_ID); + expect(rxTask._eventEmitter).to.be.instanceOf(EventEmitter); + }); + }); - describe('# test class method: reporter getter', () => { - it('| getter function returns skipTask method which emit "skip" event', () => { - // setup - const rxTask = new ListrReactiveTask(TEST_TASK_HANDLE, TEST_TASK_ID); - const emitStub = sinon.stub(rxTask._eventEmitter, 'emit'); - // call - rxTask.reporter.skipTask('skippedReason'); - // verify - expect(emitStub.args[0][0]).equal('skip'); - expect(emitStub.args[0][1]).equal('skippedReason'); - }); + describe('# test class method: reporter getter', () => { + it('| getter function returns skipTask method which emit "skip" event', () => { + // setup + const rxTask = new ListrReactiveTask(TEST_TASK_HANDLE, TEST_TASK_ID); + const emitStub = sinon.stub(rxTask._eventEmitter, 'emit'); + // call + rxTask.reporter.skipTask('skippedReason'); + // verify + expect(emitStub.args[0][0]).equal('skip'); + expect(emitStub.args[0][1]).equal('skippedReason'); + }); - it('| getter function returns updateStatus method which emit "status" event', () => { - // setup - const rxTask = new ListrReactiveTask(TEST_TASK_HANDLE, TEST_TASK_ID); - const emitStub = sinon.stub(rxTask._eventEmitter, 'emit'); - // call - rxTask.reporter.updateStatus('statusUpdate'); - // verify - expect(emitStub.args[0][0]).equal('status'); - expect(emitStub.args[0][1]).equal('statusUpdate'); - }); - }); + it('| getter function returns updateStatus method which emit "status" event', () => { + // setup + const rxTask = new ListrReactiveTask(TEST_TASK_HANDLE, TEST_TASK_ID); + const emitStub = sinon.stub(rxTask._eventEmitter, 'emit'); + // call + rxTask.reporter.updateStatus('statusUpdate'); + // verify + expect(emitStub.args[0][0]).equal('status'); + expect(emitStub.args[0][1]).equal('statusUpdate'); + }); + }); - describe('# test class method: execute', () => { - it('| execute task handle but callback with error, expect emit error event', () => { - // setup - const taskHandleStub = sinon.stub().callsArgWith(1, 'errorMessage'); - const rxTask = new ListrReactiveTask(taskHandleStub, TEST_TASK_ID); - const emitStub = sinon.stub(rxTask._eventEmitter, 'emit'); - // call - rxTask.execute(); - // verify - expect(emitStub.args[0][0]).equal('error'); - expect(emitStub.args[0][1]).equal('errorMessage'); - }); + describe('# test class method: execute', () => { + it('| execute task handle but callback with error, expect emit error event', () => { + // setup + const taskHandleStub = sinon.stub().callsArgWith(1, 'errorMessage'); + const rxTask = new ListrReactiveTask(taskHandleStub, TEST_TASK_ID); + const emitStub = sinon.stub(rxTask._eventEmitter, 'emit'); + // call + rxTask.execute(); + // verify + expect(emitStub.args[0][0]).equal('error'); + expect(emitStub.args[0][1]).equal('errorMessage'); + }); - it('| execute task handle with result, expect emit complete event', () => { - // setup - const taskHandleStub = sinon.stub().callsArgWith(1, null, { result: 'pass' }); - const rxTask = new ListrReactiveTask(taskHandleStub, TEST_TASK_ID); - const emitStub = sinon.stub(rxTask._eventEmitter, 'emit'); - // call - rxTask.execute(); - // verify - expect(emitStub.args[0][0]).equal('complete'); - expect(emitStub.args[0][1]).deep.equal({ result: 'pass' }); - }); - }); + it('| execute task handle with result, expect emit complete event', () => { + // setup + const taskHandleStub = sinon.stub().callsArgWith(1, null, { result: 'pass' }); + const rxTask = new ListrReactiveTask(taskHandleStub, TEST_TASK_ID); + const emitStub = sinon.stub(rxTask._eventEmitter, 'emit'); + // call + rxTask.execute(); + // verify + expect(emitStub.args[0][0]).equal('complete'); + expect(emitStub.args[0][1]).deep.equal({ result: 'pass' }); + }); + }); - describe('# test class method: buildObservable', () => { - let TEST_CONTEXT = {}; - let TEST_TASK = {}; + describe('# test class method: buildObservable', () => { + let TEST_CONTEXT = {}; + let TEST_TASK = {}; - beforeEach(() => { - TEST_CONTEXT = {}; - TEST_TASK = {}; - }); + beforeEach(() => { + TEST_CONTEXT = {}; + TEST_TASK = {}; + }); - afterEach(() => { - sinon.restore(); - }); + afterEach(() => { + sinon.restore(); + }); - it('| make sure method returns Observable class', () => { - // setup - const rxTask = new ListrReactiveTask(TEST_TASK_HANDLE, TEST_TASK_ID); - // call - expect(rxTask.buildObservable()(TEST_CONTEXT, TEST_TASK)).to.be.instanceOf(Observable); - }); + it('| make sure method returns Observable class', () => { + // setup + const rxTask = new ListrReactiveTask(TEST_TASK_HANDLE, TEST_TASK_ID); + // call + expect(rxTask.buildObservable()(TEST_CONTEXT, TEST_TASK)).to.be.instanceOf(Observable); + }); - it('| when "status" event emit, expect subscriber to call "next"', () => { - // setup - const subscribeStub = { - next: sinon.stub() - }; - const rxTask = new ListrReactiveTask(TEST_TASK_HANDLE, TEST_TASK_ID); - sinon.stub(rxTask._eventEmitter, 'on').withArgs('status').callsArgWith(1, 'statusUpdate'); - // call - const obsv = rxTask.buildObservable()(TEST_CONTEXT, TEST_TASK); - obsv._subscribe(subscribeStub); - // verify - expect(subscribeStub.next.args[0][0]).equal('statusUpdate'); - }); + it('| when "status" event emit, expect subscriber to call "next"', () => { + // setup + const subscribeStub = { + next: sinon.stub() + }; + const rxTask = new ListrReactiveTask(TEST_TASK_HANDLE, TEST_TASK_ID); + sinon.stub(rxTask._eventEmitter, 'on').withArgs('status').callsArgWith(1, 'statusUpdate'); + // call + const obsv = rxTask.buildObservable()(TEST_CONTEXT, TEST_TASK); + obsv._subscribe(subscribeStub); + // verify + expect(subscribeStub.next.args[0][0]).equal('statusUpdate'); + }); - it('| when "error" event emit, expect subscriber to call "error"', () => { - // setup - const subscribeStub = { - error: sinon.stub() - }; - const rxTask = new ListrReactiveTask(TEST_TASK_HANDLE, TEST_TASK_ID); - sinon.stub(rxTask._eventEmitter, 'on').withArgs('error').callsArgWith(1, 'error'); - // call - const obsv = rxTask.buildObservable()(TEST_CONTEXT, TEST_TASK); - obsv._subscribe(subscribeStub); - // verify - expect(subscribeStub.error.args[0][0]).equal('error'); - }); + it('| when "error" event emit, expect subscriber to call "error"', () => { + // setup + const subscribeStub = { + error: sinon.stub() + }; + const rxTask = new ListrReactiveTask(TEST_TASK_HANDLE, TEST_TASK_ID); + sinon.stub(rxTask._eventEmitter, 'on').withArgs('error').callsArgWith(1, 'error'); + // call + const obsv = rxTask.buildObservable()(TEST_CONTEXT, TEST_TASK); + obsv._subscribe(subscribeStub); + // verify + expect(subscribeStub.error.args[0][0]).equal('error'); + }); - it('| when "error" event emit, expect subscriber to call "error" with partial result', () => { - // setup - const subscribeStub = { - error: sinon.stub() - }; - const rxTask = new ListrReactiveTask(TEST_TASK_HANDLE, TEST_TASK_ID); - sinon.stub(rxTask._eventEmitter, 'on').withArgs('error').callsArgWith(1, { message: 'error', context: 'partial'}); - // call - const obsv = rxTask.buildObservable()(TEST_CONTEXT, TEST_TASK); - obsv._subscribe(subscribeStub); - // verify - expect(subscribeStub.error.args[0][0]).deep.equal({ message: 'error', context: 'partial'}); - expect(TEST_CONTEXT[TEST_TASK_ID]).equal('partial'); - }); + it('| when "error" event emit, expect subscriber to call "error" with partial result', () => { + // setup + const subscribeStub = { + error: sinon.stub() + }; + const rxTask = new ListrReactiveTask(TEST_TASK_HANDLE, TEST_TASK_ID); + sinon.stub(rxTask._eventEmitter, 'on').withArgs('error').callsArgWith(1, { message: 'error', context: 'partial'}); + // call + const obsv = rxTask.buildObservable()(TEST_CONTEXT, TEST_TASK); + obsv._subscribe(subscribeStub); + // verify + expect(subscribeStub.error.args[0][0]).deep.equal({ message: 'error', context: 'partial'}); + expect(TEST_CONTEXT[TEST_TASK_ID]).equal('partial'); + }); - it('| when "skip" event emit, expect task to call "skip"', () => { - // setup - const subscribeStub = {}; - const TEST_TASK = { - skip: sinon.stub() - } - const rxTask = new ListrReactiveTask(TEST_TASK_HANDLE, TEST_TASK_ID); - sinon.stub(rxTask._eventEmitter, 'on').withArgs('skip').callsArgWith(1, 'skippedReason'); - // call - const obsv = rxTask.buildObservable()(TEST_CONTEXT, TEST_TASK); - obsv._subscribe(subscribeStub); - // verify - expect(TEST_TASK.skip.calledOnce).equal(true); - expect(TEST_TASK.skip.args[0][0]).equal('skippedReason'); - }); + it('| when "skip" event emit, expect task to call "skip"', () => { + // setup + const subscribeStub = {}; + const TEST_TASK = { + skip: sinon.stub() + } + const rxTask = new ListrReactiveTask(TEST_TASK_HANDLE, TEST_TASK_ID); + sinon.stub(rxTask._eventEmitter, 'on').withArgs('skip').callsArgWith(1, 'skippedReason'); + // call + const obsv = rxTask.buildObservable()(TEST_CONTEXT, TEST_TASK); + obsv._subscribe(subscribeStub); + // verify + expect(TEST_TASK.skip.calledOnce).equal(true); + expect(TEST_TASK.skip.args[0][0]).equal('skippedReason'); + }); - it('| when "title" event emit, expect task title to be set', () => { - // setup - const subscribeStub = {}; - const rxTask = new ListrReactiveTask(TEST_TASK_HANDLE, TEST_TASK_ID); - sinon.stub(rxTask._eventEmitter, 'on').withArgs('title').callsArgWith(1, 'new title'); - // call - const obsv = rxTask.buildObservable()(TEST_CONTEXT, TEST_TASK); - obsv._subscribe(subscribeStub); - // verify - expect(TEST_TASK.title).equal('new title'); - }); + it('| when "title" event emit, expect task title to be set', () => { + // setup + const subscribeStub = {}; + const rxTask = new ListrReactiveTask(TEST_TASK_HANDLE, TEST_TASK_ID); + sinon.stub(rxTask._eventEmitter, 'on').withArgs('title').callsArgWith(1, 'new title'); + // call + const obsv = rxTask.buildObservable()(TEST_CONTEXT, TEST_TASK); + obsv._subscribe(subscribeStub); + // verify + expect(TEST_TASK.title).equal('new title'); + }); - it('| when "complete" event emit, expect subscriber to call "complete"', () => { - // setup - const subscribeStub = { - complete: sinon.stub() - }; - const rxTask = new ListrReactiveTask(TEST_TASK_HANDLE, TEST_TASK_ID); - sinon.stub(rxTask._eventEmitter, 'on').withArgs('complete').callsArgWith(1); - // call - const obsv = rxTask.buildObservable()(TEST_CONTEXT, TEST_TASK); - obsv._subscribe(subscribeStub); - // verify - expect(subscribeStub.complete.args[0][0]).equal(undefined); - }); + it('| when "complete" event emit, expect subscriber to call "complete"', () => { + // setup + const subscribeStub = { + complete: sinon.stub() + }; + const rxTask = new ListrReactiveTask(TEST_TASK_HANDLE, TEST_TASK_ID); + sinon.stub(rxTask._eventEmitter, 'on').withArgs('complete').callsArgWith(1); + // call + const obsv = rxTask.buildObservable()(TEST_CONTEXT, TEST_TASK); + obsv._subscribe(subscribeStub); + // verify + expect(subscribeStub.complete.args[0][0]).equal(undefined); + }); - it('| when "complete" event emit, expect subscriber to call "complete" with result', () => { - // setup - const subscribeStub = { - complete: sinon.stub() - }; - const rxTask = new ListrReactiveTask(TEST_TASK_HANDLE, TEST_TASK_ID); - sinon.stub(rxTask._eventEmitter, 'on').withArgs('complete').callsArgWith(1, 'done'); - // call - const obsv = rxTask.buildObservable()(TEST_CONTEXT, TEST_TASK); - obsv._subscribe(subscribeStub); - // verify - expect(subscribeStub.complete.args[0][0]).equal(undefined); - expect(TEST_CONTEXT[TEST_TASK_ID]).equal('done'); - }); - }); + it('| when "complete" event emit, expect subscriber to call "complete" with result', () => { + // setup + const subscribeStub = { + complete: sinon.stub() + }; + const rxTask = new ListrReactiveTask(TEST_TASK_HANDLE, TEST_TASK_ID); + sinon.stub(rxTask._eventEmitter, 'on').withArgs('complete').callsArgWith(1, 'done'); + // call + const obsv = rxTask.buildObservable()(TEST_CONTEXT, TEST_TASK); + obsv._subscribe(subscribeStub); + // verify + expect(subscribeStub.complete.args[0][0]).equal(undefined); + expect(TEST_CONTEXT[TEST_TASK_ID]).equal('done'); + }); + }); }); diff --git a/test/unit/view/prompt-view-test.js b/test/unit/view/prompt-view-test.js deleted file mode 100644 index 05ef6827..00000000 --- a/test/unit/view/prompt-view-test.js +++ /dev/null @@ -1,116 +0,0 @@ -const { expect } = require('chai'); -const fs = require('fs'); -const inquirer = require('inquirer'); -const sinon = require('sinon'); - -const Messenger = require('@src/view/messenger'); -const ui = require('@src/view/prompt-view'); - -function validateInquirerConfig(stub, expectedConfig) { - const { message, type, defaultValue, choices } = expectedConfig; - expect(stub.message).equal(message); - expect(stub.type).equal(type); - if (defaultValue) { - expect(stub.default).equal(defaultValue); - } - if (choices) { - expect(stub.choices).deep.equal(choices); - } -} -describe('View test - prompt view test', () => { - const TEST_ERROR = 'init error'; - let infoStub; - let accessSyncStub; - - describe('# validate ui.getProjectFolderName', () => { - beforeEach(() => { - infoStub = sinon.stub(); - sinon.stub(inquirer, 'prompt'); - sinon.stub(Messenger, 'getInstance').returns({ - info: infoStub - }); - accessSyncStub = sinon.stub(fs, 'accessSync'); - }); - - afterEach(() => { - sinon.restore(); - }); - - it('| confirm project folder name from user fails, expect error thrown', (done) => { - // setup - const TEST_DEFAULT_NAME = 'TEST_DEFAULT_NAME'; - inquirer.prompt.rejects(TEST_ERROR); - // call - ui.getProjectFolderName(TEST_DEFAULT_NAME, (err, response) => { - // verify - validateInquirerConfig(inquirer.prompt.args[0][0][0], { - message: 'Please type in your folder name for the skill project (alphanumeric): ', - type: 'input', - default: TEST_DEFAULT_NAME, - }); - expect(err.name).equal(TEST_ERROR); - expect(response).equal(undefined); - done(); - }); - }); - - it('| confirm project folder name from user', (done) => { - // setup - const TEST_DEFAULT_NAME = 'HOSTED-SKILL_NAME@'; - const TEST_FILTERED_NAME = 'HOSTEDSKILLNAME'; - inquirer.prompt.resolves({ projectFolderName: TEST_FILTERED_NAME }); - // call - ui.getProjectFolderName(TEST_DEFAULT_NAME, (err, response) => { - // verify - validateInquirerConfig(inquirer.prompt.args[0][0][0], { - message: 'Please type in your folder name for the skill project (alphanumeric): ', - type: 'input', - default: TEST_DEFAULT_NAME, - name: 'projectFolderName', - }); - expect(err).equal(null); - expect(response).equal(TEST_FILTERED_NAME); - done(); - }); - }); - - it('| project folder name from user with NonAlphanumeric filter is empty, expect error thrown', (done) => { - // setup - const TEST_DEFAULT_NAME = 'HOSTED-SKILL_NAME@'; - inquirer.prompt.resolves({ projectFolderName: TEST_DEFAULT_NAME }); - // call - ui.getProjectFolderName(TEST_DEFAULT_NAME, () => { - // verify - expect(inquirer.prompt.args[0][0][0].validate(TEST_DEFAULT_NAME)).equal(true); - done(); - }); - }); - - it('| project folder name from user with NonAlphanumeric filter is valid, expect return true', (done) => { - // setup - const TEST_DEFAULT_NAME = '@_@'; - const TEST_EMPTY_ERROR = 'Project folder name should consist of alphanumeric character(s) plus "-" only.'; - inquirer.prompt.resolves({ projectFolderName: TEST_DEFAULT_NAME }); - // call - ui.getProjectFolderName(TEST_DEFAULT_NAME, () => { - // verify - expect(inquirer.prompt.args[0][0][0].validate(TEST_DEFAULT_NAME)) - .equal(TEST_EMPTY_ERROR); - done(); - }); - }); - it('| user does not have read/write to project folder, expect return error message string', (done) => { - // setup - const TEST_DEFAULT_NAME = 'some-folder'; - inquirer.prompt.resolves({ projectFolderName: TEST_DEFAULT_NAME }); - accessSyncStub.throws('Some error'); - // call - ui.getProjectFolderName(TEST_DEFAULT_NAME, () => { - // verify - expect(inquirer.prompt.args[0][0][0].validate(TEST_DEFAULT_NAME)) - .include('No write access inside of the folder'); - done(); - }); - }); - }); -}); diff --git a/test/unit/view/prompt-view-test.ts b/test/unit/view/prompt-view-test.ts new file mode 100644 index 00000000..674cfe30 --- /dev/null +++ b/test/unit/view/prompt-view-test.ts @@ -0,0 +1,119 @@ +import {expect} from "chai"; +import fs from "fs"; +import inquirer from "inquirer"; +import sinon, {SinonStub} from "sinon"; + +import Messenger from "../../../lib/view/messenger"; +import * as ui from "../../../lib/view/prompt-view"; + +function validateInquirerConfig( + stub: any, + expectedConfig: { + message: string; + type: string; + defaultName?: string; + }, +) { + const {message, type, defaultName} = expectedConfig; + expect(stub.message).equal(message); + expect(stub.type).equal(type); + if (defaultName) { + expect(stub.default).equal(defaultName); + } +} + +describe("View test - prompt view test", () => { + const TEST_ERROR = "init error"; + let infoStub: SinonStub; + let accessSyncStub: SinonStub; + let inquirerPrompt: SinonStub; + + describe("# validate ui.getProjectFolderName", () => { + beforeEach(() => { + infoStub = sinon.stub(); + inquirerPrompt = sinon.stub(inquirer, "prompt"); + sinon.stub(Messenger, "getInstance").returns({ + info: infoStub, + }); + accessSyncStub = sinon.stub(fs, "accessSync"); + }); + + afterEach(() => { + sinon.restore(); + }); + + it("| confirm project folder name from user fails, expect error thrown", (done) => { + // setup + const TEST_DEFAULT_NAME = "TEST_DEFAULT_NAME"; + inquirerPrompt.rejects(TEST_ERROR); + // call + ui.getProjectFolderName(TEST_DEFAULT_NAME, (err, response) => { + // verify + validateInquirerConfig(inquirerPrompt.args[0][0][0], { + message: "Please type in your folder name for the skill project (alphanumeric): ", + type: "input", + defaultName: TEST_DEFAULT_NAME, + }); + expect(err?.name).equal(TEST_ERROR); + expect(response).equal(undefined); + done(); + }); + }); + + it("| confirm project folder name from user", (done) => { + // setup + const TEST_DEFAULT_NAME = "HOSTED-SKILL_NAME@"; + const TEST_FILTERED_NAME = "HOSTEDSKILLNAME"; + inquirerPrompt.resolves({projectFolderName: TEST_FILTERED_NAME}); + // call + ui.getProjectFolderName(TEST_DEFAULT_NAME, (err, response) => { + // verify + validateInquirerConfig(inquirerPrompt.args[0][0][0], { + message: "Please type in your folder name for the skill project (alphanumeric): ", + type: "input", + defaultName: TEST_DEFAULT_NAME, + }); + expect(err).equal(null); + expect(response).equal(TEST_FILTERED_NAME); + done(); + }); + }); + + it("| project folder name from user with NonAlphanumeric filter is empty, expect error thrown", (done) => { + // setup + const TEST_DEFAULT_NAME = "HOSTED-SKILL_NAME@"; + inquirerPrompt.resolves({projectFolderName: TEST_DEFAULT_NAME}); + // call + ui.getProjectFolderName(TEST_DEFAULT_NAME, () => { + // verify + expect(inquirerPrompt.args[0][0][0].validate(TEST_DEFAULT_NAME)).equal(true); + done(); + }); + }); + + it("| project folder name from user with NonAlphanumeric filter is valid, expect return true", (done) => { + // setup + const TEST_DEFAULT_NAME = "@_@"; + const TEST_EMPTY_ERROR = 'Project folder name should consist of alphanumeric character(s) plus "-" only.'; + inquirerPrompt.resolves({projectFolderName: TEST_DEFAULT_NAME}); + // call + ui.getProjectFolderName(TEST_DEFAULT_NAME, () => { + // verify + expect(inquirerPrompt.args[0][0][0].validate(TEST_DEFAULT_NAME)).equal(TEST_EMPTY_ERROR); + done(); + }); + }); + it("| user does not have read/write to project folder, expect return error message string", (done) => { + // setup + const TEST_DEFAULT_NAME = "some-folder"; + inquirerPrompt.resolves({projectFolderName: TEST_DEFAULT_NAME}); + accessSyncStub.throws("Some error"); + // call + ui.getProjectFolderName(TEST_DEFAULT_NAME, () => { + // verify + expect(inquirerPrompt.args[0][0][0].validate(TEST_DEFAULT_NAME)).include("No write access inside of the folder"); + done(); + }); + }); + }); +}); diff --git a/test/unit/view/spinner-view-test.js b/test/unit/view/spinner-view-test.js index 3d6c7655..c58e9e52 100644 --- a/test/unit/view/spinner-view-test.js +++ b/test/unit/view/spinner-view-test.js @@ -1,181 +1,222 @@ -const { expect } = require('chai'); -const sinon = require('sinon'); -const proxyquire = require('proxyquire'); -const SpinnerView = require('@src/view/spinner-view'); - - -describe('View test - spinner view test', () => { - const TEST_MESSAGE = 'TEST_MESSAGE'; - - describe('# inspect correctness for constructor', () => { - afterEach(() => { - sinon.restore(); - }); - - it('| initiate as a SpinnerView class', () => { - const spinnerView = new SpinnerView(); - expect(spinnerView).to.be.instanceof(SpinnerView); - }); - - it('| make sure SpinnerView class init with default config', () => { - // setup - const oraStub = sinon.stub(); - const ProxySpinnerView = proxyquire('@src/view/spinner-view', { - ora: oraStub - }); - // call - new ProxySpinnerView(); - // verify - expect(oraStub.args[0][0].color).equal('yellow'); - }); - - it('| make sure SpinnerView class init with default config, when platform is not darwin', () => { - // setup - const oraStub = sinon.stub(); - const ProxySpinnerView = proxyquire('@src/view/spinner-view', { - ora: oraStub - }); - sinon.stub(process, 'platform').value('win32'); - // call - new ProxySpinnerView(); - // verify - expect(oraStub.args[0][0]).deep.equal({ color: 'yellow', spinner: 'balloon' }); - }); - - it('| make sure SpinnerView class init custom config', () => { - // setup - const TEST_CUSTOM_CONFIG = { - color: 'blue', - spinner: 'line', - text: 'message' - }; - const oraStub = sinon.stub(); - const ProxySpinnerView = proxyquire('@src/view/spinner-view', { - ora: oraStub - }); - // call - new ProxySpinnerView(TEST_CUSTOM_CONFIG); - // verify - expect(oraStub.args[0][0]).deep.equal(TEST_CUSTOM_CONFIG); - }); - }); - - describe('# test class methods', () => { - let ProxySpinnerView; - let startStub, stopStub, succeedStub, failStub, warnStub, infoStub, stopAndPersistStub; - - beforeEach(() => { - startStub = sinon.stub(); - stopStub = sinon.stub(); - succeedStub = sinon.stub(); - failStub = sinon.stub(); - warnStub = sinon.stub(); - infoStub = sinon.stub(); - stopAndPersistStub = sinon.stub(); - ProxySpinnerView = proxyquire('@src/view/spinner-view', { - ora: () => ({ - start: startStub, - stop: stopStub, - succeed: succeedStub, - fail: failStub, - warn: warnStub, - info: infoStub, - stopAndPersist: stopAndPersistStub - }) - }); - }); - - afterEach(() => { - sinon.restore(); - }); - - it('| test SpinnerView class method - start spinner', () => { - // call - const spinner = new ProxySpinnerView(); - spinner.start(); - // expect - expect(startStub.callCount).equal(1); - expect(startStub.args[0][0]).equal(undefined); - }); - - it('| test SpinnerView class method - start with message', () => { - // call - const spinner = new ProxySpinnerView(); - spinner.start(TEST_MESSAGE); - // expect - expect(startStub.callCount).equal(1); - expect(startStub.args[0][0]).equal(TEST_MESSAGE); - }); - - it('| test SpinnerView class method - update with message', () => { - // call - const spinner = new ProxySpinnerView(); - spinner.update(TEST_MESSAGE); - // expect - expect(spinner.oraSpinner.text).equal(TEST_MESSAGE); - }); - - it('| test SpinnerView class method - terminate with succeed style', () => { - // call - const spinner = new ProxySpinnerView(); - spinner.terminate(SpinnerView.TERMINATE_STYLE.SUCCEED); - // expect - expect(succeedStub.callCount).equal(1); - expect(succeedStub.args[0][0]).equal(undefined); - }); - - it('| test SpinnerView class method - terminate with fail style', () => { - // call - const spinner = new ProxySpinnerView(); - spinner.terminate(SpinnerView.TERMINATE_STYLE.FAIL); - // expect - expect(failStub.callCount).equal(1); - expect(failStub.args[0][0]).equal(undefined); - }); - - it('| test SpinnerView class method - terminate with warn style', () => { - // call - const spinner = new ProxySpinnerView(); - spinner.terminate(SpinnerView.TERMINATE_STYLE.WARN); - // expect - expect(warnStub.callCount).equal(1); - expect(warnStub.args[0][0]).equal(undefined); - }); - - it('| test SpinnerView class method - terminate with info style', () => { - // call - const spinner = new ProxySpinnerView(); - spinner.terminate(SpinnerView.TERMINATE_STYLE.INFO); - // expect - expect(infoStub.callCount).equal(1); - expect(infoStub.args[0][0]).equal(undefined); - }); - - it('| test SpinnerView class method - terminate with persist style', () => { - // call - const spinner = new ProxySpinnerView(); - spinner.terminate(SpinnerView.TERMINATE_STYLE.PERSIST); - // expect - expect(stopAndPersistStub.callCount).equal(1); - expect(stopAndPersistStub.args[0][0]).equal(undefined); - }); - - it('| test SpinnerView class method - terminate with clear style', () => { - // call - const spinner = new ProxySpinnerView(); - spinner.terminate(SpinnerView.TERMINATE_STYLE.CLEAR); - // expect - expect(stopStub.callCount).equal(1); - expect(stopStub.args[0][0]).equal(undefined); - }); - - it('| test SpinnerView class method - terminate with default style', () => { - // call - const spinner = new ProxySpinnerView(); - spinner.terminate(); - // expect - expect(stopStub.callCount).equal(1); - expect(stopStub.args[0][0]).equal(undefined); - }); +const {expect} = require("chai"); +const sinon = require("sinon"); +const proxyquire = require("proxyquire"); +const SpinnerView = require("../../../lib/view/spinner-view"); + +describe("View test - spinner view test", () => { + const TEST_MESSAGE = "TEST_MESSAGE"; + + describe("# inspect correctness for constructor", () => { + afterEach(() => { + sinon.restore(); + }); + + it("| initiate as a SpinnerView class", () => { + const spinnerView = new SpinnerView(); + expect(spinnerView).to.be.instanceof(SpinnerView); + }); + + it("| make sure SpinnerView class init with default config", () => { + // setup + const oraStub = sinon.stub(); + const ProxySpinnerView = proxyquire("../../../lib/view/spinner-view", { + ora: oraStub, + }); + // call + new ProxySpinnerView(); + // verify + expect(oraStub.args[0][0].color).equal("yellow"); + }); + + it("| make sure SpinnerView class init with default config, when platform is not darwin", () => { + // setup + const oraStub = sinon.stub(); + const ProxySpinnerView = proxyquire("../../../lib/view/spinner-view", { + ora: oraStub, + }); + sinon.stub(process, "platform").value("win32"); + // call + new ProxySpinnerView(); + // verify + expect(oraStub.args[0][0]).deep.equal({color: "yellow", spinner: "balloon"}); + }); + + it("| make sure SpinnerView class init custom config", () => { + // setup + const TEST_CUSTOM_CONFIG = { + color: "blue", + spinner: "line", + text: "message", + }; + const oraStub = sinon.stub(); + const ProxySpinnerView = proxyquire("../../../lib/view/spinner-view", { + ora: oraStub, + }); + // call + new ProxySpinnerView(TEST_CUSTOM_CONFIG); + // verify + expect(oraStub.args[0][0]).deep.equal(TEST_CUSTOM_CONFIG); + }); + }); + + describe("# test class methods", () => { + let ProxySpinnerView; + let startStub, stopStub, succeedStub, failStub, warnStub, infoStub, stopAndPersistStub; + + beforeEach(() => { + startStub = sinon.stub(); + stopStub = sinon.stub(); + succeedStub = sinon.stub(); + failStub = sinon.stub(); + warnStub = sinon.stub(); + infoStub = sinon.stub(); + stopAndPersistStub = sinon.stub(); + ProxySpinnerView = proxyquire("../../../lib/view/spinner-view", { + ora: () => ({ + start: startStub, + stop: stopStub, + succeed: succeedStub, + fail: failStub, + warn: warnStub, + info: infoStub, + stopAndPersist: stopAndPersistStub, + text: TEST_MESSAGE, + }), + }); + }); + + afterEach(() => { + sinon.restore(); + }); + + it("| test SpinnerView class method - start spinner", () => { + // call + const spinner = new ProxySpinnerView(); + spinner.start(); + // expect + expect(startStub.callCount).equal(1); + expect(startStub.args[0][0]).equal(undefined); + }); + + it("| test SpinnerView class method - start with message", () => { + // call + const spinner = new ProxySpinnerView(); + spinner.start(TEST_MESSAGE); + // expect + expect(startStub.callCount).equal(1); + expect(startStub.args[0][0]).equal(TEST_MESSAGE); + }); + + it("| test SpinnerView class method - update with message", () => { + // call + const spinner = new ProxySpinnerView(); + spinner.update(TEST_MESSAGE); + // expect + expect(spinner.oraSpinner.text).equal(TEST_MESSAGE); + }); + + it("| test SpinnerView class method - terminate with succeed style", () => { + // call + const spinner = new ProxySpinnerView(); + spinner.terminate(SpinnerView.TERMINATE_STYLE.SUCCEED); + // expect + expect(succeedStub.callCount).equal(1); + expect(succeedStub.args[0][0]).equal(undefined); + }); + + it("| test SpinnerView class method - terminate with fail style", () => { + // call + const spinner = new ProxySpinnerView(); + spinner.terminate(SpinnerView.TERMINATE_STYLE.FAIL); + // expect + expect(failStub.callCount).equal(1); + expect(failStub.args[0][0]).equal(undefined); + }); + + it("| test SpinnerView class method - terminate with warn style", () => { + // call + const spinner = new ProxySpinnerView(); + spinner.terminate(SpinnerView.TERMINATE_STYLE.WARN); + // expect + expect(warnStub.callCount).equal(1); + expect(warnStub.args[0][0]).equal(undefined); + }); + + it("| test SpinnerView class method - terminate with info style", () => { + // call + const spinner = new ProxySpinnerView(); + spinner.terminate(SpinnerView.TERMINATE_STYLE.INFO); + // expect + expect(infoStub.callCount).equal(1); + expect(infoStub.args[0][0]).equal(undefined); + }); + + it("| test SpinnerView class method - terminate with persist style", () => { + // call + const spinner = new ProxySpinnerView(); + spinner.terminate(SpinnerView.TERMINATE_STYLE.PERSIST); + // expect + expect(stopAndPersistStub.callCount).equal(1); + expect(stopAndPersistStub.args[0][0]).equal(undefined); + }); + + it("| test SpinnerView class method - terminate with clear style", () => { + // call + const spinner = new ProxySpinnerView(); + spinner.terminate(SpinnerView.TERMINATE_STYLE.CLEAR); + // expect + expect(stopStub.callCount).equal(1); + expect(stopStub.args[0][0]).equal(undefined); + }); + + it("| test SpinnerView class method - terminate with default style", () => { + // call + const spinner = new ProxySpinnerView(); + spinner.terminate(); + // expect + expect(stopStub.callCount).equal(1); + expect(stopStub.args[0][0]).equal(undefined); + }); + + + it('| test SpinnerView class method - restart with default style', () => { + // call + const spinner = new ProxySpinnerView(); + spinner.start(TEST_MESSAGE); + spinner.restart(); + // expect + expect(stopStub.callCount).equal(1); + expect(stopStub.args[0][0]).equal(undefined); + expect(startStub.callCount).equal(2); + expect(startStub.args[0][0]).equal(TEST_MESSAGE); + expect(startStub.args[1][0]).equal(TEST_MESSAGE); + }); + + it('| test SpinnerView class method - restart with FAIL style', () => { + // call + const spinner = new ProxySpinnerView(); + spinner.start(TEST_MESSAGE); + spinner.restart(SpinnerView.TERMINATE_STYLE.FAIL); + // expect + expect(failStub.callCount).equal(1); + expect(failStub.args[0][0]).equal(undefined); + expect(startStub.callCount).equal(2); + expect(startStub.args[0][0]).equal(TEST_MESSAGE); + expect(startStub.args[1][0]).equal(TEST_MESSAGE); + }); + + it('| test SpinnerView class method - restart with SUCCEED style and a custom message', () => { + // call + const spinner = new ProxySpinnerView(); + const message = 'F00'; + spinner.start(TEST_MESSAGE); + spinner.restart(SpinnerView.TERMINATE_STYLE.SUCCEED, message); + // expect + expect(succeedStub.callCount).equal(1); + expect(succeedStub.args[0][0]).equal(message); + expect(startStub.callCount).equal(2); + expect(startStub.args[0][0]).equal(TEST_MESSAGE); + expect(startStub.args[1][0]).equal(TEST_MESSAGE); }); + }); }); diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 00000000..0918620e --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,49 @@ +{ + "include": ["lib", "bin"], + "compilerOptions": { + "target": "es2018" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', 'ES2021', or 'ESNEXT'. */, + "module": "commonjs" /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */, + "allowJs": true /* Allow javascript files to be compiled. */, + "checkJs": false /* Report errors in .js files. */, + "outDir": "./dist" /* Redirect output structure to the directory. */, + "strict": true /* Enable all strict type-checking options. */, + "skipLibCheck": true, + "resolveJsonModule": true, + // "rootDir": "./lib", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */ + // "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */ + // "strictNullChecks": true, /* Enable strict null checks. */ + // "strictFunctionTypes": true, /* Enable strict checking of function types. */ + // "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */ + // "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */ + // "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */ + "alwaysStrict": true /* Parse in strict mode and emit "use strict" for each source file. */, + + /* Additional Checks */ + "noUnusedLocals": true /* Report errors on unused locals. */, + "noFallthroughCasesInSwitch": true /* Report errors for fallthrough cases in switch statement. */, + "noImplicitReturns": true /* Report error when not all code paths in function return a value. */, + "noUnusedParameters": true /* Report errors on unused parameters. */, + // "noUncheckedIndexedAccess": true, /* Include 'undefined' in index signature results */ + "noImplicitOverride": true /* Ensure overriding members in derived classes are marked with an 'override' modifier. */, + // "noPropertyAccessFromIndexSignature": true, /* Require undeclared properties from index signatures to use element accesses. */ + + /* Module Resolution Options */ + "moduleResolution": "node" /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */, + // "baseUrl": "./", /* Base directory to resolve non-absolute module names. */ + // "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */ + // "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */ + // "typeRoots": [], /* List of folders to include type definitions from. */ + // "types": [], /* Type declaration files to be included in compilation. */ + "allowSyntheticDefaultImports": true /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */, + "esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */, + // "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */ + // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ + + /* Source Map Options */ + // "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */ + // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ + // "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */ + // "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */ + "forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */ + } +} From 345279e0e3006d60c13a941189d838fa75e81ae3 Mon Sep 17 00:00:00 2001 From: Mario Doiron <4956+doiron@users.noreply.github.com> Date: Thu, 30 Mar 2023 11:12:53 -0700 Subject: [PATCH 02/10] feat: migrate release workflow to use github actions --- .github/workflows/release.yml | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 .github/workflows/release.yml diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 00000000..3d05006c --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,21 @@ +name: "Publish the ask-cli package to the npmjs registry" + +# this action will only run when a new GitHub release is published. +on: + release: + types: [published] + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-node@v3 + with: + node-version: '16.x' + registry-url: 'https://registry.npmjs.org' + - run: npm ci + - run: npm test + - run: npm publish + env: + NODE_AUTH_TOKEN: ${{ secrets.ASK_TOOLS_NPM_TOKEN }} From cba137229018be97c909e47cff7bbf1ef289fef3 Mon Sep 17 00:00:00 2001 From: Mario Doiron <4956+doiron@users.noreply.github.com> Date: Thu, 30 Mar 2023 11:40:45 -0700 Subject: [PATCH 03/10] fix: udate node version on github workflows --- .../workflows/functional-test-clean-up.yml | 2 +- .github/workflows/functional-test.yml | 2 +- .github/workflows/integration-test.yml | 2 +- .github/workflows/unit-test.yml | 2 +- package-lock.json | 2781 +++++++++++------ 5 files changed, 1913 insertions(+), 876 deletions(-) diff --git a/.github/workflows/functional-test-clean-up.yml b/.github/workflows/functional-test-clean-up.yml index 7ad84708..9bde89b5 100644 --- a/.github/workflows/functional-test-clean-up.yml +++ b/.github/workflows/functional-test-clean-up.yml @@ -15,7 +15,7 @@ jobs: - name: Use Node.js uses: actions/setup-node@v1 with: - node-version: '12.x' + node-version: '16.x' - run: npm install - run: npm run functional-test:clean-up --unhandled-rejections=strict env: diff --git a/.github/workflows/functional-test.yml b/.github/workflows/functional-test.yml index 96a6b2a9..59a3f1c1 100644 --- a/.github/workflows/functional-test.yml +++ b/.github/workflows/functional-test.yml @@ -16,7 +16,7 @@ jobs: - name: Use Node.js uses: actions/setup-node@v1 with: - node-version: '12.x' + node-version: '16.x' - run: git config --global user.email "ask-cli-test@amazon.com" - run: git config --global user.name "Ask Cli Test" - run: npm install diff --git a/.github/workflows/integration-test.yml b/.github/workflows/integration-test.yml index 4eb1d64d..de61b601 100644 --- a/.github/workflows/integration-test.yml +++ b/.github/workflows/integration-test.yml @@ -18,7 +18,7 @@ jobs: strategy: matrix: os: [ubuntu-latest, windows-latest, macos-latest] - node: [12, 14, 16] + node: [14, 16] steps: - uses: actions/checkout@v3 diff --git a/.github/workflows/unit-test.yml b/.github/workflows/unit-test.yml index b21d020f..c5032688 100644 --- a/.github/workflows/unit-test.yml +++ b/.github/workflows/unit-test.yml @@ -18,7 +18,7 @@ jobs: strategy: matrix: os: [ubuntu-latest, windows-latest, macos-latest] - node: [12, 14, 16] + node: [14, 16] steps: - uses: actions/checkout@v3 diff --git a/package-lock.json b/package-lock.json index c36ecc83..a70873a6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -122,6 +122,7 @@ }, "node_modules/@alexa/acdl/node_modules/ask-smapi-model": { "version": "1.23.0", + "resolved": "https://registry.npmjs.org/ask-smapi-model/-/ask-smapi-model-1.23.0.tgz", "integrity": "sha512-wGpHSvd1qIwqDw5YJPpga0HUFQItoT13LZAm1s4hpCcxY18vwPu5IK6w19syGztWAc2qn4k6fDDhz1UrgPm07A==", "dependencies": { "ask-sdk-model-runtime": "^1.1.0" @@ -129,10 +130,12 @@ }, "node_modules/@alexa/ask-expressions-spec": { "version": "0.0.2", + "resolved": "https://registry.npmjs.org/@alexa/ask-expressions-spec/-/ask-expressions-spec-0.0.2.tgz", "integrity": "sha512-/yk3yp6HCCtAlzujRByxY9JqHt/h1LVQE0KUKM16TlVD318gWHBH50zuSpAse5K+doCDWQYLrgxHc5etE0AKAw==" }, "node_modules/@ampproject/remapping": { "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.0.tgz", "integrity": "sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==", "dev": true, "dependencies": { @@ -145,6 +148,7 @@ }, "node_modules/@babel/code-frame": { "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz", "integrity": "sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==", "dev": true, "dependencies": { @@ -155,28 +159,30 @@ } }, "node_modules/@babel/compat-data": { - "version": "7.20.10", - "integrity": "sha512-sEnuDPpOJR/fcafHMjpcpGN5M2jbUGUHwmuWKM/YdPzeEDJg8bgmbcWQFUfE32MQjti1koACvoPVsDe8Uq+idg==", + "version": "7.21.0", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.21.0.tgz", + "integrity": "sha512-gMuZsmsgxk/ENC3O/fRw5QY8A9/uxQbbCEypnLIiYYc/qVJtEV7ouxC3EllIIwNzMqAQee5tanFabWsUOutS7g==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/core": { - "version": "7.20.12", - "integrity": "sha512-XsMfHovsUYHFMdrIHkZphTN/2Hzzi78R08NuHfDBehym2VsPDL6Zn/JAD/JQdnRvbSsbQc4mVaU1m6JgtTEElg==", + "version": "7.21.3", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.21.3.tgz", + "integrity": "sha512-qIJONzoa/qiHghnm0l1n4i/6IIziDpzqc36FBs4pzMhDUraHqponwJLiAKm1hGLP3OSB/TVNz6rMwVGpwxxySw==", "dev": true, "dependencies": { - "@ampproject/remapping": "^2.1.0", + "@ampproject/remapping": "^2.2.0", "@babel/code-frame": "^7.18.6", - "@babel/generator": "^7.20.7", + "@babel/generator": "^7.21.3", "@babel/helper-compilation-targets": "^7.20.7", - "@babel/helper-module-transforms": "^7.20.11", - "@babel/helpers": "^7.20.7", - "@babel/parser": "^7.20.7", + "@babel/helper-module-transforms": "^7.21.2", + "@babel/helpers": "^7.21.0", + "@babel/parser": "^7.21.3", "@babel/template": "^7.20.7", - "@babel/traverse": "^7.20.12", - "@babel/types": "^7.20.7", + "@babel/traverse": "^7.21.3", + "@babel/types": "^7.21.3", "convert-source-map": "^1.7.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", @@ -193,6 +199,7 @@ }, "node_modules/@babel/core/node_modules/semver": { "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", "dev": true, "bin": { @@ -200,12 +207,14 @@ } }, "node_modules/@babel/generator": { - "version": "7.20.7", - "integrity": "sha512-7wqMOJq8doJMZmP4ApXTzLxSr7+oO2jroJURrVEp6XShrQUObV8Tq/D0NCcoYg2uHqUrjzO0zwBjoYzelxK+sw==", + "version": "7.21.3", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.21.3.tgz", + "integrity": "sha512-QS3iR1GYC/YGUnW7IdggFeN5c1poPUurnGttOV/bZgPGV+izC/D8HnD6DLwod0fsatNyVn1G3EVWMYIF0nHbeA==", "dev": true, "dependencies": { - "@babel/types": "^7.20.7", + "@babel/types": "^7.21.3", "@jridgewell/gen-mapping": "^0.3.2", + "@jridgewell/trace-mapping": "^0.3.17", "jsesc": "^2.5.1" }, "engines": { @@ -214,6 +223,7 @@ }, "node_modules/@babel/generator/node_modules/@jridgewell/gen-mapping": { "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", "dev": true, "dependencies": { @@ -225,8 +235,19 @@ "node": ">=6.0.0" } }, + "node_modules/@babel/generator/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.17", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz", + "integrity": "sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g==", + "dev": true, + "dependencies": { + "@jridgewell/resolve-uri": "3.1.0", + "@jridgewell/sourcemap-codec": "1.4.14" + } + }, "node_modules/@babel/helper-compilation-targets": { "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.20.7.tgz", "integrity": "sha512-4tGORmfQcrc+bvrjb5y3dG9Mx1IOZjsHqQVUz7XCNHO+iTmqxWnVg3KRygjGmpRLJGdQSKuvFinbIb0CnZwHAQ==", "dev": true, "dependencies": { @@ -243,16 +264,33 @@ "@babel/core": "^7.0.0" } }, + "node_modules/@babel/helper-compilation-targets/node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "dependencies": { + "yallist": "^3.0.2" + } + }, "node_modules/@babel/helper-compilation-targets/node_modules/semver": { "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", "dev": true, "bin": { "semver": "bin/semver.js" } }, + "node_modules/@babel/helper-compilation-targets/node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true + }, "node_modules/@babel/helper-environment-visitor": { "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz", "integrity": "sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg==", "dev": true, "engines": { @@ -260,12 +298,13 @@ } }, "node_modules/@babel/helper-function-name": { - "version": "7.19.0", - "integrity": "sha512-WAwHBINyrpqywkUH0nTnNgI5ina5TFn85HKS0pbPDfxFfhyR/aNQEn4hGi1P1JyT//I0t4OgXUlofzWILRvS5w==", + "version": "7.21.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.21.0.tgz", + "integrity": "sha512-HfK1aMRanKHpxemaY2gqBmL04iAPOPRj7DxtNbiDOrJK+gdwkiNRVpCpUJYbUT+aZyemKN8brqTOxzCaG6ExRg==", "dev": true, "dependencies": { - "@babel/template": "^7.18.10", - "@babel/types": "^7.19.0" + "@babel/template": "^7.20.7", + "@babel/types": "^7.21.0" }, "engines": { "node": ">=6.9.0" @@ -273,6 +312,7 @@ }, "node_modules/@babel/helper-hoist-variables": { "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz", "integrity": "sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==", "dev": true, "dependencies": { @@ -284,6 +324,7 @@ }, "node_modules/@babel/helper-module-imports": { "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.18.6.tgz", "integrity": "sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA==", "dev": true, "dependencies": { @@ -294,8 +335,9 @@ } }, "node_modules/@babel/helper-module-transforms": { - "version": "7.20.11", - "integrity": "sha512-uRy78kN4psmji1s2QtbtcCSaj/LILFDp0f/ymhpQH5QY3nljUZCaNWz9X1dEj/8MBdBEFECs7yRhKn8i7NjZgg==", + "version": "7.21.2", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.21.2.tgz", + "integrity": "sha512-79yj2AR4U/Oqq/WOV7Lx6hUjau1Zfo4cI+JLAVYeMV5XIlbOhmjEk5ulbTc9fMpmlojzZHkUUxAiK+UKn+hNQQ==", "dev": true, "dependencies": { "@babel/helper-environment-visitor": "^7.18.9", @@ -304,8 +346,8 @@ "@babel/helper-split-export-declaration": "^7.18.6", "@babel/helper-validator-identifier": "^7.19.1", "@babel/template": "^7.20.7", - "@babel/traverse": "^7.20.10", - "@babel/types": "^7.20.7" + "@babel/traverse": "^7.21.2", + "@babel/types": "^7.21.2" }, "engines": { "node": ">=6.9.0" @@ -313,6 +355,7 @@ }, "node_modules/@babel/helper-plugin-utils": { "version": "7.20.2", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.20.2.tgz", "integrity": "sha512-8RvlJG2mj4huQ4pZ+rU9lqKi9ZKiRmuvGuM2HlWmkmgOhbs6zEAw6IEiJ5cQqGbDzGZOhwuOQNtZMi/ENLjZoQ==", "dev": true, "engines": { @@ -321,6 +364,7 @@ }, "node_modules/@babel/helper-simple-access": { "version": "7.20.2", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.20.2.tgz", "integrity": "sha512-+0woI/WPq59IrqDYbVGfshjT5Dmk/nnbdpcF8SnMhhXObpTq2KNBdLFRFrkVdbDOyUmHBCxzm5FHV1rACIkIbA==", "dev": true, "dependencies": { @@ -332,6 +376,7 @@ }, "node_modules/@babel/helper-split-export-declaration": { "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz", "integrity": "sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==", "dev": true, "dependencies": { @@ -343,6 +388,7 @@ }, "node_modules/@babel/helper-string-parser": { "version": "7.19.4", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.19.4.tgz", "integrity": "sha512-nHtDoQcuqFmwYNYPz3Rah5ph2p8PFeFCsZk9A/48dPc/rGocJ5J3hAAZ7pb76VWX3fZKu+uEr/FhH5jLx7umrw==", "dev": true, "engines": { @@ -351,6 +397,7 @@ }, "node_modules/@babel/helper-validator-identifier": { "version": "7.19.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz", "integrity": "sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==", "dev": true, "engines": { @@ -358,21 +405,23 @@ } }, "node_modules/@babel/helper-validator-option": { - "version": "7.18.6", - "integrity": "sha512-XO7gESt5ouv/LRJdrVjkShckw6STTaB7l9BrpBaAHDeF5YZT+01PCwmR0SJHnkW6i8OwW/EVWRShfi4j2x+KQw==", + "version": "7.21.0", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.21.0.tgz", + "integrity": "sha512-rmL/B8/f0mKS2baE9ZpyTcTavvEuWhTTW8amjzXNvYG4AwBsqTLikfXsEofsJEfKHf+HQVQbFOHy6o+4cnC/fQ==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helpers": { - "version": "7.20.13", - "integrity": "sha512-nzJ0DWCL3gB5RCXbUO3KIMMsBY2Eqbx8mBpKGE/02PgyRQFcPQLbkQ1vyy596mZLaP+dAfD+R4ckASzNVmW3jg==", + "version": "7.21.0", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.21.0.tgz", + "integrity": "sha512-XXve0CBtOW0pd7MRzzmoyuSj0e3SEzj8pgyFxnTT1NJZL38BD1MK7yYrm8yefRPIDvNNe14xR4FdbHwpInD4rA==", "dev": true, "dependencies": { "@babel/template": "^7.20.7", - "@babel/traverse": "^7.20.13", - "@babel/types": "^7.20.7" + "@babel/traverse": "^7.21.0", + "@babel/types": "^7.21.0" }, "engines": { "node": ">=6.9.0" @@ -380,6 +429,7 @@ }, "node_modules/@babel/highlight": { "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz", "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==", "dev": true, "dependencies": { @@ -393,6 +443,7 @@ }, "node_modules/@babel/highlight/node_modules/ansi-styles": { "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", "dev": true, "dependencies": { @@ -404,6 +455,7 @@ }, "node_modules/@babel/highlight/node_modules/chalk": { "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "dev": true, "dependencies": { @@ -417,6 +469,7 @@ }, "node_modules/@babel/highlight/node_modules/color-convert": { "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", "dev": true, "dependencies": { @@ -425,11 +478,13 @@ }, "node_modules/@babel/highlight/node_modules/color-name": { "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", "dev": true }, "node_modules/@babel/highlight/node_modules/has-flag": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", "dev": true, "engines": { @@ -438,6 +493,7 @@ }, "node_modules/@babel/highlight/node_modules/supports-color": { "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", "dev": true, "dependencies": { @@ -448,8 +504,9 @@ } }, "node_modules/@babel/parser": { - "version": "7.20.13", - "integrity": "sha512-gFDLKMfpiXCsjt4za2JA9oTMn70CeseCehb11kRZgvd7+F67Hih3OHOK24cRrWECJ/ljfPGac6ygXAs/C8kIvw==", + "version": "7.21.3", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.21.3.tgz", + "integrity": "sha512-lobG0d7aOfQRXh8AyklEAgZGvA4FShxo6xQbUrrT/cNBPUdIDojlokwJsQyCC/eKia7ifqM0yP+2DRZ4WKw2RQ==", "dev": true, "bin": { "parser": "bin/babel-parser.js" @@ -460,6 +517,7 @@ }, "node_modules/@babel/plugin-syntax-async-generators": { "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", "dev": true, "dependencies": { @@ -471,6 +529,7 @@ }, "node_modules/@babel/plugin-syntax-bigint": { "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz", "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==", "dev": true, "dependencies": { @@ -482,6 +541,7 @@ }, "node_modules/@babel/plugin-syntax-class-properties": { "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", "dev": true, "dependencies": { @@ -493,6 +553,7 @@ }, "node_modules/@babel/plugin-syntax-import-meta": { "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", "dev": true, "dependencies": { @@ -504,6 +565,7 @@ }, "node_modules/@babel/plugin-syntax-json-strings": { "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", "dev": true, "dependencies": { @@ -515,6 +577,7 @@ }, "node_modules/@babel/plugin-syntax-logical-assignment-operators": { "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", "dev": true, "dependencies": { @@ -526,6 +589,7 @@ }, "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": { "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", "dev": true, "dependencies": { @@ -537,6 +601,7 @@ }, "node_modules/@babel/plugin-syntax-numeric-separator": { "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", "dev": true, "dependencies": { @@ -548,6 +613,7 @@ }, "node_modules/@babel/plugin-syntax-object-rest-spread": { "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", "dev": true, "dependencies": { @@ -559,6 +625,7 @@ }, "node_modules/@babel/plugin-syntax-optional-catch-binding": { "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", "dev": true, "dependencies": { @@ -570,6 +637,7 @@ }, "node_modules/@babel/plugin-syntax-optional-chaining": { "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", "dev": true, "dependencies": { @@ -581,6 +649,7 @@ }, "node_modules/@babel/plugin-syntax-top-level-await": { "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", "dev": true, "dependencies": { @@ -595,6 +664,7 @@ }, "node_modules/@babel/plugin-syntax-typescript": { "version": "7.20.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.20.0.tgz", "integrity": "sha512-rd9TkG+u1CExzS4SM1BlMEhMXwFLKVjOAFFCDx9PbX5ycJWDoWMcwdJH9RhkPu1dOgn5TrxLot/Gx6lWFuAUNQ==", "dev": true, "dependencies": { @@ -609,6 +679,7 @@ }, "node_modules/@babel/template": { "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.20.7.tgz", "integrity": "sha512-8SegXApWe6VoNw0r9JHpSteLKTpTiLZ4rMlGIm9JQ18KiCtyQiAMEazujAHrUS5flrcqYZa75ukev3P6QmUwUw==", "dev": true, "dependencies": { @@ -621,18 +692,19 @@ } }, "node_modules/@babel/traverse": { - "version": "7.20.13", - "integrity": "sha512-kMJXfF0T6DIS9E8cgdLCSAL+cuCK+YEZHWiLK0SXpTo8YRj5lpJu3CDNKiIBCne4m9hhTIqUg6SYTAI39tAiVQ==", + "version": "7.21.3", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.21.3.tgz", + "integrity": "sha512-XLyopNeaTancVitYZe2MlUEvgKb6YVVPXzofHgqHijCImG33b/uTurMS488ht/Hbsb2XK3U2BnSTxKVNGV3nGQ==", "dev": true, "dependencies": { "@babel/code-frame": "^7.18.6", - "@babel/generator": "^7.20.7", + "@babel/generator": "^7.21.3", "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-function-name": "^7.19.0", + "@babel/helper-function-name": "^7.21.0", "@babel/helper-hoist-variables": "^7.18.6", "@babel/helper-split-export-declaration": "^7.18.6", - "@babel/parser": "^7.20.13", - "@babel/types": "^7.20.7", + "@babel/parser": "^7.21.3", + "@babel/types": "^7.21.3", "debug": "^4.1.0", "globals": "^11.1.0" }, @@ -641,8 +713,9 @@ } }, "node_modules/@babel/types": { - "version": "7.20.7", - "integrity": "sha512-69OnhBxSSgK0OzTJai4kyPDiKTIe3j+ctaHdIGVbRahTLAT7L3R9oeXHC2aVSuGYt3cVnoAMDmOCgJ2yaiLMvg==", + "version": "7.21.3", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.21.3.tgz", + "integrity": "sha512-sBGdETxC+/M4o/zKC0sl6sjWv62WFR/uzxrJ6uYyMLZOUlPnwzw0tKgVHOXxaAd5l2g8pEDM5RZ495GPQI77kg==", "dev": true, "dependencies": { "@babel/helper-string-parser": "^7.19.4", @@ -655,6 +728,7 @@ }, "node_modules/@commitlint/cli": { "version": "16.3.0", + "resolved": "https://registry.npmjs.org/@commitlint/cli/-/cli-16.3.0.tgz", "integrity": "sha512-P+kvONlfsuTMnxSwWE1H+ZcPMY3STFaHb2kAacsqoIkNx66O0T7sTpBxpxkMrFPyhkJiLJnJWMhk4bbvYD3BMA==", "dev": true, "dependencies": { @@ -677,6 +751,7 @@ }, "node_modules/@commitlint/config-conventional": { "version": "16.2.4", + "resolved": "https://registry.npmjs.org/@commitlint/config-conventional/-/config-conventional-16.2.4.tgz", "integrity": "sha512-av2UQJa3CuE5P0dzxj/o/B9XVALqYzEViHrMXtDrW9iuflrqCStWBAioijppj9URyz6ONpohJKAtSdgAOE0gkA==", "dev": true, "dependencies": { @@ -688,6 +763,7 @@ }, "node_modules/@commitlint/config-validator": { "version": "16.2.1", + "resolved": "https://registry.npmjs.org/@commitlint/config-validator/-/config-validator-16.2.1.tgz", "integrity": "sha512-hogSe0WGg7CKmp4IfNbdNES3Rq3UEI4XRPB8JL4EPgo/ORq5nrGTVzxJh78omibNuB8Ho4501Czb1Er1MoDWpw==", "dev": true, "dependencies": { @@ -700,6 +776,7 @@ }, "node_modules/@commitlint/config-validator/node_modules/ajv": { "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "dev": true, "dependencies": { @@ -715,11 +792,13 @@ }, "node_modules/@commitlint/config-validator/node_modules/json-schema-traverse": { "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", "dev": true }, "node_modules/@commitlint/ensure": { "version": "16.2.1", + "resolved": "https://registry.npmjs.org/@commitlint/ensure/-/ensure-16.2.1.tgz", "integrity": "sha512-/h+lBTgf1r5fhbDNHOViLuej38i3rZqTQnBTk+xEg+ehOwQDXUuissQ5GsYXXqI5uGy+261ew++sT4EA3uBJ+A==", "dev": true, "dependencies": { @@ -732,6 +811,7 @@ }, "node_modules/@commitlint/execute-rule": { "version": "16.2.1", + "resolved": "https://registry.npmjs.org/@commitlint/execute-rule/-/execute-rule-16.2.1.tgz", "integrity": "sha512-oSls82fmUTLM6cl5V3epdVo4gHhbmBFvCvQGHBRdQ50H/690Uq1Dyd7hXMuKITCIdcnr9umyDkr8r5C6HZDF3g==", "dev": true, "engines": { @@ -740,6 +820,7 @@ }, "node_modules/@commitlint/format": { "version": "16.2.1", + "resolved": "https://registry.npmjs.org/@commitlint/format/-/format-16.2.1.tgz", "integrity": "sha512-Yyio9bdHWmNDRlEJrxHKglamIk3d6hC0NkEUW6Ti6ipEh2g0BAhy8Od6t4vLhdZRa1I2n+gY13foy+tUgk0i1Q==", "dev": true, "dependencies": { @@ -752,6 +833,7 @@ }, "node_modules/@commitlint/is-ignored": { "version": "16.2.4", + "resolved": "https://registry.npmjs.org/@commitlint/is-ignored/-/is-ignored-16.2.4.tgz", "integrity": "sha512-Lxdq9aOAYCOOOjKi58ulbwK/oBiiKz+7Sq0+/SpFIEFwhHkIVugvDvWjh2VRBXmRC/x5lNcjDcYEwS/uYUvlYQ==", "dev": true, "dependencies": { @@ -762,19 +844,9 @@ "node": ">=v12" } }, - "node_modules/@commitlint/is-ignored/node_modules/lru-cache": { - "version": "6.0.0", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/@commitlint/is-ignored/node_modules/semver": { "version": "7.3.7", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", "dev": true, "dependencies": { @@ -787,13 +859,9 @@ "node": ">=10" } }, - "node_modules/@commitlint/is-ignored/node_modules/yallist": { - "version": "4.0.0", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, "node_modules/@commitlint/lint": { "version": "16.2.4", + "resolved": "https://registry.npmjs.org/@commitlint/lint/-/lint-16.2.4.tgz", "integrity": "sha512-AUDuwOxb2eGqsXbTMON3imUGkc1jRdtXrbbohiLSCSk3jFVXgJLTMaEcr39pR00N8nE9uZ+V2sYaiILByZVmxQ==", "dev": true, "dependencies": { @@ -808,6 +876,7 @@ }, "node_modules/@commitlint/load": { "version": "16.3.0", + "resolved": "https://registry.npmjs.org/@commitlint/load/-/load-16.3.0.tgz", "integrity": "sha512-3tykjV/iwbkv2FU9DG+NZ/JqmP0Nm3b7aDwgCNQhhKV5P74JAuByULkafnhn+zsFGypG1qMtI5u+BZoa9APm0A==", "dev": true, "dependencies": { @@ -829,6 +898,7 @@ }, "node_modules/@commitlint/message": { "version": "16.2.1", + "resolved": "https://registry.npmjs.org/@commitlint/message/-/message-16.2.1.tgz", "integrity": "sha512-2eWX/47rftViYg7a3axYDdrgwKv32mxbycBJT6OQY/MJM7SUfYNYYvbMFOQFaA4xIVZt7t2Alyqslbl6blVwWw==", "dev": true, "engines": { @@ -837,6 +907,7 @@ }, "node_modules/@commitlint/parse": { "version": "16.2.1", + "resolved": "https://registry.npmjs.org/@commitlint/parse/-/parse-16.2.1.tgz", "integrity": "sha512-2NP2dDQNL378VZYioLrgGVZhWdnJO4nAxQl5LXwYb08nEcN+cgxHN1dJV8OLJ5uxlGJtDeR8UZZ1mnQ1gSAD/g==", "dev": true, "dependencies": { @@ -850,6 +921,7 @@ }, "node_modules/@commitlint/read": { "version": "16.2.1", + "resolved": "https://registry.npmjs.org/@commitlint/read/-/read-16.2.1.tgz", "integrity": "sha512-tViXGuaxLTrw2r7PiYMQOFA2fueZxnnt0lkOWqKyxT+n2XdEMGYcI9ID5ndJKXnfPGPppD0w/IItKsIXlZ+alw==", "dev": true, "dependencies": { @@ -864,6 +936,7 @@ }, "node_modules/@commitlint/resolve-extends": { "version": "16.2.1", + "resolved": "https://registry.npmjs.org/@commitlint/resolve-extends/-/resolve-extends-16.2.1.tgz", "integrity": "sha512-NbbCMPKTFf2J805kwfP9EO+vV+XvnaHRcBy6ud5dF35dxMsvdJqke54W3XazXF1ZAxC4a3LBy4i/GNVBAthsEg==", "dev": true, "dependencies": { @@ -880,6 +953,7 @@ }, "node_modules/@commitlint/rules": { "version": "16.2.4", + "resolved": "https://registry.npmjs.org/@commitlint/rules/-/rules-16.2.4.tgz", "integrity": "sha512-rK5rNBIN2ZQNQK+I6trRPK3dWa0MtaTN4xnwOma1qxa4d5wQMQJtScwTZjTJeallFxhOgbNOgr48AMHkdounVg==", "dev": true, "dependencies": { @@ -895,6 +969,7 @@ }, "node_modules/@commitlint/to-lines": { "version": "16.2.1", + "resolved": "https://registry.npmjs.org/@commitlint/to-lines/-/to-lines-16.2.1.tgz", "integrity": "sha512-9/VjpYj5j1QeY3eiog1zQWY6axsdWAc0AonUUfyZ7B0MVcRI0R56YsHAfzF6uK/g/WwPZaoe4Lb1QCyDVnpVaQ==", "dev": true, "engines": { @@ -903,6 +978,7 @@ }, "node_modules/@commitlint/top-level": { "version": "16.2.1", + "resolved": "https://registry.npmjs.org/@commitlint/top-level/-/top-level-16.2.1.tgz", "integrity": "sha512-lS6GSieHW9y6ePL73ied71Z9bOKyK+Ib9hTkRsB8oZFAyQZcyRwq2w6nIa6Fngir1QW51oKzzaXfJL94qwImyw==", "dev": true, "dependencies": { @@ -912,8 +988,70 @@ "node": ">=v12" } }, + "node_modules/@commitlint/top-level/node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@commitlint/top-level/node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@commitlint/top-level/node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@commitlint/top-level/node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/@commitlint/types": { "version": "16.2.1", + "resolved": "https://registry.npmjs.org/@commitlint/types/-/types-16.2.1.tgz", "integrity": "sha512-7/z7pA7BM0i8XvMSBynO7xsB3mVQPUZbVn6zMIlp/a091XJ3qAXRXc+HwLYhiIdzzS5fuxxNIHZMGHVD4HJxdA==", "dev": true, "dependencies": { @@ -925,6 +1063,7 @@ }, "node_modules/@cspotcode/source-map-support": { "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", "dev": true, "dependencies": { @@ -934,17 +1073,9 @@ "node": ">=12" } }, - "node_modules/@cspotcode/source-map-support/node_modules/@jridgewell/trace-mapping": { - "version": "0.3.9", - "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", - "dev": true, - "dependencies": { - "@jridgewell/resolve-uri": "^3.0.3", - "@jridgewell/sourcemap-codec": "^1.4.10" - } - }, "node_modules/@faker-js/faker": { "version": "6.3.1", + "resolved": "https://registry.npmjs.org/@faker-js/faker/-/faker-6.3.1.tgz", "integrity": "sha512-8YXBE2ZcU/pImVOHX7MWrSR/X5up7t6rPWZlk34RwZEcdr3ua6X+32pSd6XuOQRN+vbuvYNfA6iey8NbrjuMFQ==", "dev": true, "engines": { @@ -954,11 +1085,13 @@ }, "node_modules/@gar/promisify": { "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@gar/promisify/-/promisify-1.1.3.tgz", "integrity": "sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==", "dev": true }, "node_modules/@hutson/parse-repository-url": { "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@hutson/parse-repository-url/-/parse-repository-url-3.0.2.tgz", "integrity": "sha512-H9XAx3hc0BQHY6l+IFSWHDySypcXsvsuLhgYLUGywmJ5pswRVQJUHpOsobnLYp2ZUaUlKiKDrgWWhosOwAEM8Q==", "dev": true, "engines": { @@ -967,6 +1100,7 @@ }, "node_modules/@istanbuljs/load-nyc-config": { "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", "dev": true, "dependencies": { @@ -982,26 +1116,16 @@ }, "node_modules/@istanbuljs/load-nyc-config/node_modules/argparse": { "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", "dev": true, "dependencies": { "sprintf-js": "~1.0.2" } }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/find-up": { - "version": "4.1.0", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, - "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/@istanbuljs/load-nyc-config/node_modules/js-yaml": { "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", "dev": true, "dependencies": { @@ -1012,44 +1136,9 @@ "js-yaml": "bin/js-yaml.js" } }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/locate-path": { - "version": "5.0.0", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, - "dependencies": { - "p-locate": "^4.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/p-limit": { - "version": "2.3.0", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/p-locate": { - "version": "4.1.0", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, - "dependencies": { - "p-limit": "^2.2.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/@istanbuljs/nyc-config-typescript": { "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@istanbuljs/nyc-config-typescript/-/nyc-config-typescript-1.0.2.tgz", "integrity": "sha512-iKGIyMoyJuFnJRSVTZ78POIRvNnwZaWIf8vG4ZS3rQq58MMDrqEX2nnzx0R28V2X8JvmKYiqY9FP2hlJsm8A0w==", "dev": true, "dependencies": { @@ -1064,6 +1153,7 @@ }, "node_modules/@istanbuljs/schema": { "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", "dev": true, "engines": { @@ -1072,6 +1162,7 @@ }, "node_modules/@jest/console": { "version": "28.1.3", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-28.1.3.tgz", "integrity": "sha512-QPAkP5EwKdK/bxIr6C1I4Vs0rm2nHiANzj/Z5X2JQkrZo6IqvC4ldZ9K95tF0HdidhA8Bo6egxSzUFPYKcEXLw==", "dev": true, "dependencies": { @@ -1088,6 +1179,7 @@ }, "node_modules/@jest/expect-utils": { "version": "28.1.3", + "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-28.1.3.tgz", "integrity": "sha512-wvbi9LUrHJLn3NlDW6wF2hvIMtd4JUl2QNVrjq+IBSHirgfrR3o9RnVtxzdEGO2n9JyIWwHnLfby5KzqBGg2YA==", "dev": true, "dependencies": { @@ -1099,6 +1191,7 @@ }, "node_modules/@jest/schemas": { "version": "28.1.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-28.1.3.tgz", "integrity": "sha512-/l/VWsdt/aBXgjshLWOFyFt3IVdYypu5y2Wn2rOO1un6nkqIn8SLXzgIMYXFyYsRWDyF5EthmKJMIdJvk08grg==", "dev": true, "dependencies": { @@ -1110,6 +1203,7 @@ }, "node_modules/@jest/test-result": { "version": "28.1.3", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-28.1.3.tgz", "integrity": "sha512-kZAkxnSE+FqE8YjW8gNuoVkkC9I7S1qmenl8sGcDOLropASP+BkcGKwhXoyqQuGOGeYY0y/ixjrd/iERpEXHNg==", "dev": true, "dependencies": { @@ -1124,6 +1218,7 @@ }, "node_modules/@jest/transform": { "version": "28.1.3", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-28.1.3.tgz", "integrity": "sha512-u5dT5di+oFI6hfcLOHGTAfmUxFRrjK+vnaP0kkVow9Md/M7V/MxqQMOz/VV25UZO8pzeA9PjfTpOu6BDuwSPQA==", "dev": true, "dependencies": { @@ -1147,8 +1242,19 @@ "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" } }, + "node_modules/@jest/transform/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.17", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz", + "integrity": "sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g==", + "dev": true, + "dependencies": { + "@jridgewell/resolve-uri": "3.1.0", + "@jridgewell/sourcemap-codec": "1.4.14" + } + }, "node_modules/@jest/types": { "version": "28.1.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-28.1.3.tgz", "integrity": "sha512-RyjiyMUZrKz/c+zlMFO1pm70DcIlST8AeWTkoUdZevew44wcNZQHsEVOiCVtgVnlFFD82FPaXycys58cf2muVQ==", "dev": true, "dependencies": { @@ -1165,6 +1271,7 @@ }, "node_modules/@jridgewell/gen-mapping": { "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz", "integrity": "sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==", "dev": true, "dependencies": { @@ -1177,6 +1284,7 @@ }, "node_modules/@jridgewell/resolve-uri": { "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", "dev": true, "engines": { @@ -1185,6 +1293,7 @@ }, "node_modules/@jridgewell/set-array": { "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", "dev": true, "engines": { @@ -1193,25 +1302,29 @@ }, "node_modules/@jridgewell/sourcemap-codec": { "version": "1.4.14", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", "dev": true }, "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.17", - "integrity": "sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g==", + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", "dev": true, "dependencies": { - "@jridgewell/resolve-uri": "3.1.0", - "@jridgewell/sourcemap-codec": "1.4.14" + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" } }, "node_modules/@jsdevtools/ono": { "version": "7.1.3", + "resolved": "https://registry.npmjs.org/@jsdevtools/ono/-/ono-7.1.3.tgz", "integrity": "sha512-4JQNk+3mVzK3xh2rqd6RB4J46qUR19azEHBneZyTZM+c456qOrbbM/5xcR8huNCCcbVt7+UmizG6GuUvPvKUYg==", "dev": true }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", "dev": true, "dependencies": { @@ -1224,6 +1337,7 @@ }, "node_modules/@nodelib/fs.stat": { "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", "dev": true, "engines": { @@ -1232,6 +1346,7 @@ }, "node_modules/@nodelib/fs.walk": { "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", "dev": true, "dependencies": { @@ -1244,6 +1359,7 @@ }, "node_modules/@npmcli/fs": { "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-2.1.2.tgz", "integrity": "sha512-yOJKRvohFOaLqipNtwYB9WugyZKhC/DZC4VYPmpaCzDBrA8YpK3qHZ8/HGscMnE4GqbkLNuVcCnxkeQEdGt6LQ==", "dev": true, "dependencies": { @@ -1256,6 +1372,7 @@ }, "node_modules/@npmcli/git": { "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@npmcli/git/-/git-3.0.2.tgz", "integrity": "sha512-CAcd08y3DWBJqJDpfuVL0uijlq5oaXaOJEKHKc4wqrjd00gkvTZB+nFuLn+doOOKddaQS9JfqtNoFCO2LCvA3w==", "dev": true, "dependencies": { @@ -1274,8 +1391,9 @@ } }, "node_modules/@npmcli/git/node_modules/lru-cache": { - "version": "7.14.1", - "integrity": "sha512-ysxwsnTKdAx96aTRdhDOCQfDgbHnt8SK0KY8SEjO0wHinhWOFTESbjVCMPbU1uGXg/ch4lifqx0wfjOawU2+WA==", + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", + "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", "dev": true, "engines": { "node": ">=12" @@ -1283,6 +1401,7 @@ }, "node_modules/@npmcli/git/node_modules/mkdirp": { "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", "dev": true, "bin": { @@ -1294,6 +1413,7 @@ }, "node_modules/@npmcli/installed-package-contents": { "version": "1.0.7", + "resolved": "https://registry.npmjs.org/@npmcli/installed-package-contents/-/installed-package-contents-1.0.7.tgz", "integrity": "sha512-9rufe0wnJusCQoLpV9ZPKIVP55itrM5BxOXs10DmdbRfgWtHy1LDyskbwRnBghuB0PrF7pNPOqREVtpz4HqzKw==", "dev": true, "dependencies": { @@ -1307,8 +1427,15 @@ "node": ">= 10" } }, + "node_modules/@npmcli/installed-package-contents/node_modules/npm-normalize-package-bin": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-1.0.1.tgz", + "integrity": "sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA==", + "dev": true + }, "node_modules/@npmcli/move-file": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-2.0.1.tgz", "integrity": "sha512-mJd2Z5TjYWq/ttPLLGqArdtnC74J6bOzg4rMDnN+p1xTacZ2yPRCk2y0oSWQtygLR9YVQXgOcONrwtnk3JupxQ==", "deprecated": "This functionality has been moved to @npmcli/fs", "dev": true, @@ -1322,6 +1449,7 @@ }, "node_modules/@npmcli/move-file/node_modules/mkdirp": { "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", "dev": true, "bin": { @@ -1333,6 +1461,7 @@ }, "node_modules/@npmcli/node-gyp": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@npmcli/node-gyp/-/node-gyp-2.0.0.tgz", "integrity": "sha512-doNI35wIe3bBaEgrlPfdJPaCpUR89pJWep4Hq3aRdh6gKazIVWfs0jHttvSSoq47ZXgC7h73kDsUl8AoIQUB+A==", "dev": true, "engines": { @@ -1341,6 +1470,7 @@ }, "node_modules/@npmcli/promise-spawn": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@npmcli/promise-spawn/-/promise-spawn-3.0.0.tgz", "integrity": "sha512-s9SgS+p3a9Eohe68cSI3fi+hpcZUmXq5P7w0kMlAsWVtR7XbK3ptkZqKT2cK1zLDObJ3sR+8P59sJE0w/KTL1g==", "dev": true, "dependencies": { @@ -1352,6 +1482,7 @@ }, "node_modules/@npmcli/run-script": { "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@npmcli/run-script/-/run-script-4.2.1.tgz", "integrity": "sha512-7dqywvVudPSrRCW5nTHpHgeWnbBtz8cFkOuKrecm6ih+oO9ciydhWt6OF7HlqupRRmB8Q/gECVdB9LMfToJbRg==", "dev": true, "dependencies": { @@ -1367,6 +1498,7 @@ }, "node_modules/@samverschueren/stream-to-observable": { "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@samverschueren/stream-to-observable/-/stream-to-observable-0.3.1.tgz", "integrity": "sha512-c/qwwcHyafOQuVQJj0IlBjf5yYgBI7YPJ77k4fOJYesb41jio65eaJODRUmfYKhTOFBrIZ66kgvGPlNbjuoRdQ==", "dependencies": { "any-observable": "^0.3.0" @@ -1385,11 +1517,13 @@ }, "node_modules/@sinclair/typebox": { "version": "0.24.51", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.24.51.tgz", "integrity": "sha512-1P1OROm/rdubP5aFDSZQILU0vrLCJ4fvHt6EoqHEM+2D/G5MK3bIaymUKLit8Js9gbns5UyJnkP/TZROLw4tUA==", "dev": true }, "node_modules/@sindresorhus/is": { "version": "0.14.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz", "integrity": "sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ==", "dev": true, "engines": { @@ -1398,6 +1532,7 @@ }, "node_modules/@sinonjs/commons": { "version": "1.8.6", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.6.tgz", "integrity": "sha512-Ky+XkAkqPZSm3NLBeUng77EBQl3cmeJhITaGHdYH8kjVB+aun3S4XBRti2zt17mtt0mIUDiNxYeoJm6drVvBJQ==", "dev": true, "dependencies": { @@ -1406,6 +1541,7 @@ }, "node_modules/@sinonjs/fake-timers": { "version": "9.1.2", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-9.1.2.tgz", "integrity": "sha512-BPS4ynJW/o92PUR4wgriz2Ud5gpST5vz6GQfMixEDK0Z8ZCUv2M7SkBLykH56T++Xs+8ln9zTGbOvNGIe02/jw==", "dev": true, "dependencies": { @@ -1414,6 +1550,7 @@ }, "node_modules/@sinonjs/samsam": { "version": "6.1.3", + "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-6.1.3.tgz", "integrity": "sha512-nhOb2dWPeb1sd3IQXL/dVPnKHDOAFfvichtBf4xV00/rU1QbPCQqKMbvIheIjqwVjh7qIgf2AHTHi391yMOMpQ==", "dev": true, "dependencies": { @@ -1424,16 +1561,18 @@ }, "node_modules/@sinonjs/text-encoding": { "version": "0.7.2", + "resolved": "https://registry.npmjs.org/@sinonjs/text-encoding/-/text-encoding-0.7.2.tgz", "integrity": "sha512-sXXKG+uL9IrKqViTtao2Ws6dy0znu9sOaP1di/jKGW1M6VssO8vlpXCQcpZ+jisQ1tTFAC5Jo/EOzFbggBagFQ==", "dev": true }, "node_modules/@stoplight/http-spec": { - "version": "5.5.2", - "integrity": "sha512-WW2CeTxIuvbT59lm+n47iyxLHO/Uj73Mnta2uW39WdE3uUkJIEqovFJPflsIrJCXUcNIIwLuB+I6ZMTuTGK2Uw==", + "version": "5.6.2", + "resolved": "https://registry.npmjs.org/@stoplight/http-spec/-/http-spec-5.6.2.tgz", + "integrity": "sha512-r071B/7u2qbJhHoJF0vnlZ4oghDvuW8OKuSrubSRP9pAoqiOD89HUNNUhlB1j6aO27lAHoz/qwxSUM7KS54HMw==", "dev": true, "dependencies": { "@stoplight/json": "^3.18.1", - "@stoplight/json-schema-generator": "1.0.1", + "@stoplight/json-schema-generator": "1.0.2", "@stoplight/types": "^13.6.0", "@types/json-schema": "7.0.11", "@types/swagger-schema-official": "~2.0.22", @@ -1452,8 +1591,9 @@ } }, "node_modules/@stoplight/json": { - "version": "3.20.1", - "integrity": "sha512-FXfud+uWgIj1xv6nUO9WnmgmnVikaxJcbtR4XQt4C42n5c2qua3U05Z/3B57hP5TJRSj+tpn9ID6/bFeyYYlEg==", + "version": "3.20.2", + "resolved": "https://registry.npmjs.org/@stoplight/json/-/json-3.20.2.tgz", + "integrity": "sha512-e3Eb/DdLSpJVAsxAG1jKSnl4TVZLl2pH8KsJBWKf5GPCeI58Eo0ZpRTX3HcZ0gBaHWH6CnEHJkCRCONhoFbDIA==", "dev": true, "dependencies": { "@stoplight/ordered-object-literal": "^1.0.3", @@ -1468,15 +1608,16 @@ } }, "node_modules/@stoplight/json-schema-generator": { - "version": "1.0.1", - "integrity": "sha512-b9WT8Z5M7Nc/O6+JVEMvOdkLR1fePbCHnPlOpnRFxp+pkfM+VRwLaD4toWRpnpBlHXphRfDxFj5/zxcVvqeKDA==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@stoplight/json-schema-generator/-/json-schema-generator-1.0.2.tgz", + "integrity": "sha512-FzSLFoIZc6Lmw3oRE7kU6YUrl5gBmUs//rY59jdFipBoSyTPv5NyqeyTg5mvT6rY1F3qTLU3xgzRi/9Pb9eZpA==", "dev": true, "dependencies": { + "cross-fetch": "^3.1.5", "json-promise": "1.1.x", "minimist": "1.2.6", "mkdirp": "0.5.x", - "pretty-data": "0.40.x", - "request": "2.x.x" + "pretty-data": "0.40.x" }, "bin": { "json-schema-generator": "bin/cli.js" @@ -1484,6 +1625,7 @@ }, "node_modules/@stoplight/json-schema-merge-allof": { "version": "0.7.8", + "resolved": "https://registry.npmjs.org/@stoplight/json-schema-merge-allof/-/json-schema-merge-allof-0.7.8.tgz", "integrity": "sha512-JTDt6GYpCWQSb7+UW1P91IAp/pcLWis0mmEzWVFcLsrNgtUYK7JLtYYz0ZPSR4QVL0fJ0YQejM+MPq5iNDFO4g==", "dev": true, "dependencies": { @@ -1494,6 +1636,7 @@ }, "node_modules/@stoplight/json-schema-ref-parser": { "version": "9.2.1", + "resolved": "https://registry.npmjs.org/@stoplight/json-schema-ref-parser/-/json-schema-ref-parser-9.2.1.tgz", "integrity": "sha512-iKWeomA0HHDcbG0G8yVzQFs9y5vtF/GtjEDSuhofdHcPxXMhnTUh8d9NdbhXPCVhwIRmdvzP3jMv2A3747hyWg==", "dev": true, "dependencies": { @@ -1508,6 +1651,7 @@ }, "node_modules/@stoplight/json-schema-sampler": { "version": "0.2.2", + "resolved": "https://registry.npmjs.org/@stoplight/json-schema-sampler/-/json-schema-sampler-0.2.2.tgz", "integrity": "sha512-QP4ZwXh3dEn5wHZs2361kdf4BmaKiiP+pxIImAuVTLmulv9sBTB+ETG7Y5z9u4DOUQu2GNxfUY10iSwuBQMXrg==", "dev": true, "dependencies": { @@ -1517,6 +1661,7 @@ }, "node_modules/@stoplight/ordered-object-literal": { "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@stoplight/ordered-object-literal/-/ordered-object-literal-1.0.4.tgz", "integrity": "sha512-OF8uib1jjDs5/cCU+iOVy+GJjU3X7vk/qJIkIJFqwmlJKrrtijFmqwbu8XToXrwTYLQTP+Hebws5gtZEmk9jag==", "dev": true, "engines": { @@ -1525,6 +1670,7 @@ }, "node_modules/@stoplight/path": { "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@stoplight/path/-/path-1.3.2.tgz", "integrity": "sha512-lyIc6JUlUA8Ve5ELywPC8I2Sdnh1zc1zmbYgVarhXIp9YeAB0ReeqmGEOWNtlHkbP2DAA1AL65Wfn2ncjK/jtQ==", "dev": true, "engines": { @@ -1533,6 +1679,7 @@ }, "node_modules/@stoplight/prism-cli": { "version": "4.10.5", + "resolved": "https://registry.npmjs.org/@stoplight/prism-cli/-/prism-cli-4.10.5.tgz", "integrity": "sha512-1DB3fNM+Lj7oSgfFQK+Zc8TY1lK4S5I9KB5hhJbTjqXFXhYNWucmDxcTyQWiNTp/FBOxGtuMpg+z0sr27Z/vkw==", "dev": true, "dependencies": { @@ -1566,6 +1713,7 @@ }, "node_modules/@stoplight/prism-cli/node_modules/chalk": { "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, "dependencies": { @@ -1581,6 +1729,7 @@ }, "node_modules/@stoplight/prism-cli/node_modules/cliui": { "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", "dev": true, "dependencies": { @@ -1591,6 +1740,7 @@ }, "node_modules/@stoplight/prism-cli/node_modules/yargs": { "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", "dev": true, "dependencies": { @@ -1607,8 +1757,9 @@ } }, "node_modules/@stoplight/prism-core": { - "version": "4.10.5", - "integrity": "sha512-HF6ScLTvW1J8scylJKoYh3k7vXGKTjOw3l8w7XpOoCM0VUDGG3w+9GBzTMmLCLpvvC+m1gaaTk1j58m8p2P11A==", + "version": "4.11.1", + "resolved": "https://registry.npmjs.org/@stoplight/prism-core/-/prism-core-4.11.1.tgz", + "integrity": "sha512-iqWQk0g9qLsNNBnWXOuQ4CxRHYRiPGRxE3cR2As3SpxGjJWsX1BSEwsld2wjSGRpLG7V6VsKt4dWTkaC9aJicA==", "dev": true, "dependencies": { "fp-ts": "^2.11.5", @@ -1621,15 +1772,16 @@ } }, "node_modules/@stoplight/prism-http": { - "version": "4.10.5", - "integrity": "sha512-jlA0oF4n1cUf9kfmGf3mWcXbbeyHRFqYObeIbfgPmc4WcmQLEKOw4pDOo1xpmO516PLHEeqtyd4EtRGtn/JZHg==", + "version": "4.11.1", + "resolved": "https://registry.npmjs.org/@stoplight/prism-http/-/prism-http-4.11.1.tgz", + "integrity": "sha512-IwPzPGQX/bF7u+mMtWyALI9ulucCTBQCma7hvWLrg4YMOij8ieB+6KR+PqQ5p/0kBnj/g9JhPBAouL1L10LUSQ==", "dev": true, "dependencies": { "@faker-js/faker": "^6.0.0", "@stoplight/json": "^3.18.1", "@stoplight/json-schema-merge-allof": "0.7.8", "@stoplight/json-schema-sampler": "0.2.2", - "@stoplight/prism-core": "^4.10.5", + "@stoplight/prism-core": "^4.11.1", "@stoplight/types": "^13.0.0", "@stoplight/yaml": "^4.2.3", "abstract-logging": "^2.0.1", @@ -1654,12 +1806,13 @@ } }, "node_modules/@stoplight/prism-http-server": { - "version": "4.10.5", - "integrity": "sha512-rUFYVxnL/8+PVuwP9Bca5K+sv4QorpHcSyO6lj2/e8lwaWxMcUjXBZwxo8Qc7sr4baO+thM5yhlMmN7zc5mtYA==", + "version": "4.11.1", + "resolved": "https://registry.npmjs.org/@stoplight/prism-http-server/-/prism-http-server-4.11.1.tgz", + "integrity": "sha512-IjWkEB/kPwEy/uBsKHu4uihcK9l4cARE44WYgZ/CMXAdwqHeK5ZT/W0wIAKGxguWQOTuAOye05CzkNTKK0Eokg==", "dev": true, "dependencies": { - "@stoplight/prism-core": "^4.10.5", - "@stoplight/prism-http": "^4.10.5", + "@stoplight/prism-core": "^4.11.1", + "@stoplight/prism-http": "^4.11.1", "@stoplight/types": "^13.0.0", "fast-xml-parser": "^3.20.3", "fp-ts": "^2.11.5", @@ -1676,8 +1829,9 @@ } }, "node_modules/@stoplight/types": { - "version": "13.8.0", - "integrity": "sha512-5glKswz7y9aACh+a+JegID+4xX//4TsIdv7iPl29hWnOoWrnlPbg3Gjc4nYUXXgMSaSlSsA15JU/0+rE89fR4A==", + "version": "13.10.0", + "resolved": "https://registry.npmjs.org/@stoplight/types/-/types-13.10.0.tgz", + "integrity": "sha512-clCXabaqDZQxtTnmeH2ZHdUeZsQtQkebLo+tPywqr8tgcrNbkKUBiBQRFW/CfU3DGN3OM+jCquN0O6u/4a0qbQ==", "dev": true, "dependencies": { "@types/json-schema": "^7.0.4", @@ -1689,6 +1843,7 @@ }, "node_modules/@stoplight/yaml": { "version": "4.2.3", + "resolved": "https://registry.npmjs.org/@stoplight/yaml/-/yaml-4.2.3.tgz", "integrity": "sha512-Mx01wjRAR9C7yLMUyYFTfbUf5DimEpHMkRDQ1PKLe9dfNILbgdxyrncsOXM3vCpsQ1Hfj4bPiGl+u4u6e9Akqw==", "dev": true, "dependencies": { @@ -1703,11 +1858,13 @@ }, "node_modules/@stoplight/yaml-ast-parser": { "version": "0.0.48", + "resolved": "https://registry.npmjs.org/@stoplight/yaml-ast-parser/-/yaml-ast-parser-0.0.48.tgz", "integrity": "sha512-sV+51I7WYnLJnKPn2EMWgS4EUfoP4iWEbrWwbXsj0MZCB/xOK8j6+C9fntIdOM50kpx45ZLC3s6kwKivWuqvyg==", "dev": true }, "node_modules/@szmarczak/http-timer": { "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-1.1.2.tgz", "integrity": "sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA==", "dev": true, "dependencies": { @@ -1719,6 +1876,7 @@ }, "node_modules/@tootallnate/once": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", "dev": true, "engines": { @@ -1727,26 +1885,31 @@ }, "node_modules/@tsconfig/node10": { "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz", "integrity": "sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==", "dev": true }, "node_modules/@tsconfig/node12": { "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", "dev": true }, "node_modules/@tsconfig/node14": { "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", "dev": true }, "node_modules/@tsconfig/node16": { "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.3.tgz", "integrity": "sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ==", "dev": true }, "node_modules/@types/babel__traverse": { "version": "7.18.3", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.18.3.tgz", "integrity": "sha512-1kbcJ40lLB7MHsj39U4Sh1uTd2E7rLEa79kmDpI6cy+XiXsteB3POdQomoq4FxszMrO3ZYchkhYJw7A2862b3w==", "dev": true, "dependencies": { @@ -1755,11 +1918,13 @@ }, "node_modules/@types/chai": { "version": "4.3.4", + "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.3.4.tgz", "integrity": "sha512-KnRanxnpfpjUTqTCXslZSEdLfXExwgNxYPdiO2WGUj8+HDjFi8R3k5RVKPeSCzLjCcshCAtVO2QBbVuAV4kTnw==", "dev": true }, "node_modules/@types/chai-as-promised": { "version": "7.1.5", + "resolved": "https://registry.npmjs.org/@types/chai-as-promised/-/chai-as-promised-7.1.5.tgz", "integrity": "sha512-jStwss93SITGBwt/niYrkf2C+/1KTeZCZl1LaeezTlqppAKeoQC7jxyqYuP72sxBGKCIbw7oHgbYssIRzT5FCQ==", "dev": true, "dependencies": { @@ -1768,6 +1933,7 @@ }, "node_modules/@types/chai-json-schema": { "version": "1.4.6", + "resolved": "https://registry.npmjs.org/@types/chai-json-schema/-/chai-json-schema-1.4.6.tgz", "integrity": "sha512-Z+zM4XwNkno4nWkKkbeLvf6IZTnA7ffGpX0QAcql0wQdKniGc849Leblx4ojRsv7IjS4Ct16MGr1SLNrJQZsRg==", "dev": true, "dependencies": { @@ -1776,6 +1942,7 @@ }, "node_modules/@types/chai-uuid": { "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@types/chai-uuid/-/chai-uuid-1.0.2.tgz", "integrity": "sha512-bT/Y19gztsbE5ZvKBCMHf6Ziiw3e3l2v962ycLIksjJEd85YSW+L3jrj6wO4yA53d6CRKifZ09QDa73OA2VUDw==", "dev": true, "dependencies": { @@ -1785,6 +1952,7 @@ }, "node_modules/@types/fs-extra": { "version": "9.0.13", + "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-9.0.13.tgz", "integrity": "sha512-nEnwB++1u5lVDM2UI4c1+5R+FYaKfaAzS4OococimjVm3nQw3TuzH5UNsocrcTBbhnerblyHj4A49qXbIiZdpA==", "dependencies": { "@types/node": "*" @@ -1792,6 +1960,7 @@ }, "node_modules/@types/graceful-fs": { "version": "4.1.6", + "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.6.tgz", "integrity": "sha512-Sig0SNORX9fdW+bQuTEovKj3uHcUL6LQKbCrrqb1X7J6/ReAbhCXRAhc+SMejhLELFj2QcyuxmUooZ4bt5ReSw==", "dev": true, "dependencies": { @@ -1800,6 +1969,7 @@ }, "node_modules/@types/inquirer": { "version": "8.2.5", + "resolved": "https://registry.npmjs.org/@types/inquirer/-/inquirer-8.2.5.tgz", "integrity": "sha512-QXlzybid60YtAwfgG3cpykptRYUx2KomzNutMlWsQC64J/WG/gQSl+P4w7A21sGN0VIxRVava4rgnT7FQmFCdg==", "dev": true, "dependencies": { @@ -1808,11 +1978,13 @@ }, "node_modules/@types/istanbul-lib-coverage": { "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz", "integrity": "sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g==", "dev": true }, "node_modules/@types/istanbul-lib-report": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", "integrity": "sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg==", "dev": true, "dependencies": { @@ -1821,6 +1993,7 @@ }, "node_modules/@types/istanbul-reports": { "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz", "integrity": "sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw==", "dev": true, "dependencies": { @@ -1829,11 +2002,13 @@ }, "node_modules/@types/json-schema": { "version": "7.0.11", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz", "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==", "dev": true }, "node_modules/@types/jsonfile": { "version": "6.1.1", + "resolved": "https://registry.npmjs.org/@types/jsonfile/-/jsonfile-6.1.1.tgz", "integrity": "sha512-GSgiRCVeapDN+3pqA35IkQwasaCh/0YFH5dEF6S88iDvEn901DjOeH3/QPY+XYP1DFzDZPvIvfeEgk+7br5png==", "dev": true, "dependencies": { @@ -1870,45 +2045,54 @@ }, "node_modules/@types/minimist": { "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.2.tgz", "integrity": "sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ==", "dev": true }, "node_modules/@types/mocha": { "version": "9.1.1", + "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-9.1.1.tgz", "integrity": "sha512-Z61JK7DKDtdKTWwLeElSEBcWGRLY8g95ic5FoQqI9CMx0ns/Ghep3B4DfcEimiKMvtamNVULVNKEsiwV3aQmXw==", "dev": true }, "node_modules/@types/node": { "version": "18.11.18", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.18.tgz", "integrity": "sha512-DHQpWGjyQKSHj3ebjFI/wRKcqQcdR+MoFBygntYOZytCqNfkd2ZC4ARDJ2DQqhjH5p85Nnd3jhUJIXrszFX/JA==" }, "node_modules/@types/normalize-package-data": { "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.1.tgz", "integrity": "sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==", "dev": true }, "node_modules/@types/parse-json": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz", "integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==", "dev": true }, "node_modules/@types/portscanner": { "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@types/portscanner/-/portscanner-2.1.1.tgz", "integrity": "sha512-1NsVIbgBKvrqxwtMN0V6CLji1ERwKSI/RWz0J3y++CzSwYNGBStCfpIFgxV3ZwxsDR5PoZqoUWhwraDm+Ztn0Q==", "dev": true }, "node_modules/@types/prettier": { "version": "2.7.2", + "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.7.2.tgz", "integrity": "sha512-KufADq8uQqo1pYKVIYzfKbJfBAc0sOeXqGbFaSpv8MRmC/zXgowNZmFcbngndGk922QDmOASEXUZCaY48gs4cg==", "dev": true }, "node_modules/@types/proxyquire": { "version": "1.3.28", + "resolved": "https://registry.npmjs.org/@types/proxyquire/-/proxyquire-1.3.28.tgz", "integrity": "sha512-SQaNzWQ2YZSr7FqAyPPiA3FYpux2Lqh3HWMZQk47x3xbMCqgC/w0dY3dw9rGqlweDDkrySQBcaScXWeR+Yb11Q==", "dev": true }, "node_modules/@types/ramda": { "version": "0.28.22", + "resolved": "https://registry.npmjs.org/@types/ramda/-/ramda-0.28.22.tgz", "integrity": "sha512-DoIfh0sBxrL/aqADk+SGrfjJT9cB8modg+4NRlF7/Tfg4N2+KBEkAgpYYzrjiZxxR5YzWizjfVrTEdVDwYK7xQ==", "dev": true, "dependencies": { @@ -1917,11 +2101,13 @@ }, "node_modules/@types/semver": { "version": "7.3.13", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.3.13.tgz", "integrity": "sha512-21cFJr9z3g5dW8B0CVI9g2O9beqaThGQ6ZFBqHfwhzLDKUxaqTIy3vnfah/UPkfOiF2pLq+tGz+W8RyCskuslw==", "dev": true }, "node_modules/@types/sinon": { "version": "10.0.13", + "resolved": "https://registry.npmjs.org/@types/sinon/-/sinon-10.0.13.tgz", "integrity": "sha512-UVjDqJblVNQYvVNUsj0PuYYw0ELRmgt1Nt5Vk0pT5f16ROGfcKJY8o1HVuMOJOpD727RrGB9EGvoaTQE5tgxZQ==", "dev": true, "dependencies": { @@ -1930,6 +2116,7 @@ }, "node_modules/@types/sinon-chai": { "version": "3.2.9", + "resolved": "https://registry.npmjs.org/@types/sinon-chai/-/sinon-chai-3.2.9.tgz", "integrity": "sha512-/19t63pFYU0ikrdbXKBWj9PCdnKyTd0Qkz0X91Ta081cYsq90OxYdcWwK/dwEoDa6dtXgj2HJfmzgq+QZTHdmQ==", "dev": true, "dependencies": { @@ -1939,21 +2126,25 @@ }, "node_modules/@types/sinonjs__fake-timers": { "version": "8.1.2", + "resolved": "https://registry.npmjs.org/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-8.1.2.tgz", "integrity": "sha512-9GcLXF0/v3t80caGs5p2rRfkB+a8VBGLJZVih6CNFkx8IZ994wiKKLSRs9nuFwk1HevWs/1mnUmkApGrSGsShA==", "dev": true }, "node_modules/@types/stack-utils": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz", "integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==", "dev": true }, "node_modules/@types/swagger-schema-official": { "version": "2.0.22", + "resolved": "https://registry.npmjs.org/@types/swagger-schema-official/-/swagger-schema-official-2.0.22.tgz", "integrity": "sha512-7yQiX6MWSFSvc/1wW5smJMZTZ4fHOd+hqLr3qr/HONDxHEa2bnYAsOcGBOEqFIjd4yetwMOdEDdeW+udRAQnHA==", "dev": true }, "node_modules/@types/through": { "version": "0.0.30", + "resolved": "https://registry.npmjs.org/@types/through/-/through-0.0.30.tgz", "integrity": "sha512-FvnCJljyxhPM3gkRgWmxmDZyAQSiBQQWLI0A0VFL0K7W1oRUrPJSqNO0NvTnLkBcotdlp3lKvaT0JrnyRDkzOg==", "dev": true, "dependencies": { @@ -1962,11 +2153,13 @@ }, "node_modules/@types/tv4": { "version": "1.2.31", + "resolved": "https://registry.npmjs.org/@types/tv4/-/tv4-1.2.31.tgz", "integrity": "sha512-P97XU07fcpauSw3/fE2Q7eF6bHl4oHhwkikjnM7zlQLENrdC2rZuHSdNlMBhnW82NyBEsVJHII1Jk3d/MtQsQQ==", "dev": true }, "node_modules/@types/type-is": { "version": "1.6.3", + "resolved": "https://registry.npmjs.org/@types/type-is/-/type-is-1.6.3.tgz", "integrity": "sha512-PNs5wHaNcBgCQG5nAeeZ7OvosrEsI9O4W2jAOO9BCCg4ux9ZZvH2+0iSCOIDBiKuQsiNS8CBlmfX9f5YBQ22cA==", "dev": true, "dependencies": { @@ -1975,17 +2168,20 @@ }, "node_modules/@types/uuid": { "version": "8.3.4", + "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-8.3.4.tgz", "integrity": "sha512-c/I8ZRb51j+pYGAu5CrFMRxqZ2ke4y2grEBO5AUjgSkSk+qT2Ea+OdWElz/OiMf5MNpn2b17kuVBwZLQJXzihw==", "dev": true }, "node_modules/@types/vscode": { "version": "1.74.0", + "resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.74.0.tgz", "integrity": "sha512-LyeCIU3jb9d38w0MXFwta9r0Jx23ugujkAxdwLTNCyspdZTKUc43t7ppPbCiPoQ/Ivd/pnDFZrb4hWd45wrsgA==", "dev": true }, "node_modules/@types/yargs": { - "version": "17.0.20", - "integrity": "sha512-eknWrTHofQuPk2iuqDm1waA7V6xPlbgBoaaXEgYkClhLOnB0TtbW+srJaOToAgawPxPlHQzwypFA2bhZaUGP5A==", + "version": "17.0.24", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.24.tgz", + "integrity": "sha512-6i0aC7jV6QzQB8ne1joVZ0eSFIstHsCrobmOtghM11yGlH0j43FKL2UhWdELkyps0zuf7qVTUVCCR+tgSlyLLw==", "dev": true, "dependencies": { "@types/yargs-parser": "*" @@ -1993,16 +2189,19 @@ }, "node_modules/@types/yargs-parser": { "version": "21.0.0", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.0.tgz", "integrity": "sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==", "dev": true }, "node_modules/@ungap/promise-all-settled": { "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz", "integrity": "sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q==", "dev": true }, "node_modules/@vscode/test-electron": { "version": "1.6.2", + "resolved": "https://registry.npmjs.org/@vscode/test-electron/-/test-electron-1.6.2.tgz", "integrity": "sha512-W01ajJEMx6223Y7J5yaajGjVs1QfW3YGkkOJHVKfAMEqNB1ZHN9wCcViehv5ZwVSSJnjhu6lYEYgwBdHtCxqhQ==", "dev": true, "dependencies": { @@ -2017,6 +2216,7 @@ }, "node_modules/@vscode/test-electron/node_modules/@tootallnate/once": { "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", "dev": true, "engines": { @@ -2025,6 +2225,7 @@ }, "node_modules/@vscode/test-electron/node_modules/http-proxy-agent": { "version": "4.0.1", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", "dev": true, "dependencies": { @@ -2038,10 +2239,12 @@ }, "node_modules/abbrev": { "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" }, "node_modules/abort-controller": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", "dev": true, "dependencies": { @@ -2053,11 +2256,13 @@ }, "node_modules/abstract-logging": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/abstract-logging/-/abstract-logging-2.0.1.tgz", "integrity": "sha512-2BjRTZxTPvheOvGbBslFSYOUkr+SjPtOnrLP33f+VIWLzezQpZcqVg7ja3L4dBXmzzgwT+a029jRx5PCi3JuiA==", "dev": true }, "node_modules/accepts": { "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", "dev": true, "dependencies": { @@ -2070,6 +2275,7 @@ }, "node_modules/acorn": { "version": "8.8.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz", "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==", "dev": true, "bin": { @@ -2081,6 +2287,7 @@ }, "node_modules/acorn-walk": { "version": "8.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", "dev": true, "engines": { @@ -2089,11 +2296,13 @@ }, "node_modules/add-stream": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/add-stream/-/add-stream-1.0.0.tgz", "integrity": "sha512-qQLMr+8o0WC4FZGQTcJiKBVC59JylcPSrTtk6usvmIDFUOCKegapy1VHQwRbFMOFyb/inzUVqHs+eMYKDM1YeQ==", "dev": true }, "node_modules/adm-zip": { "version": "0.5.10", + "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.5.10.tgz", "integrity": "sha512-x0HvcHqVJNTPk/Bw8JbLWlWoo6Wwnsug0fnYYro1HBrjxZ3G7/AZk7Ahv8JwDe1uIcz8eBqvu86FuF1POiG7vQ==", "engines": { "node": ">=6.0" @@ -2101,6 +2310,7 @@ }, "node_modules/agent-base": { "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", "dev": true, "dependencies": { @@ -2111,12 +2321,13 @@ } }, "node_modules/agentkeepalive": { - "version": "4.2.1", - "integrity": "sha512-Zn4cw2NEqd+9fiSVWMscnjyQ1a8Yfoc5oBajLeo5w+YBHgDUcEBY2hS4YpTz6iN5f/2zQiktcuM6tS8x1p9dpA==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.3.0.tgz", + "integrity": "sha512-7Epl1Blf4Sy37j4v9f9FjICCh4+KAQOyXgHEwlyBiAQLbhKdq/i2QQU3amQalS/wPhdPzDXPL5DMR5bkn+YeWg==", "dev": true, "dependencies": { "debug": "^4.1.0", - "depd": "^1.1.2", + "depd": "^2.0.0", "humanize-ms": "^1.2.1" }, "engines": { @@ -2125,6 +2336,7 @@ }, "node_modules/aggregate-error": { "version": "3.1.0", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", "dependencies": { "clean-stack": "^2.0.0", @@ -2134,15 +2346,9 @@ "node": ">=8" } }, - "node_modules/aggregate-error/node_modules/indent-string": { - "version": "4.0.0", - "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", - "engines": { - "node": ">=8" - } - }, "node_modules/ajv": { "version": "8.12.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", "dependencies": { "fast-deep-equal": "^3.1.1", @@ -2157,6 +2363,7 @@ }, "node_modules/ajv-formats": { "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", "dependencies": { "ajv": "^8.0.0" @@ -2172,6 +2379,7 @@ }, "node_modules/ansi-align": { "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz", "integrity": "sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==", "dev": true, "dependencies": { @@ -2180,6 +2388,7 @@ }, "node_modules/ansi-colors": { "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", "dev": true, "engines": { @@ -2188,6 +2397,7 @@ }, "node_modules/ansi-escapes": { "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", "dependencies": { "type-fest": "^0.21.3" @@ -2201,6 +2411,7 @@ }, "node_modules/ansi-regex": { "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "engines": { "node": ">=8" @@ -2208,6 +2419,7 @@ }, "node_modules/ansi-styles": { "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dependencies": { "color-convert": "^2.0.1" @@ -2221,10 +2433,12 @@ }, "node_modules/antlr4ts": { "version": "0.5.0-alpha.4", + "resolved": "https://registry.npmjs.org/antlr4ts/-/antlr4ts-0.5.0-alpha.4.tgz", "integrity": "sha512-WPQDt1B74OfPv/IMS2ekXAKkTZIHl88uMetg6q3OTqgFxZ/dxDXI0EWLyZid/1Pe6hTftyg5N7gel5wNAGxXyQ==" }, "node_modules/any-observable": { "version": "0.3.0", + "resolved": "https://registry.npmjs.org/any-observable/-/any-observable-0.3.0.tgz", "integrity": "sha512-/FQM1EDkTsf63Ub2C6O7GuYFDsSXUwsaZDurV0np41ocwq0jthUAYCmhBX9f+KwlaCgIuWyr/4WlUQUBfKfZog==", "engines": { "node": ">=6" @@ -2232,6 +2446,7 @@ }, "node_modules/anymatch": { "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", "dependencies": { "normalize-path": "^3.0.0", @@ -2243,6 +2458,7 @@ }, "node_modules/append-transform": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/append-transform/-/append-transform-2.0.0.tgz", "integrity": "sha512-7yeyCEurROLQJFv5Xj4lEGTy0borxepjFv1g22oAdqFu//SrAlDl1O1Nxx15SH1RoliUml6p8dwJW9jvZughhg==", "dev": true, "dependencies": { @@ -2254,11 +2470,13 @@ }, "node_modules/aproba": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==", "dev": true }, "node_modules/archiver": { "version": "5.3.1", + "resolved": "https://registry.npmjs.org/archiver/-/archiver-5.3.1.tgz", "integrity": "sha512-8KyabkmbYrH+9ibcTScQ1xCJC/CGcugdVIwB+53f5sZziXgwUh3iXlAlANMxcZyDEfTHMe6+Z5FofV8nopXP7w==", "dependencies": { "archiver-utils": "^2.1.0", @@ -2275,6 +2493,7 @@ }, "node_modules/archiver-utils": { "version": "2.1.0", + "resolved": "https://registry.npmjs.org/archiver-utils/-/archiver-utils-2.1.0.tgz", "integrity": "sha512-bEL/yUb/fNNiNTuUz979Z0Yg5L+LzLxGJz8x79lYmR54fmTIb6ob/hNQgkQnIUDWIFjZVQwl9Xs356I6BAMHfw==", "dependencies": { "glob": "^7.1.4", @@ -2293,8 +2512,9 @@ } }, "node_modules/archiver-utils/node_modules/readable-stream": { - "version": "2.3.7", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", "dependencies": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", @@ -2307,26 +2527,23 @@ }, "node_modules/archiver-utils/node_modules/safe-buffer": { "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" }, - "node_modules/archiver-utils/node_modules/string_decoder": { - "version": "1.1.1", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, "node_modules/archiver/node_modules/async": { "version": "3.2.4", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz", "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==" }, "node_modules/archy": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", "integrity": "sha512-Xg+9RwCg/0p32teKdGMPTPnVXKD0w3DfHnFTficozsAgsvq2XenPJq/MYpzzQ/v8zrOyJn6Ds39VA4JIDwFfqw==", "dev": true }, "node_modules/are-we-there-yet": { "version": "3.0.1", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-3.0.1.tgz", "integrity": "sha512-QZW4EDmGwlYur0Yyf/b2uGucHQMa8aFUP7eu9ddR73vvhFyt4V0Vl3QHPcTNJ8l6qYOBdxgXdnBXQrHilfRQBg==", "dev": true, "dependencies": { @@ -2339,20 +2556,24 @@ }, "node_modules/arg": { "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", "dev": true }, "node_modules/argparse": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" }, "node_modules/array-ify": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-ify/-/array-ify-1.0.0.tgz", "integrity": "sha512-c5AMf34bKdvPhQ7tBGhqkgKNUzMr4WUs+WDtC2ZUGOUncbxKMTvqxYctiseW3+L4bA8ec+GcZ6/A/FW4m8ukng==", "dev": true }, "node_modules/array-union": { "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", "dev": true, "engines": { @@ -2361,6 +2582,7 @@ }, "node_modules/arrify": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", "integrity": "sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==", "dev": true, "engines": { @@ -2369,10 +2591,12 @@ }, "node_modules/ask-sdk-model-runtime": { "version": "1.4.0", + "resolved": "https://registry.npmjs.org/ask-sdk-model-runtime/-/ask-sdk-model-runtime-1.4.0.tgz", "integrity": "sha512-JSu9zGklm8jtaQMk344BTJqVSX/tenFNB7b+jgnoHDp4aRwmzCAlDnBiiNAVMXlbrBeIi+ms79yK1s2oq0PjFg==" }, "node_modules/ask-smapi-model": { "version": "1.19.12", + "resolved": "https://registry.npmjs.org/ask-smapi-model/-/ask-smapi-model-1.19.12.tgz", "integrity": "sha512-sQaf624rnP/avcIm2Rpt1FOI/ysJzeAHsWudu6JdJbVLl3jc8M8ItRIS9iICyfslkF7CspA+N+4HI8cNTfXcRg==", "dependencies": { "ask-sdk-model-runtime": "^1.1.0" @@ -2380,6 +2604,7 @@ }, "node_modules/ask-smapi-sdk": { "version": "1.3.0", + "resolved": "https://registry.npmjs.org/ask-smapi-sdk/-/ask-smapi-sdk-1.3.0.tgz", "integrity": "sha512-1mTYkHp9ZzB3l4C9ZVFMKmEw+Ynm0vgQcLunCl6yOc3cxWmiI8QkbjJAs93F28Bg6EPBOTo8UOUtyjFz9vu9LA==", "dependencies": { "ask-smapi-model": "^1.4.0" @@ -2387,6 +2612,7 @@ }, "node_modules/asn1": { "version": "0.2.6", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz", "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==", "dependencies": { "safer-buffer": "~2.1.0" @@ -2394,6 +2620,7 @@ }, "node_modules/assert-plus": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", "integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==", "engines": { "node": ">=0.8" @@ -2401,6 +2628,7 @@ }, "node_modules/assertion-error": { "version": "1.1.0", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", "dev": true, "engines": { @@ -2409,6 +2637,7 @@ }, "node_modules/astral-regex": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", "engines": { "node": ">=8" @@ -2416,6 +2645,7 @@ }, "node_modules/async": { "version": "2.6.4", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz", "integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==", "dependencies": { "lodash": "^4.17.14" @@ -2423,10 +2653,12 @@ }, "node_modules/asynckit": { "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" }, "node_modules/atomic-sleep": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/atomic-sleep/-/atomic-sleep-1.0.0.tgz", "integrity": "sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==", "dev": true, "engines": { @@ -2435,6 +2667,7 @@ }, "node_modules/available-typed-arrays": { "version": "1.0.5", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==", "engines": { "node": ">= 0.4" @@ -2445,10 +2678,12 @@ }, "node_modules/aws-profile-handler": { "version": "2.0.3", + "resolved": "https://registry.npmjs.org/aws-profile-handler/-/aws-profile-handler-2.0.3.tgz", "integrity": "sha512-CDArk54zuHtbB13OKXgiwaCGyyH8TJlh+24lI3vw8dD3DpRQtg7uJDjIDZplqIOQqQ6/qdynHf0EjkXdrV1GuA==" }, "node_modules/aws-sdk": { "version": "2.1303.0", + "resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.1303.0.tgz", "integrity": "sha512-KTzMliy60ParQgmnHB3jcAZVQmyLV1ZlNK4jUDP6Hzb0SPZFkGHzzjfSb224o8pB/HfR5n4fT3hOUVWMjISwdA==", "dependencies": { "buffer": "4.9.2", @@ -2466,8 +2701,24 @@ "node": ">= 10.0.0" } }, + "node_modules/aws-sdk/node_modules/buffer": { + "version": "4.9.2", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.2.tgz", + "integrity": "sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg==", + "dependencies": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4", + "isarray": "^1.0.0" + } + }, + "node_modules/aws-sdk/node_modules/ieee754": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", + "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==" + }, "node_modules/aws-sdk/node_modules/uuid": { "version": "8.0.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.0.0.tgz", "integrity": "sha512-jOXGuXZAWdsTH7eZLtyXMqUb9EcWMGZNbL9YcGBJl4MH4nrxHmZJhEHvyLFrkxo+28uLb/NYRcStH48fnD0Vzw==", "bin": { "uuid": "dist/bin/uuid" @@ -2475,6 +2726,7 @@ }, "node_modules/aws-sign2": { "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", "integrity": "sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA==", "engines": { "node": "*" @@ -2482,10 +2734,12 @@ }, "node_modules/aws4": { "version": "1.12.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.12.0.tgz", "integrity": "sha512-NmWvPnx0F1SfrQbYwOi7OeaNGokp9XhzNioJ/CSBs8Qa4vxug81mhJEAVZwxXuBmYB5KDRfMq/F3RR0BIU7sWg==" }, "node_modules/axios": { "version": "0.26.1", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.26.1.tgz", "integrity": "sha512-fPwcX4EvnSHuInCMItEhAGnaSEXRBjtzh9fOtsE6E1G6p7vl7edEeZe11QHf18+6+9gR5PbKV/sGKNaD8YaMeA==", "dependencies": { "follow-redirects": "^1.14.8" @@ -2493,6 +2747,7 @@ }, "node_modules/babel-plugin-istanbul": { "version": "6.1.1", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", "dev": true, "dependencies": { @@ -2508,6 +2763,7 @@ }, "node_modules/babel-preset-current-node-syntax": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz", "integrity": "sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ==", "dev": true, "dependencies": { @@ -2530,10 +2786,12 @@ }, "node_modules/balanced-match": { "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" }, "node_modules/base64-js": { "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", "funding": [ { @@ -2552,6 +2810,7 @@ }, "node_modules/bcrypt-pbkdf": { "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", "integrity": "sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==", "dependencies": { "tweetnacl": "^0.14.3" @@ -2559,6 +2818,7 @@ }, "node_modules/big-integer": { "version": "1.6.51", + "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.51.tgz", "integrity": "sha512-GPEid2Y9QU1Exl1rpO9B2IPJGHPSupF5GnVIP0blYvNOMer2bTvSWs1jGOUg04hTmu67nmLsQ9TBo1puaotBHg==", "dev": true, "engines": { @@ -2567,6 +2827,7 @@ }, "node_modules/binary": { "version": "0.3.0", + "resolved": "https://registry.npmjs.org/binary/-/binary-0.3.0.tgz", "integrity": "sha512-D4H1y5KYwpJgK8wk1Cue5LLPgmwHKYSChkbspQg5JtVuR5ulGckxfR62H3AE9UDkdMC8yyXlqYihuz3Aqg2XZg==", "dev": true, "dependencies": { @@ -2579,6 +2840,7 @@ }, "node_modules/binary-extensions": { "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", "engines": { "node": ">=8" @@ -2586,6 +2848,7 @@ }, "node_modules/bl": { "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", "dependencies": { "buffer": "^5.5.0", @@ -2593,35 +2856,15 @@ "readable-stream": "^3.4.0" } }, - "node_modules/bl/node_modules/buffer": { - "version": "5.7.1", - "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.1.13" - } - }, "node_modules/bluebird": { - "version": "3.7.2", - "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", + "version": "3.4.7", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.4.7.tgz", + "integrity": "sha512-iD3898SR7sWVRHbiQv+sHUtHnMvC1o3nW5rAcqnq3uOn07DSAppZYUkIGslDz6gXC7HfunPe7YVBgoEJASPcHA==", "dev": true }, "node_modules/boxen": { "version": "5.1.2", + "resolved": "https://registry.npmjs.org/boxen/-/boxen-5.1.2.tgz", "integrity": "sha512-9gYgQKXx+1nP8mP7CzFyaUARhg7D3n1dF/FnErWmu9l6JvGpNUN278h0aSb+QjoiKSWG+iZ3uHrcqk0qrY9RQQ==", "dev": true, "dependencies": { @@ -2643,6 +2886,7 @@ }, "node_modules/boxen/node_modules/camelcase": { "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", "dev": true, "engines": { @@ -2654,6 +2898,7 @@ }, "node_modules/boxen/node_modules/chalk": { "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, "dependencies": { @@ -2669,6 +2914,7 @@ }, "node_modules/boxen/node_modules/type-fest": { "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", "dev": true, "engines": { @@ -2680,6 +2926,7 @@ }, "node_modules/brace-expansion": { "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dependencies": { "balanced-match": "^1.0.0", @@ -2688,6 +2935,7 @@ }, "node_modules/braces": { "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", "dependencies": { "fill-range": "^7.0.1" @@ -2698,12 +2946,14 @@ }, "node_modules/browser-stdout": { "version": "1.3.1", + "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", "dev": true }, "node_modules/browserslist": { - "version": "4.21.4", - "integrity": "sha512-CBHJJdDmgjl3daYjN5Cp5kbTf1mUhZoS+beLklHIvkOWscs83YAhLlF3Wsh/lciQYAcbBJgTOD44VtG31ZM4Hw==", + "version": "4.21.5", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.5.tgz", + "integrity": "sha512-tUkiguQGW7S3IhB7N+c2MV/HZPSCPAAiYBZXLsBhFB/PCy6ZKKsZrmBayHV9fdGV/ARIfJ14NkxKzRDjvp7L6w==", "dev": true, "funding": [ { @@ -2716,10 +2966,10 @@ } ], "dependencies": { - "caniuse-lite": "^1.0.30001400", - "electron-to-chromium": "^1.4.251", - "node-releases": "^2.0.6", - "update-browserslist-db": "^1.0.9" + "caniuse-lite": "^1.0.30001449", + "electron-to-chromium": "^1.4.284", + "node-releases": "^2.0.8", + "update-browserslist-db": "^1.0.10" }, "bin": { "browserslist": "cli.js" @@ -2730,6 +2980,7 @@ }, "node_modules/bser": { "version": "2.1.1", + "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", "dev": true, "dependencies": { @@ -2737,16 +2988,31 @@ } }, "node_modules/buffer": { - "version": "4.9.2", - "integrity": "sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg==", + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], "dependencies": { - "base64-js": "^1.0.2", - "ieee754": "^1.1.4", - "isarray": "^1.0.0" + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" } }, "node_modules/buffer-crc32": { "version": "0.2.13", + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", "engines": { "node": "*" @@ -2754,10 +3020,12 @@ }, "node_modules/buffer-from": { "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" }, "node_modules/buffer-indexof-polyfill": { "version": "1.0.2", + "resolved": "https://registry.npmjs.org/buffer-indexof-polyfill/-/buffer-indexof-polyfill-1.0.2.tgz", "integrity": "sha512-I7wzHwA3t1/lwXQh+A5PbNvJxgfo5r3xulgpYDB5zckTu/Z9oUK9biouBKQUjEqzaz3HnAT6TYoovmE+GqSf7A==", "dev": true, "engines": { @@ -2766,6 +3034,7 @@ }, "node_modules/buffers": { "version": "0.1.1", + "resolved": "https://registry.npmjs.org/buffers/-/buffers-0.1.1.tgz", "integrity": "sha512-9q/rDEGSb/Qsvv2qvzIzdluL5k7AaJOTrw23z9reQthrbF7is4CtlT0DXyO1oei2DCp4uojjzQ7igaSHp1kAEQ==", "dev": true, "engines": { @@ -2774,6 +3043,7 @@ }, "node_modules/builtins": { "version": "5.0.1", + "resolved": "https://registry.npmjs.org/builtins/-/builtins-5.0.1.tgz", "integrity": "sha512-qwVpFEHNfhYJIzNRBvd2C1kyo6jz3ZSMPyyuR47OPdiKWlbYnZNyDWuyR175qDnAJLiCo5fBBqPb3RiXgWlkOQ==", "dev": true, "dependencies": { @@ -2782,6 +3052,7 @@ }, "node_modules/bunyan": { "version": "1.8.15", + "resolved": "https://registry.npmjs.org/bunyan/-/bunyan-1.8.15.tgz", "integrity": "sha512-0tECWShh6wUysgucJcBAoYegf3JJoZWibxdqhTm7OHPeT42qdjkZ29QCMcKwbgU1kiH+auSIasNRXMLWXafXig==", "engines": [ "node >=0.10.0" @@ -2798,6 +3069,7 @@ }, "node_modules/cacache": { "version": "16.1.3", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-16.1.3.tgz", "integrity": "sha512-/+Emcj9DAXxX4cwlLmRI9c166RuL3w30zp4R7Joiv2cQTtTtA+jeuCAjH3ZlGnYS3tKENSrKhAzVVP9GVyzeYQ==", "dev": true, "dependencies": { @@ -2826,6 +3098,7 @@ }, "node_modules/cacache/node_modules/brace-expansion": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", "dev": true, "dependencies": { @@ -2834,6 +3107,7 @@ }, "node_modules/cacache/node_modules/glob": { "version": "8.1.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", "dev": true, "dependencies": { @@ -2851,8 +3125,9 @@ } }, "node_modules/cacache/node_modules/lru-cache": { - "version": "7.14.1", - "integrity": "sha512-ysxwsnTKdAx96aTRdhDOCQfDgbHnt8SK0KY8SEjO0wHinhWOFTESbjVCMPbU1uGXg/ch4lifqx0wfjOawU2+WA==", + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", + "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", "dev": true, "engines": { "node": ">=12" @@ -2860,6 +3135,7 @@ }, "node_modules/cacache/node_modules/minimatch": { "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", "dev": true, "dependencies": { @@ -2871,6 +3147,7 @@ }, "node_modules/cacache/node_modules/mkdirp": { "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", "dev": true, "bin": { @@ -2880,23 +3157,10 @@ "node": ">=10" } }, - "node_modules/cacache/node_modules/p-map": { - "version": "4.0.0", - "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", - "dev": true, - "dependencies": { - "aggregate-error": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/cacheable-request": { - "version": "6.1.0", - "integrity": "sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg==", + "node_modules/cacheable-request": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-6.1.0.tgz", + "integrity": "sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg==", "dev": true, "dependencies": { "clone-response": "^1.0.2", @@ -2913,6 +3177,7 @@ }, "node_modules/cacheable-request/node_modules/get-stream": { "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", "dev": true, "dependencies": { @@ -2927,6 +3192,7 @@ }, "node_modules/cacheable-request/node_modules/lowercase-keys": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", "dev": true, "engines": { @@ -2935,6 +3201,7 @@ }, "node_modules/caching-transform": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/caching-transform/-/caching-transform-4.0.0.tgz", "integrity": "sha512-kpqOvwXnjjN44D89K5ccQC+RUrsy7jB/XLlRrx0D7/2HNcTPqzsb6XgYoErwko6QsV184CA2YgS1fxDiiDZMWA==", "dev": true, "dependencies": { @@ -2949,6 +3216,7 @@ }, "node_modules/caching-transform/node_modules/write-file-atomic": { "version": "3.0.3", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", "dev": true, "dependencies": { @@ -2960,6 +3228,7 @@ }, "node_modules/call-bind": { "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", "dependencies": { "function-bind": "^1.1.1", @@ -2971,11 +3240,13 @@ }, "node_modules/call-me-maybe": { "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-me-maybe/-/call-me-maybe-1.0.2.tgz", "integrity": "sha512-HpX65o1Hnr9HH25ojC1YGs7HCQLq0GCOibSaWER0eNpgJ/Z1MZv2mTc7+xh6WOPxbRVcmgbv4hGU+uSQ/2xFZQ==", "dev": true }, "node_modules/callsites": { "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", "dev": true, "engines": { @@ -2984,6 +3255,7 @@ }, "node_modules/camelcase": { "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", "dev": true, "engines": { @@ -2992,6 +3264,7 @@ }, "node_modules/camelcase-keys": { "version": "6.2.2", + "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-6.2.2.tgz", "integrity": "sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg==", "dev": true, "dependencies": { @@ -3007,8 +3280,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001448", - "integrity": "sha512-tq2YI+MJnooG96XpbTRYkBxLxklZPOdLmNIOdIhvf7SNJan6u5vCKum8iT7ZfCt70m1GPkuC7P3TtX6UuhupuA==", + "version": "1.0.30001473", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001473.tgz", + "integrity": "sha512-ewDad7+D2vlyy+E4UJuVfiBsU69IL+8oVmTuZnH5Q6CIUbxNfI50uVpRHbUPDD6SUaN2o0Lh4DhTrvLG/Tn1yg==", "dev": true, "funding": [ { @@ -3018,15 +3292,21 @@ { "type": "tidelift", "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" } ] }, "node_modules/caseless": { "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", "integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==" }, "node_modules/chai": { "version": "4.3.7", + "resolved": "https://registry.npmjs.org/chai/-/chai-4.3.7.tgz", "integrity": "sha512-HLnAzZ2iupm25PlN0xFreAlBA5zaBSv3og0DdeGA4Ar6h6rJ3A0rolRUKJhSF2V10GZKDgWF/VmAEsNWjCRB+A==", "dev": true, "dependencies": { @@ -3044,6 +3324,7 @@ }, "node_modules/chai-as-promised": { "version": "7.1.1", + "resolved": "https://registry.npmjs.org/chai-as-promised/-/chai-as-promised-7.1.1.tgz", "integrity": "sha512-azL6xMoi+uxu6z4rhWQ1jbdUhOMhis2PvscD/xjLqNMkv3BPPp2JyyuTHOrf9BOosGpNQ11v6BKv/g57RXbiaA==", "dev": true, "dependencies": { @@ -3055,6 +3336,7 @@ }, "node_modules/chai-json-schema": { "version": "1.5.1", + "resolved": "https://registry.npmjs.org/chai-json-schema/-/chai-json-schema-1.5.1.tgz", "integrity": "sha512-TR/xPDxRhqwFFCWg1HgL8nNWbpNfUwaib6pBN++QKpnd0t+o3+MBvAn5CM1mpdUMaM76oJAtUjGKdjGad01lIA==", "dev": true, "dependencies": { @@ -3070,11 +3352,13 @@ }, "node_modules/chai-uuid": { "version": "1.0.6", + "resolved": "https://registry.npmjs.org/chai-uuid/-/chai-uuid-1.0.6.tgz", "integrity": "sha512-CG0kRk6TqI16ifkoNGLvyb6/Dz8ChE7nsrKCEUXa98ES3nnF3lYDCqXystFXTkH+2233favzkqmCbQT5uW+8iQ==", "dev": true }, "node_modules/chainsaw": { "version": "0.1.0", + "resolved": "https://registry.npmjs.org/chainsaw/-/chainsaw-0.1.0.tgz", "integrity": "sha512-75kWfWt6MEKNC8xYXIdRpDehRYY/tNSgwKaJq+dbbDcxORuVrrQ+SEHoWsniVn9XPYfP4gmdWIeDk/4YNp1rNQ==", "dev": true, "dependencies": { @@ -3086,6 +3370,7 @@ }, "node_modules/chalk": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.0.0.tgz", "integrity": "sha512-N9oWFcegS0sFr9oh1oz2d7Npos6vNoWW9HvtCg5N1KRFpUhaAhvTv5Y58g880fZaEYSNm3qDz8SU1UrGvp+n7A==", "dependencies": { "ansi-styles": "^4.1.0", @@ -3100,10 +3385,12 @@ }, "node_modules/chardet": { "version": "0.7.0", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==" }, "node_modules/charset": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/charset/-/charset-1.0.1.tgz", "integrity": "sha512-6dVyOOYjpfFcL1Y4qChrAoQLRHvj2ziyhcm0QJlhOcAhykL/k1kTUPbeo+87MNRTRdk2OIIsIXbuF3x2wi5EXg==", "dev": true, "engines": { @@ -3112,6 +3399,7 @@ }, "node_modules/check-error": { "version": "1.0.2", + "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", "integrity": "sha512-BrgHpW9NURQgzoNyjfq0Wu6VFO6D7IZEmJNdtgNqpzGG8RuNFHt2jQxWlAs4HMe119chBnv+34syEZtc6IhLtA==", "dev": true, "engines": { @@ -3120,6 +3408,7 @@ }, "node_modules/chokidar": { "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", "funding": [ { @@ -3145,6 +3434,7 @@ }, "node_modules/chownr": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", "dev": true, "engines": { @@ -3152,8 +3442,9 @@ } }, "node_modules/ci-info": { - "version": "3.7.1", - "integrity": "sha512-4jYS4MOAaCIStSRwiuxc4B8MYhIe676yO1sYGzARnjXkWpmzZMMYxY6zu8WYWDhSuth5zhrQ1rhNSibyyvv4/w==", + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.8.0.tgz", + "integrity": "sha512-eXTggHWSooYhq49F2opQhuHWgzucfF2YgODK4e1566GQs5BIfP30B0oenwBJHfWxAs2fyPB1s7Mg949zLf61Yw==", "dev": true, "funding": [ { @@ -3167,11 +3458,13 @@ }, "node_modules/cint": { "version": "8.2.1", + "resolved": "https://registry.npmjs.org/cint/-/cint-8.2.1.tgz", "integrity": "sha512-gyWqJHXgDFPNx7PEyFJotutav+al92TTC3dWlMFyTETlOyKBQMZb7Cetqmj3GlrnSILHwSJRwf4mIGzc7C5lXw==", "dev": true }, "node_modules/clean-stack": { "version": "2.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", "engines": { "node": ">=6" @@ -3179,6 +3472,7 @@ }, "node_modules/cli-boxes": { "version": "2.2.1", + "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-2.2.1.tgz", "integrity": "sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw==", "dev": true, "engines": { @@ -3190,6 +3484,7 @@ }, "node_modules/cli-cursor": { "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", "dependencies": { "restore-cursor": "^3.1.0" @@ -3200,6 +3495,7 @@ }, "node_modules/cli-spinners": { "version": "2.7.0", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.7.0.tgz", "integrity": "sha512-qu3pN8Y3qHNgE2AFweciB1IfMnmZ/fsNTEE+NOFjmGB2F/7rLhnhzppvpCnN4FovtP26k8lHyy9ptEbNwWFLzw==", "engines": { "node": ">=6" @@ -3210,6 +3506,7 @@ }, "node_modules/cli-table": { "version": "0.3.11", + "resolved": "https://registry.npmjs.org/cli-table/-/cli-table-0.3.11.tgz", "integrity": "sha512-IqLQi4lO0nIB4tcdTpN4LCB9FI3uqrJZK7RC515EnhZ6qBaglkIgICb1wjeAqpdoOabm1+SuQtkXIPdYC93jhQ==", "dev": true, "dependencies": { @@ -3221,6 +3518,7 @@ }, "node_modules/cli-truncate": { "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-3.1.0.tgz", "integrity": "sha512-wfOBkjXteqSnI59oPcJkcPl/ZmwvMMOj340qUIY1SKZCv0B9Cf4D4fAucRkIKQmsIuYK3x1rrgU7MeGRruiuiA==", "dependencies": { "slice-ansi": "^5.0.0", @@ -3235,6 +3533,7 @@ }, "node_modules/cli-truncate/node_modules/ansi-regex": { "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", "engines": { "node": ">=12" @@ -3245,10 +3544,12 @@ }, "node_modules/cli-truncate/node_modules/emoji-regex": { "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==" }, "node_modules/cli-truncate/node_modules/string-width": { "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", "dependencies": { "eastasianwidth": "^0.2.0", @@ -3264,6 +3565,7 @@ }, "node_modules/cli-truncate/node_modules/strip-ansi": { "version": "7.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.0.1.tgz", "integrity": "sha512-cXNxvT8dFNRVfhVME3JAe98mkXDYN2O1l7jmcwMnOslDeESg1rF/OZMtK0nRAhiari1unG5cD4jG3rapUAkLbw==", "dependencies": { "ansi-regex": "^6.0.1" @@ -3277,6 +3579,7 @@ }, "node_modules/cli-width": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-3.0.0.tgz", "integrity": "sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==", "engines": { "node": ">= 10" @@ -3284,6 +3587,7 @@ }, "node_modules/cliui": { "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", "dependencies": { "string-width": "^4.2.0", @@ -3296,6 +3600,7 @@ }, "node_modules/clone": { "version": "1.0.4", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==", "engines": { "node": ">=0.8" @@ -3303,6 +3608,7 @@ }, "node_modules/clone-response": { "version": "1.0.3", + "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.3.tgz", "integrity": "sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA==", "dev": true, "dependencies": { @@ -3314,6 +3620,7 @@ }, "node_modules/code-point-at": { "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", "integrity": "sha512-RpAVKQA5T63xEj6/giIbUEtZwJ4UFIc3ZtvEkiaUERylqe8xb5IvqcgOurZLahv93CLKfxcw5YI+DZcUBRyLXA==", "engines": { "node": ">=0.10.0" @@ -3321,11 +3628,13 @@ }, "node_modules/collect-v8-coverage": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.1.tgz", "integrity": "sha512-iBPtljfCNcTKNAto0KEtDfZ3qzjJvqE3aTGZsbhjSBlorqpXJlaWWtPO35D+ZImoC3KWejX64o+yPGxhWSTzfg==", "dev": true }, "node_modules/color-convert": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dependencies": { "color-name": "~1.1.4" @@ -3336,10 +3645,12 @@ }, "node_modules/color-name": { "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" }, "node_modules/color-support": { "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", "dev": true, "bin": { @@ -3348,10 +3659,12 @@ }, "node_modules/colorette": { "version": "2.0.19", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.19.tgz", "integrity": "sha512-3tlv/dIP7FWvj3BsbHrGLJ6l/oKh1O3TcgBqMn+yyCagOxc23fyzDS6HypQbgxWbkpDnf52p1LuR4eWDQ/K9WQ==" }, "node_modules/colors": { "version": "1.0.3", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.0.3.tgz", "integrity": "sha512-pFGrxThWcWQ2MsAz6RtgeWe4NK2kUE1WfsrvvlctdII745EW9I0yflqhe7++M5LEc7bV2c/9/5zc8sFcpL0Drw==", "dev": true, "engines": { @@ -3360,6 +3673,7 @@ }, "node_modules/combined-stream": { "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", "dependencies": { "delayed-stream": "~1.0.0" @@ -3370,6 +3684,7 @@ }, "node_modules/commander": { "version": "4.1.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", "engines": { "node": ">= 6" @@ -3377,11 +3692,13 @@ }, "node_modules/commondir": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==", "dev": true }, "node_modules/compare-func": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/compare-func/-/compare-func-2.0.0.tgz", "integrity": "sha512-zHig5N+tPWARooBnb0Zx1MFcdfpyJrfTJ3Y5L+IFvUm8rM74hHz66z0gw0x4tijh5CorKkKUCnW82R2vmpeCRA==", "dev": true, "dependencies": { @@ -3391,6 +3708,7 @@ }, "node_modules/compress-commons": { "version": "4.1.1", + "resolved": "https://registry.npmjs.org/compress-commons/-/compress-commons-4.1.1.tgz", "integrity": "sha512-QLdDLCKNV2dtoTorqgxngQCMA+gWXkM/Nwu7FpeBhk/RdkzimqC3jueb/FDmaZeXh+uby1jkBqE3xArsLBE5wQ==", "dependencies": { "buffer-crc32": "^0.2.13", @@ -3404,6 +3722,7 @@ }, "node_modules/compute-gcd": { "version": "1.2.1", + "resolved": "https://registry.npmjs.org/compute-gcd/-/compute-gcd-1.2.1.tgz", "integrity": "sha512-TwMbxBNz0l71+8Sc4czv13h4kEqnchV9igQZBi6QUaz09dnz13juGnnaWWJTRsP3brxOoxeB4SA2WELLw1hCtg==", "dev": true, "dependencies": { @@ -3414,6 +3733,7 @@ }, "node_modules/compute-lcm": { "version": "1.1.2", + "resolved": "https://registry.npmjs.org/compute-lcm/-/compute-lcm-1.1.2.tgz", "integrity": "sha512-OFNPdQAXnQhDSKioX8/XYT6sdUlXwpeMjfd6ApxMJfyZ4GxmLR1xvMERctlYhlHwIiz6CSpBc2+qYKjHGZw4TQ==", "dev": true, "dependencies": { @@ -3425,10 +3745,12 @@ }, "node_modules/concat-map": { "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" }, "node_modules/concat-stream": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz", "integrity": "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==", "dev": true, "engines": [ @@ -3443,6 +3765,7 @@ }, "node_modules/configstore": { "version": "5.0.1", + "resolved": "https://registry.npmjs.org/configstore/-/configstore-5.0.1.tgz", "integrity": "sha512-aMKprgk5YhBNyH25hj8wGt2+D52Sw1DRRIzqBwLp2Ya9mFmY8KPvvtvmna8SxVR9JMZ4kzMD68N22vlaRpkeFA==", "dev": true, "dependencies": { @@ -3459,6 +3782,7 @@ }, "node_modules/configstore/node_modules/write-file-atomic": { "version": "3.0.3", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", "dev": true, "dependencies": { @@ -3470,12 +3794,14 @@ }, "node_modules/console-control-strings": { "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==", "dev": true }, "node_modules/content-type": { - "version": "1.0.4", - "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", "dev": true, "engines": { "node": ">= 0.6" @@ -3483,6 +3809,7 @@ }, "node_modules/conventional-changelog": { "version": "3.1.25", + "resolved": "https://registry.npmjs.org/conventional-changelog/-/conventional-changelog-3.1.25.tgz", "integrity": "sha512-ryhi3fd1mKf3fSjbLXOfK2D06YwKNic1nC9mWqybBHdObPd8KJ2vjaXZfYj1U23t+V8T8n0d7gwnc9XbIdFbyQ==", "dev": true, "dependencies": { @@ -3504,6 +3831,7 @@ }, "node_modules/conventional-changelog-angular": { "version": "5.0.13", + "resolved": "https://registry.npmjs.org/conventional-changelog-angular/-/conventional-changelog-angular-5.0.13.tgz", "integrity": "sha512-i/gipMxs7s8L/QeuavPF2hLnJgH6pEZAttySB6aiQLWcX3puWDL3ACVmvBhJGxnAy52Qc15ua26BufY6KpmrVA==", "dev": true, "dependencies": { @@ -3516,6 +3844,7 @@ }, "node_modules/conventional-changelog-atom": { "version": "2.0.8", + "resolved": "https://registry.npmjs.org/conventional-changelog-atom/-/conventional-changelog-atom-2.0.8.tgz", "integrity": "sha512-xo6v46icsFTK3bb7dY/8m2qvc8sZemRgdqLb/bjpBsH2UyOS8rKNTgcb5025Hri6IpANPApbXMg15QLb1LJpBw==", "dev": true, "dependencies": { @@ -3527,6 +3856,7 @@ }, "node_modules/conventional-changelog-codemirror": { "version": "2.0.8", + "resolved": "https://registry.npmjs.org/conventional-changelog-codemirror/-/conventional-changelog-codemirror-2.0.8.tgz", "integrity": "sha512-z5DAsn3uj1Vfp7po3gpt2Boc+Bdwmw2++ZHa5Ak9k0UKsYAO5mH1UBTN0qSCuJZREIhX6WU4E1p3IW2oRCNzQw==", "dev": true, "dependencies": { @@ -3538,11 +3868,13 @@ }, "node_modules/conventional-changelog-config-spec": { "version": "2.1.0", + "resolved": "https://registry.npmjs.org/conventional-changelog-config-spec/-/conventional-changelog-config-spec-2.1.0.tgz", "integrity": "sha512-IpVePh16EbbB02V+UA+HQnnPIohgXvJRxHcS5+Uwk4AT5LjzCZJm5sp/yqs5C6KZJ1jMsV4paEV13BN1pvDuxQ==", "dev": true }, "node_modules/conventional-changelog-conventionalcommits": { "version": "4.6.3", + "resolved": "https://registry.npmjs.org/conventional-changelog-conventionalcommits/-/conventional-changelog-conventionalcommits-4.6.3.tgz", "integrity": "sha512-LTTQV4fwOM4oLPad317V/QNQ1FY4Hju5qeBIM1uTHbrnCE+Eg4CdRZ3gO2pUeR+tzWdp80M2j3qFFEDWVqOV4g==", "dev": true, "dependencies": { @@ -3556,6 +3888,7 @@ }, "node_modules/conventional-changelog-core": { "version": "4.2.4", + "resolved": "https://registry.npmjs.org/conventional-changelog-core/-/conventional-changelog-core-4.2.4.tgz", "integrity": "sha512-gDVS+zVJHE2v4SLc6B0sLsPiloR0ygU7HaDW14aNJE1v4SlqJPILPl/aJC7YdtRE4CybBf8gDwObBvKha8Xlyg==", "dev": true, "dependencies": { @@ -3580,6 +3913,7 @@ }, "node_modules/conventional-changelog-core/node_modules/find-up": { "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", "integrity": "sha512-NWzkk0jSJtTt08+FBFMvXoeZnOJD+jTtsRmBYbAIzJdX6l7dLgR7CTubCM5/eDdPUBvLCeVasP1brfVR/9/EZQ==", "dev": true, "dependencies": { @@ -3591,11 +3925,13 @@ }, "node_modules/conventional-changelog-core/node_modules/hosted-git-info": { "version": "2.8.9", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", "dev": true }, "node_modules/conventional-changelog-core/node_modules/locate-path": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", "integrity": "sha512-NCI2kiDkyR7VeEKm27Kda/iQHyKJe1Bu0FlTbYp3CqJu+9IFe9bLyAjMxf5ZDDbEg+iMPzB5zYyUTSm8wVTKmA==", "dev": true, "dependencies": { @@ -3608,6 +3944,7 @@ }, "node_modules/conventional-changelog-core/node_modules/p-limit": { "version": "1.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", "dev": true, "dependencies": { @@ -3619,6 +3956,7 @@ }, "node_modules/conventional-changelog-core/node_modules/p-locate": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", "integrity": "sha512-nQja7m7gSKuewoVRen45CtVfODR3crN3goVQ0DDZ9N3yHxgpkuBhZqsaiotSQRrADUrne346peY7kT3TSACykg==", "dev": true, "dependencies": { @@ -3630,6 +3968,7 @@ }, "node_modules/conventional-changelog-core/node_modules/p-try": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", "integrity": "sha512-U1etNYuMJoIz3ZXSrrySFjsXQTWOx2/jdi86L+2pRvph/qMKL6sbcCYdH23fqsbm8TH2Gn0OybpT4eSFlCVHww==", "dev": true, "engines": { @@ -3638,6 +3977,7 @@ }, "node_modules/conventional-changelog-core/node_modules/path-exists": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", "dev": true, "engines": { @@ -3646,6 +3986,7 @@ }, "node_modules/conventional-changelog-core/node_modules/path-type": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", "dev": true, "dependencies": { @@ -3657,6 +3998,7 @@ }, "node_modules/conventional-changelog-core/node_modules/read-pkg": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", "integrity": "sha512-BLq/cCO9two+lBgiTYNqD6GdtK8s4NpaWrl6/rCO9w0TUS8oJl7cmToOZfRYllKTISY6nt1U7jQ53brmKqY6BA==", "dev": true, "dependencies": { @@ -3670,6 +4012,7 @@ }, "node_modules/conventional-changelog-core/node_modules/read-pkg-up": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-3.0.0.tgz", "integrity": "sha512-YFzFrVvpC6frF1sz8psoHDBGF7fLPc+llq/8NB43oagqWkx8ar5zYtsTORtOjw9W2RHLpWP+zTWwBvf1bCmcSw==", "dev": true, "dependencies": { @@ -3682,6 +4025,7 @@ }, "node_modules/conventional-changelog-core/node_modules/read-pkg/node_modules/normalize-package-data": { "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", "dev": true, "dependencies": { @@ -3693,6 +4037,7 @@ }, "node_modules/conventional-changelog-core/node_modules/semver": { "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", "dev": true, "bin": { @@ -3701,6 +4046,7 @@ }, "node_modules/conventional-changelog-ember": { "version": "2.0.9", + "resolved": "https://registry.npmjs.org/conventional-changelog-ember/-/conventional-changelog-ember-2.0.9.tgz", "integrity": "sha512-ulzIReoZEvZCBDhcNYfDIsLTHzYHc7awh+eI44ZtV5cx6LVxLlVtEmcO+2/kGIHGtw+qVabJYjdI5cJOQgXh1A==", "dev": true, "dependencies": { @@ -3712,6 +4058,7 @@ }, "node_modules/conventional-changelog-eslint": { "version": "3.0.9", + "resolved": "https://registry.npmjs.org/conventional-changelog-eslint/-/conventional-changelog-eslint-3.0.9.tgz", "integrity": "sha512-6NpUCMgU8qmWmyAMSZO5NrRd7rTgErjrm4VASam2u5jrZS0n38V7Y9CzTtLT2qwz5xEChDR4BduoWIr8TfwvXA==", "dev": true, "dependencies": { @@ -3723,6 +4070,7 @@ }, "node_modules/conventional-changelog-express": { "version": "2.0.6", + "resolved": "https://registry.npmjs.org/conventional-changelog-express/-/conventional-changelog-express-2.0.6.tgz", "integrity": "sha512-SDez2f3iVJw6V563O3pRtNwXtQaSmEfTCaTBPCqn0oG0mfkq0rX4hHBq5P7De2MncoRixrALj3u3oQsNK+Q0pQ==", "dev": true, "dependencies": { @@ -3734,6 +4082,7 @@ }, "node_modules/conventional-changelog-jquery": { "version": "3.0.11", + "resolved": "https://registry.npmjs.org/conventional-changelog-jquery/-/conventional-changelog-jquery-3.0.11.tgz", "integrity": "sha512-x8AWz5/Td55F7+o/9LQ6cQIPwrCjfJQ5Zmfqi8thwUEKHstEn4kTIofXub7plf1xvFA2TqhZlq7fy5OmV6BOMw==", "dev": true, "dependencies": { @@ -3745,6 +4094,7 @@ }, "node_modules/conventional-changelog-jshint": { "version": "2.0.9", + "resolved": "https://registry.npmjs.org/conventional-changelog-jshint/-/conventional-changelog-jshint-2.0.9.tgz", "integrity": "sha512-wMLdaIzq6TNnMHMy31hql02OEQ8nCQfExw1SE0hYL5KvU+JCTuPaDO+7JiogGT2gJAxiUGATdtYYfh+nT+6riA==", "dev": true, "dependencies": { @@ -3757,6 +4107,7 @@ }, "node_modules/conventional-changelog-preset-loader": { "version": "2.3.4", + "resolved": "https://registry.npmjs.org/conventional-changelog-preset-loader/-/conventional-changelog-preset-loader-2.3.4.tgz", "integrity": "sha512-GEKRWkrSAZeTq5+YjUZOYxdHq+ci4dNwHvpaBC3+ENalzFWuCWa9EZXSuZBpkr72sMdKB+1fyDV4takK1Lf58g==", "dev": true, "engines": { @@ -3765,6 +4116,7 @@ }, "node_modules/conventional-changelog-writer": { "version": "5.0.1", + "resolved": "https://registry.npmjs.org/conventional-changelog-writer/-/conventional-changelog-writer-5.0.1.tgz", "integrity": "sha512-5WsuKUfxW7suLblAbFnxAcrvf6r+0b7GvNaWUwUIk0bXMnENP/PEieGKVUQrjPqwPT4o3EPAASBXiY6iHooLOQ==", "dev": true, "dependencies": { @@ -3787,6 +4139,7 @@ }, "node_modules/conventional-changelog-writer/node_modules/semver": { "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", "dev": true, "bin": { @@ -3795,6 +4148,7 @@ }, "node_modules/conventional-commits-filter": { "version": "2.0.7", + "resolved": "https://registry.npmjs.org/conventional-commits-filter/-/conventional-commits-filter-2.0.7.tgz", "integrity": "sha512-ASS9SamOP4TbCClsRHxIHXRfcGCnIoQqkvAzCSbZzTFLfcTqJVugB0agRgsEELsqaeWgsXv513eS116wnlSSPA==", "dev": true, "dependencies": { @@ -3807,6 +4161,7 @@ }, "node_modules/conventional-commits-parser": { "version": "3.2.4", + "resolved": "https://registry.npmjs.org/conventional-commits-parser/-/conventional-commits-parser-3.2.4.tgz", "integrity": "sha512-nK7sAtfi+QXbxHCYfhpZsfRtaitZLIA6889kFIouLvz6repszQDgxBu7wf2WbU+Dco7sAnNCJYERCwt54WPC2Q==", "dev": true, "dependencies": { @@ -3826,6 +4181,7 @@ }, "node_modules/conventional-recommended-bump": { "version": "6.1.0", + "resolved": "https://registry.npmjs.org/conventional-recommended-bump/-/conventional-recommended-bump-6.1.0.tgz", "integrity": "sha512-uiApbSiNGM/kkdL9GTOLAqC4hbptObFo4wW2QRyHsKciGAfQuLU1ShZ1BIVI/+K2BE/W1AWYQMCXAsv4dyKPaw==", "dev": true, "dependencies": { @@ -3847,11 +4203,13 @@ }, "node_modules/convert-source-map": { "version": "1.9.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==", "dev": true }, "node_modules/copyfiles": { "version": "2.4.1", + "resolved": "https://registry.npmjs.org/copyfiles/-/copyfiles-2.4.1.tgz", "integrity": "sha512-fereAvAvxDrQDOXybk3Qu3dPbOoKoysFMWtkY3mv5BsL8//OSZVL5DCLYqgRfY5cWirgRzlC+WSrxp6Bo3eNZg==", "dev": true, "dependencies": { @@ -3870,6 +4228,7 @@ }, "node_modules/copyfiles/node_modules/cliui": { "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", "dev": true, "dependencies": { @@ -3880,6 +4239,7 @@ }, "node_modules/copyfiles/node_modules/mkdirp": { "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", "dev": true, "bin": { @@ -3890,8 +4250,9 @@ } }, "node_modules/copyfiles/node_modules/readable-stream": { - "version": "2.3.7", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", "dev": true, "dependencies": { "core-util-is": "~1.0.0", @@ -3905,19 +4266,13 @@ }, "node_modules/copyfiles/node_modules/safe-buffer": { "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", "dev": true }, - "node_modules/copyfiles/node_modules/string_decoder": { - "version": "1.1.1", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, "node_modules/copyfiles/node_modules/through2": { "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", "dev": true, "dependencies": { @@ -3927,6 +4282,7 @@ }, "node_modules/copyfiles/node_modules/yargs": { "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", "dev": true, "dependencies": { @@ -3944,10 +4300,12 @@ }, "node_modules/core-util-is": { "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", "integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==" }, "node_modules/cosmiconfig": { "version": "7.1.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz", "integrity": "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==", "dev": true, "dependencies": { @@ -3963,6 +4321,7 @@ }, "node_modules/cosmiconfig-typescript-loader": { "version": "2.0.2", + "resolved": "https://registry.npmjs.org/cosmiconfig-typescript-loader/-/cosmiconfig-typescript-loader-2.0.2.tgz", "integrity": "sha512-KmE+bMjWMXJbkWCeY4FJX/npHuZPNr9XF9q9CIQ/bpFwi1qHfCmSiKarrCcRa0LO4fWjk93pVoeRtJAkTGcYNw==", "dev": true, "dependencies": { @@ -3981,6 +4340,7 @@ }, "node_modules/crc-32": { "version": "1.2.2", + "resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.2.tgz", "integrity": "sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==", "bin": { "crc32": "bin/crc32.njs" @@ -3991,6 +4351,7 @@ }, "node_modules/crc32-stream": { "version": "4.0.2", + "resolved": "https://registry.npmjs.org/crc32-stream/-/crc32-stream-4.0.2.tgz", "integrity": "sha512-DxFZ/Hk473b/muq1VJ///PMNLj0ZMnzye9thBpmjpJKCc5eMgB95aK8zCGrGfQ90cWo561Te6HK9D+j4KPdM6w==", "dependencies": { "crc-32": "^1.2.0", @@ -4002,11 +4363,42 @@ }, "node_modules/create-require": { "version": "1.1.1", + "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", "dev": true }, + "node_modules/cross-fetch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.5.tgz", + "integrity": "sha512-lvb1SBsI0Z7GDwmuid+mU3kWVBwTVUbe7S0H52yaaAdQOXq2YktTCZdlAcNKFzE6QtRz0snpw9bNiPeOIkkQvw==", + "dev": true, + "dependencies": { + "node-fetch": "2.6.7" + } + }, + "node_modules/cross-fetch/node_modules/node-fetch": { + "version": "2.6.7", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", + "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", + "dev": true, + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, "node_modules/cross-spawn": { "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", "dependencies": { "path-key": "^3.1.0", @@ -4019,6 +4411,7 @@ }, "node_modules/crypto-random-string": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz", "integrity": "sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==", "dev": true, "engines": { @@ -4027,6 +4420,7 @@ }, "node_modules/dargs": { "version": "7.0.0", + "resolved": "https://registry.npmjs.org/dargs/-/dargs-7.0.0.tgz", "integrity": "sha512-2iy1EkLdlBzQGvbweYRFxmFath8+K7+AKB0TlhHWkNuH+TmovaMH/Wp7V7R4u7f4SnX3OgLsU9t1NI9ioDnUpg==", "dev": true, "engines": { @@ -4035,6 +4429,7 @@ }, "node_modules/dashdash": { "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", "integrity": "sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==", "dependencies": { "assert-plus": "^1.0.0" @@ -4045,6 +4440,7 @@ }, "node_modules/date-fns": { "version": "2.29.3", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.29.3.tgz", "integrity": "sha512-dDCnyH2WnnKusqvZZ6+jA1O51Ibt8ZMRNkDZdyAyK4YfbDwa/cEmuztzG5pk6hqlp9aSBPYcjOlktquahGwGeA==", "engines": { "node": ">=0.11" @@ -4056,6 +4452,7 @@ }, "node_modules/dateformat": { "version": "3.0.3", + "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-3.0.3.tgz", "integrity": "sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q==", "dev": true, "engines": { @@ -4064,6 +4461,7 @@ }, "node_modules/debug": { "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", "dependencies": { "ms": "2.1.2" @@ -4079,6 +4477,7 @@ }, "node_modules/decamelize": { "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", "dev": true, "engines": { @@ -4087,6 +4486,7 @@ }, "node_modules/decamelize-keys": { "version": "1.1.1", + "resolved": "https://registry.npmjs.org/decamelize-keys/-/decamelize-keys-1.1.1.tgz", "integrity": "sha512-WiPxgEirIV0/eIOMcnFBA3/IJZAZqKnwAwWyvvdi4lsr1WCN22nhdf/3db3DoZcUjTV2SqfzIwNyp6y2xs3nmg==", "dev": true, "dependencies": { @@ -4102,6 +4502,7 @@ }, "node_modules/decamelize-keys/node_modules/map-obj": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", "integrity": "sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg==", "dev": true, "engines": { @@ -4110,6 +4511,7 @@ }, "node_modules/decompress-response": { "version": "3.3.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", "integrity": "sha512-BzRPQuY1ip+qDonAOz42gRm/pg9F768C+npV/4JOsxRC2sq+Rlk+Q4ZCAsOhnIaMrgarILY+RMUIvMmmX1qAEA==", "dev": true, "dependencies": { @@ -4121,6 +4523,7 @@ }, "node_modules/deep-eql": { "version": "4.1.3", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.3.tgz", "integrity": "sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw==", "dev": true, "dependencies": { @@ -4132,6 +4535,7 @@ }, "node_modules/deep-extend": { "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", "dev": true, "engines": { @@ -4140,6 +4544,7 @@ }, "node_modules/default-require-extensions": { "version": "3.0.1", + "resolved": "https://registry.npmjs.org/default-require-extensions/-/default-require-extensions-3.0.1.tgz", "integrity": "sha512-eXTJmRbm2TIt9MgWTsOH1wEuhew6XGZcMeGKCtLedIg/NCsg1iBePXkceTdK4Fii7pzmN9tGsZhKzZ4h7O/fxw==", "dev": true, "dependencies": { @@ -4152,8 +4557,18 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/default-require-extensions/node_modules/strip-bom": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", + "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/defaults": { "version": "1.0.4", + "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz", "integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==", "dependencies": { "clone": "^1.0.2" @@ -4164,11 +4579,13 @@ }, "node_modules/defer-to-connect": { "version": "1.1.3", + "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-1.1.3.tgz", "integrity": "sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ==", "dev": true }, "node_modules/define-lazy-prop": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==", "engines": { "node": ">=8" @@ -4176,6 +4593,7 @@ }, "node_modules/delayed-stream": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", "engines": { "node": ">=0.4.0" @@ -4183,19 +4601,22 @@ }, "node_modules/delegates": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==", "dev": true }, "node_modules/depd": { - "version": "1.1.2", - "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", "dev": true, "engines": { - "node": ">= 0.6" + "node": ">= 0.8" } }, "node_modules/detect-indent": { "version": "6.1.0", + "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-6.1.0.tgz", "integrity": "sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==", "dev": true, "engines": { @@ -4204,6 +4625,7 @@ }, "node_modules/detect-newline": { "version": "3.1.0", + "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", "dev": true, "engines": { @@ -4211,8 +4633,9 @@ } }, "node_modules/diff": { - "version": "5.0.0", - "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", "dev": true, "engines": { "node": ">=0.3.1" @@ -4220,6 +4643,7 @@ }, "node_modules/diff-sequences": { "version": "28.1.1", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-28.1.1.tgz", "integrity": "sha512-FU0iFaH/E23a+a718l8Qa/19bF9p06kgE0KipMOMadwa3SjnaElKzPaUC0vnibs6/B/9ni97s61mcejk8W1fQw==", "dev": true, "engines": { @@ -4228,6 +4652,7 @@ }, "node_modules/dir-glob": { "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", "dev": true, "dependencies": { @@ -4239,6 +4664,7 @@ }, "node_modules/dot-prop": { "version": "5.3.0", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz", "integrity": "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==", "dev": true, "dependencies": { @@ -4250,6 +4676,7 @@ }, "node_modules/dotgitignore": { "version": "2.1.0", + "resolved": "https://registry.npmjs.org/dotgitignore/-/dotgitignore-2.1.0.tgz", "integrity": "sha512-sCm11ak2oY6DglEPpCB8TixLjWAxd3kJTs6UIcSasNYxXdFPV+YKlye92c8H4kKFqV5qYMIh7d+cYecEg0dIkA==", "dev": true, "dependencies": { @@ -4262,6 +4689,7 @@ }, "node_modules/dotgitignore/node_modules/find-up": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", "dev": true, "dependencies": { @@ -4273,6 +4701,7 @@ }, "node_modules/dotgitignore/node_modules/locate-path": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", "dev": true, "dependencies": { @@ -4283,22 +4712,9 @@ "node": ">=6" } }, - "node_modules/dotgitignore/node_modules/p-limit": { - "version": "2.3.0", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/dotgitignore/node_modules/p-locate": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", "dev": true, "dependencies": { @@ -4310,6 +4726,7 @@ }, "node_modules/dotgitignore/node_modules/path-exists": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", "dev": true, "engines": { @@ -4318,6 +4735,7 @@ }, "node_modules/dtrace-provider": { "version": "0.8.8", + "resolved": "https://registry.npmjs.org/dtrace-provider/-/dtrace-provider-0.8.8.tgz", "integrity": "sha512-b7Z7cNtHPhH9EJhNNbbeqTcXB8LGFFZhq1PGgEvpeHlzd36bhbdTWoE/Ba/YguqpBSlAPKnARWhVlhunCMwfxg==", "hasInstallScript": true, "optional": true, @@ -4330,6 +4748,7 @@ }, "node_modules/duplexer2": { "version": "0.1.4", + "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", "integrity": "sha512-asLFVfWWtJ90ZyOUHMqk7/S2w2guQKxUI2itj3d92ADHhxUSbCMGi1f1cBcJ7xM1To+pE/Khbwo1yuNbMEPKeA==", "dev": true, "dependencies": { @@ -4337,8 +4756,9 @@ } }, "node_modules/duplexer2/node_modules/readable-stream": { - "version": "2.3.7", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", "dev": true, "dependencies": { "core-util-is": "~1.0.0", @@ -4352,28 +4772,24 @@ }, "node_modules/duplexer2/node_modules/safe-buffer": { "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", "dev": true }, - "node_modules/duplexer2/node_modules/string_decoder": { - "version": "1.1.1", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, "node_modules/duplexer3": { "version": "0.1.5", + "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.5.tgz", "integrity": "sha512-1A8za6ws41LQgv9HrE/66jyC5yuSjQ3L/KOpFtoBilsAK2iA2wuS5rTt1OCzIvtS2V7nVmedsUU+DGRcjBmOYA==", "dev": true }, "node_modules/eastasianwidth": { "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==" }, "node_modules/ecc-jsbn": { "version": "0.1.2", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", "integrity": "sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==", "dependencies": { "jsbn": "~0.1.0", @@ -4381,12 +4797,14 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.4.284", - "integrity": "sha512-M8WEXFuKXMYMVr45fo8mq0wUrrJHheiKZf6BArTKk9ZBYCKJEOU5H8cdWgDT+qCVZf7Na4lVUaZsA+h6uA9+PA==", + "version": "1.4.346", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.346.tgz", + "integrity": "sha512-9ZpKQD8hyWAoYf5bccm2qpaWogAGxb833DVC0arHo9nIbiAMh+aAKHZWABR2P9sK4a3zoCq7eXg8tylqPAnuNw==", "dev": true }, "node_modules/elegant-spinner": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/elegant-spinner/-/elegant-spinner-1.0.1.tgz", "integrity": "sha512-B+ZM+RXvRqQaAmkMlO/oSe5nMUOaUnyfGYCEHoR8wrXsZR2mA0XVibsxV1bvTwxdRWah1PkQqso2EzhILGHtEQ==", "engines": { "node": ">=0.10.0" @@ -4394,10 +4812,12 @@ }, "node_modules/emoji-regex": { "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" }, "node_modules/encoding": { "version": "0.1.13", + "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", "dev": true, "optional": true, @@ -4407,6 +4827,7 @@ }, "node_modules/encoding/node_modules/iconv-lite": { "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", "dev": true, "optional": true, @@ -4419,6 +4840,7 @@ }, "node_modules/end-of-stream": { "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", "dependencies": { "once": "^1.4.0" @@ -4426,6 +4848,7 @@ }, "node_modules/env-paths": { "version": "2.2.1", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", "dev": true, "engines": { @@ -4434,11 +4857,13 @@ }, "node_modules/err-code": { "version": "2.0.3", + "resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz", "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==", "dev": true }, "node_modules/error-ex": { "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", "dev": true, "dependencies": { @@ -4447,11 +4872,13 @@ }, "node_modules/es6-error": { "version": "4.1.1", + "resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz", "integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==", "dev": true }, "node_modules/escalade": { "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", "engines": { "node": ">=6" @@ -4459,6 +4886,7 @@ }, "node_modules/escape-goat": { "version": "2.1.1", + "resolved": "https://registry.npmjs.org/escape-goat/-/escape-goat-2.1.1.tgz", "integrity": "sha512-8/uIhbG12Csjy2JEW7D9pHbreaVaS/OpN3ycnyvElTdwM5n6GY6W6e2IPemfvGZeUMqZ9A/3GqIZMgKnBhAw/Q==", "dev": true, "engines": { @@ -4467,6 +4895,7 @@ }, "node_modules/escape-string-regexp": { "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", "engines": { "node": ">=0.8.0" @@ -4474,6 +4903,7 @@ }, "node_modules/esprima": { "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", "dev": true, "bin": { @@ -4486,6 +4916,7 @@ }, "node_modules/event-target-shim": { "version": "5.0.1", + "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", "dev": true, "engines": { @@ -4494,6 +4925,7 @@ }, "node_modules/events": { "version": "1.1.1", + "resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz", "integrity": "sha512-kEcvvCBByWXGnZy6JUlgAp2gBIUjfCAV6P6TgT1/aaQKcmuAEC4OZTV1I4EWQLz2gxZw76atuVyvHhTxvi0Flw==", "engines": { "node": ">=0.4.x" @@ -4501,6 +4933,7 @@ }, "node_modules/execa": { "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", "dependencies": { "cross-spawn": "^7.0.3", @@ -4522,6 +4955,7 @@ }, "node_modules/expect": { "version": "28.1.3", + "resolved": "https://registry.npmjs.org/expect/-/expect-28.1.3.tgz", "integrity": "sha512-eEh0xn8HlsuOBxFgIss+2mX85VAS4Qy3OSkjV7rlBWljtA4oWH37glVGyOZSZvErDT/yBywZdPGwCXuTvSG85g==", "dev": true, "dependencies": { @@ -4537,10 +4971,12 @@ }, "node_modules/extend": { "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" }, "node_modules/external-editor": { "version": "3.1.0", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", "dependencies": { "chardet": "^0.7.0", @@ -4553,6 +4989,7 @@ }, "node_modules/external-editor/node_modules/tmp": { "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", "dependencies": { "os-tmpdir": "~1.0.2" @@ -4563,6 +5000,7 @@ }, "node_modules/extsprintf": { "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", "integrity": "sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==", "engines": [ "node >=0.6.0" @@ -4570,10 +5008,12 @@ }, "node_modules/fast-deep-equal": { "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" }, "node_modules/fast-glob": { "version": "3.2.12", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz", "integrity": "sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==", "dev": true, "dependencies": { @@ -4589,15 +5029,18 @@ }, "node_modules/fast-json-stable-stringify": { "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" }, "node_modules/fast-memoize": { "version": "2.5.2", + "resolved": "https://registry.npmjs.org/fast-memoize/-/fast-memoize-2.5.2.tgz", "integrity": "sha512-Ue0LwpDYErFbmNnZSF0UH6eImUwDmogUO1jyE+JbN2gsQz/jICm1Ve7t9QT0rNSsfJt+Hs4/S3GnsDVjL4HVrw==", "dev": true }, "node_modules/fast-redact": { "version": "3.1.2", + "resolved": "https://registry.npmjs.org/fast-redact/-/fast-redact-3.1.2.tgz", "integrity": "sha512-+0em+Iya9fKGfEQGcd62Yv6onjBmmhV1uh86XVfOU8VwAe6kaFdQCWI9s0/Nnugx5Vd9tdbZ7e6gE2tR9dzXdw==", "dev": true, "engines": { @@ -4606,11 +5049,13 @@ }, "node_modules/fast-safe-stringify": { "version": "2.1.1", + "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz", "integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==", "dev": true }, "node_modules/fast-xml-parser": { "version": "3.21.1", + "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-3.21.1.tgz", "integrity": "sha512-FTFVjYoBOZTJekiUsawGsSYV9QL0A+zDYCRj7y34IO6Jg+2IMYEtQa+bbictpdpV8dHxXywqU7C0gRDEOFtBFg==", "dev": true, "dependencies": { @@ -4626,11 +5071,13 @@ }, "node_modules/fastestsmallesttextencoderdecoder": { "version": "1.0.22", + "resolved": "https://registry.npmjs.org/fastestsmallesttextencoderdecoder/-/fastestsmallesttextencoderdecoder-1.0.22.tgz", "integrity": "sha512-Pb8d48e+oIuY4MaM64Cd7OW1gt4nxCHs7/ddPPZ/Ic3sg8yVGM7O9wDvZ7us6ScaUupzM+pfBolwtYhN1IxBIw==", "dev": true }, "node_modules/fastq": { "version": "1.15.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==", "dev": true, "dependencies": { @@ -4639,6 +5086,7 @@ }, "node_modules/fb-watchman": { "version": "2.0.2", + "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz", "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==", "dev": true, "dependencies": { @@ -4647,11 +5095,13 @@ }, "node_modules/figgy-pudding": { "version": "3.5.2", + "resolved": "https://registry.npmjs.org/figgy-pudding/-/figgy-pudding-3.5.2.tgz", "integrity": "sha512-0btnI/H8f2pavGMN8w40mlSKOfTK2SVJmBfBeVIj3kNw0swwgzyRq0d5TJVOwodFmtvpPeWPN/MCcfuWF0Ezbw==", "dev": true }, "node_modules/figures": { "version": "3.2.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", "dependencies": { "escape-string-regexp": "^1.0.5" @@ -4665,6 +5115,7 @@ }, "node_modules/file-type": { "version": "3.9.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-3.9.0.tgz", "integrity": "sha512-RLoqTXE8/vPmMuTI88DAzhMYC99I8BWv7zYP4A1puo5HIjEJ5EX48ighy4ZyKMG9EDXxBgW6e++cn7d1xuFghA==", "dev": true, "engines": { @@ -4673,6 +5124,7 @@ }, "node_modules/fill-keys": { "version": "1.0.2", + "resolved": "https://registry.npmjs.org/fill-keys/-/fill-keys-1.0.2.tgz", "integrity": "sha512-tcgI872xXjwFF4xgQmLxi76GnwJG3g/3isB1l4/G5Z4zrbddGpBjqZCO9oEAcB5wX0Hj/5iQB3toxfO7in1hHA==", "dev": true, "dependencies": { @@ -4685,6 +5137,7 @@ }, "node_modules/fill-range": { "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", "dependencies": { "to-regex-range": "^5.0.1" @@ -4695,6 +5148,7 @@ }, "node_modules/find-cache-dir": { "version": "3.3.2", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.2.tgz", "integrity": "sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==", "dev": true, "dependencies": { @@ -4711,26 +5165,26 @@ }, "node_modules/find-package-json": { "version": "1.2.0", + "resolved": "https://registry.npmjs.org/find-package-json/-/find-package-json-1.2.0.tgz", "integrity": "sha512-+SOGcLGYDJHtyqHd87ysBhmaeQ95oWspDKnMXBrnQ9Eq4OkLNqejgoaD8xVWu6GPa0B6roa6KinCMEMcVeqONw==", "dev": true }, "node_modules/find-up": { - "version": "5.0.0", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", "dev": true, "dependencies": { - "locate-path": "^6.0.0", + "locate-path": "^5.0.0", "path-exists": "^4.0.0" }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=8" } }, "node_modules/flat": { "version": "5.0.2", + "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", "dev": true, "bin": { @@ -4739,16 +5193,19 @@ }, "node_modules/flatstr": { "version": "1.0.12", + "resolved": "https://registry.npmjs.org/flatstr/-/flatstr-1.0.12.tgz", "integrity": "sha512-4zPxDyhCyiN2wIAtSLI6gc82/EjqZc1onI4Mz/l0pWrAlsSfYH/2ZIcU+e3oA2wDwbzIWNKwa23F8rh6+DRWkw==", "dev": true }, "node_modules/fnv-plus": { "version": "1.3.1", + "resolved": "https://registry.npmjs.org/fnv-plus/-/fnv-plus-1.3.1.tgz", "integrity": "sha512-Gz1EvfOneuFfk4yG458dJ3TLJ7gV19q3OM/vVvvHf7eT02Hm1DleB4edsia6ahbKgAYxO9gvyQ1ioWZR+a00Yw==", "dev": true }, "node_modules/folder-hash": { "version": "4.0.4", + "resolved": "https://registry.npmjs.org/folder-hash/-/folder-hash-4.0.4.tgz", "integrity": "sha512-zEyYH+UsHEfJJcCRSf9ai5I4CTZwZ8ObONRuEI5hcEmJY5pS0FUWKruX9mMnYJrgC7MlPFDYnGsK1R+WFYjLlQ==", "dependencies": { "debug": "^4.3.3", @@ -4763,6 +5220,7 @@ }, "node_modules/folder-hash/node_modules/brace-expansion": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", "dependencies": { "balanced-match": "^1.0.0" @@ -4770,6 +5228,7 @@ }, "node_modules/folder-hash/node_modules/minimatch": { "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", "dependencies": { "brace-expansion": "^2.0.1" @@ -4780,6 +5239,7 @@ }, "node_modules/follow-redirects": { "version": "1.15.2", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz", "integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==", "funding": [ { @@ -4798,6 +5258,7 @@ }, "node_modules/for-each": { "version": "0.3.3", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", "dependencies": { "is-callable": "^1.1.3" @@ -4805,11 +5266,13 @@ }, "node_modules/foreach": { "version": "2.0.6", + "resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.6.tgz", "integrity": "sha512-k6GAGDyqLe9JaebCsFCoudPPWfihKu8pylYXRlqP1J7ms39iPoTtk2fviNglIeQEwdh0bQeKJ01ZPyuyQvKzwg==", "dev": true }, "node_modules/foreground-child": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-2.0.0.tgz", "integrity": "sha512-dCIq9FpEcyQyXKCkyzmlPTFNgrCzPudOe+mhvJU5zAtlBnGVy2yKxtfsxK2tQBThwq225jcvBjpw1Gr40uzZCA==", "dev": true, "dependencies": { @@ -4822,6 +5285,7 @@ }, "node_modules/forever-agent": { "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", "integrity": "sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==", "engines": { "node": "*" @@ -4829,6 +5293,7 @@ }, "node_modules/form-data": { "version": "2.3.3", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", "dependencies": { "asynckit": "^0.4.0", @@ -4841,11 +5306,13 @@ }, "node_modules/format-util": { "version": "1.0.5", + "resolved": "https://registry.npmjs.org/format-util/-/format-util-1.0.5.tgz", "integrity": "sha512-varLbTj0e0yVyRpqQhuWV+8hlePAgaoFRhNFj50BNjEIrw1/DphHSObtqwskVCPWNgzwPoQrZAbfa/SBiicNeg==", "dev": true }, "node_modules/fp-and-or": { "version": "0.1.3", + "resolved": "https://registry.npmjs.org/fp-and-or/-/fp-and-or-0.1.3.tgz", "integrity": "sha512-wJaE62fLaB3jCYvY2ZHjZvmKK2iiLiiehX38rz5QZxtdN8fVPJDeZUiVvJrHStdTc+23LHlyZuSEKgFc0pxi2g==", "dev": true, "engines": { @@ -4854,11 +5321,13 @@ }, "node_modules/fp-ts": { "version": "2.13.1", + "resolved": "https://registry.npmjs.org/fp-ts/-/fp-ts-2.13.1.tgz", "integrity": "sha512-0eu5ULPS2c/jsa1lGFneEFFEdTbembJv8e4QKXeVJ3lm/5hyve06dlKZrpxmMwJt6rYen7sxmHHK2CLaXvWuWQ==", "dev": true }, "node_modules/fromentries": { "version": "1.3.2", + "resolved": "https://registry.npmjs.org/fromentries/-/fromentries-1.3.2.tgz", "integrity": "sha512-cHEpEQHUg0f8XdtZCc2ZAhrHzKzT0MrFUTcvx+hfxYu7rGMDc5SKoXFh+n4YigxsHXRzc6OrCshdR1bWH6HHyg==", "dev": true, "funding": [ @@ -4878,10 +5347,12 @@ }, "node_modules/fs-constants": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" }, "node_modules/fs-extra": { "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", "dependencies": { "graceful-fs": "^4.2.0", @@ -4894,6 +5365,7 @@ }, "node_modules/fs-minipass": { "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", "dev": true, "dependencies": { @@ -4905,10 +5377,12 @@ }, "node_modules/fs.realpath": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" }, "node_modules/fsevents": { "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", "hasInstallScript": true, "optional": true, @@ -4921,6 +5395,7 @@ }, "node_modules/fstream": { "version": "1.0.12", + "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.12.tgz", "integrity": "sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg==", "dev": true, "dependencies": { @@ -4935,6 +5410,7 @@ }, "node_modules/fstream/node_modules/rimraf": { "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", "dev": true, "dependencies": { @@ -4946,10 +5422,12 @@ }, "node_modules/function-bind": { "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" }, "node_modules/gauge": { "version": "4.0.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-4.0.4.tgz", "integrity": "sha512-f9m+BEN5jkg6a0fZjleidjN51VE1X+mPFQ2DJ0uv1V39oCLCbsGe6yjbBnp7eK7z/+GAon99a3nHuqbuuthyPg==", "dev": true, "dependencies": { @@ -4968,6 +5446,7 @@ }, "node_modules/gensync": { "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", "dev": true, "engines": { @@ -4976,6 +5455,7 @@ }, "node_modules/get-caller-file": { "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", "engines": { "node": "6.* || 8.* || >= 10.*" @@ -4983,6 +5463,7 @@ }, "node_modules/get-func-name": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz", "integrity": "sha512-Hm0ixYtaSZ/V7C8FJrtZIuBBI+iSgL+1Aq82zSu8VQNB4S3Gk8e7Qs3VwBDJAhmRZcFqkl3tQu36g/Foh5I5ig==", "dev": true, "engines": { @@ -4991,6 +5472,7 @@ }, "node_modules/get-intrinsic": { "version": "1.2.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.0.tgz", "integrity": "sha512-L049y6nFOuom5wGyRc3/gdTLO94dySVKRACj1RmJZBQXlbTMhtNIgkWkUHq+jYmZvKf14EW1EoJnnjbmoHij0Q==", "dependencies": { "function-bind": "^1.1.1", @@ -5003,6 +5485,7 @@ }, "node_modules/get-package-type": { "version": "0.1.0", + "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", "dev": true, "engines": { @@ -5011,6 +5494,7 @@ }, "node_modules/get-pkg-repo": { "version": "4.2.1", + "resolved": "https://registry.npmjs.org/get-pkg-repo/-/get-pkg-repo-4.2.1.tgz", "integrity": "sha512-2+QbHjFRfGB74v/pYWjd5OhU3TDIC2Gv/YKUTk/tCvAz0pkn/Mz6P3uByuBimLOcPvN2jYdScl3xGFSrx0jEcA==", "dev": true, "dependencies": { @@ -5028,6 +5512,7 @@ }, "node_modules/get-pkg-repo/node_modules/cliui": { "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", "dev": true, "dependencies": { @@ -5037,8 +5522,9 @@ } }, "node_modules/get-pkg-repo/node_modules/readable-stream": { - "version": "2.3.7", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", "dev": true, "dependencies": { "core-util-is": "~1.0.0", @@ -5052,19 +5538,13 @@ }, "node_modules/get-pkg-repo/node_modules/safe-buffer": { "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", "dev": true }, - "node_modules/get-pkg-repo/node_modules/string_decoder": { - "version": "1.1.1", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, "node_modules/get-pkg-repo/node_modules/through2": { "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", "dev": true, "dependencies": { @@ -5074,6 +5554,7 @@ }, "node_modules/get-pkg-repo/node_modules/yargs": { "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", "dev": true, "dependencies": { @@ -5091,6 +5572,7 @@ }, "node_modules/get-stdin": { "version": "8.0.0", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-8.0.0.tgz", "integrity": "sha512-sY22aA6xchAzprjyqmSEQv4UbAAzRN0L2dQB0NlN5acTTK9Don6nhoc3eAbUnpZiCANAMfd/+40kVdKfFygohg==", "dev": true, "engines": { @@ -5102,6 +5584,7 @@ }, "node_modules/get-stream": { "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", "engines": { "node": ">=10" @@ -5112,6 +5595,7 @@ }, "node_modules/getpass": { "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", "integrity": "sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==", "dependencies": { "assert-plus": "^1.0.0" @@ -5119,6 +5603,7 @@ }, "node_modules/git-raw-commits": { "version": "2.0.11", + "resolved": "https://registry.npmjs.org/git-raw-commits/-/git-raw-commits-2.0.11.tgz", "integrity": "sha512-VnctFhw+xfj8Va1xtfEqCUD2XDrbAPSJx+hSrE5K7fGdjZruW7XV+QOrN7LF/RJyvspRiD2I0asWsxFp0ya26A==", "dev": true, "dependencies": { @@ -5137,6 +5622,7 @@ }, "node_modules/git-remote-origin-url": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/git-remote-origin-url/-/git-remote-origin-url-2.0.0.tgz", "integrity": "sha512-eU+GGrZgccNJcsDH5LkXR3PB9M958hxc7sbA8DFJjrv9j4L2P/eZfKhM+QD6wyzpiv+b1BpK0XrYCxkovtjSLw==", "dev": true, "dependencies": { @@ -5149,6 +5635,7 @@ }, "node_modules/git-remote-origin-url/node_modules/pify": { "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", "dev": true, "engines": { @@ -5157,6 +5644,7 @@ }, "node_modules/git-semver-tags": { "version": "4.1.1", + "resolved": "https://registry.npmjs.org/git-semver-tags/-/git-semver-tags-4.1.1.tgz", "integrity": "sha512-OWyMt5zBe7xFs8vglMmhM9lRQzCWL3WjHtxNNfJTMngGym7pC1kh8sP6jevfydJ6LP3ZvGxfb6ABYgPUM0mtsA==", "dev": true, "dependencies": { @@ -5172,6 +5660,7 @@ }, "node_modules/git-semver-tags/node_modules/semver": { "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", "dev": true, "bin": { @@ -5180,6 +5669,7 @@ }, "node_modules/gitconfiglocal": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/gitconfiglocal/-/gitconfiglocal-1.0.0.tgz", "integrity": "sha512-spLUXeTAVHxDtKsJc8FkFVgFtMdEN9qPGpL23VfSHx4fP4+Ds097IXLvymbnDH8FnmxX5Nr9bPw3A+AQ6mWEaQ==", "dev": true, "dependencies": { @@ -5188,6 +5678,7 @@ }, "node_modules/glob": { "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", "dependencies": { "fs.realpath": "^1.0.0", @@ -5206,6 +5697,7 @@ }, "node_modules/glob-parent": { "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", "dependencies": { "is-glob": "^4.0.1" @@ -5216,6 +5708,7 @@ }, "node_modules/global-dirs": { "version": "0.1.1", + "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-0.1.1.tgz", "integrity": "sha512-NknMLn7F2J7aflwFOlGdNIuCDpN3VGoSoB+aap3KABFWbHVn1TCgFC+np23J8W2BiZbjfEw3BFBycSMv1AFblg==", "dev": true, "dependencies": { @@ -5227,6 +5720,7 @@ }, "node_modules/globals": { "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", "dev": true, "engines": { @@ -5235,6 +5729,7 @@ }, "node_modules/globby": { "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", "dev": true, "dependencies": { @@ -5254,6 +5749,7 @@ }, "node_modules/gopd": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", "dependencies": { "get-intrinsic": "^1.1.3" @@ -5264,6 +5760,7 @@ }, "node_modules/got": { "version": "9.6.0", + "resolved": "https://registry.npmjs.org/got/-/got-9.6.0.tgz", "integrity": "sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q==", "dev": true, "dependencies": { @@ -5285,6 +5782,7 @@ }, "node_modules/got/node_modules/get-stream": { "version": "4.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", "dev": true, "dependencies": { @@ -5296,10 +5794,12 @@ }, "node_modules/graceful-fs": { "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" }, "node_modules/growl": { "version": "1.10.5", + "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", "dev": true, "engines": { @@ -5308,6 +5808,7 @@ }, "node_modules/handlebars": { "version": "4.7.7", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.7.tgz", "integrity": "sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA==", "dev": true, "dependencies": { @@ -5328,11 +5829,13 @@ }, "node_modules/handler-agent": { "version": "0.2.0", + "resolved": "https://registry.npmjs.org/handler-agent/-/handler-agent-0.2.0.tgz", "integrity": "sha512-cUduQxa5p3TFtGmb55mrRbkk/3EJCsLSeFrCIuTakQHQlYVWXeW2L9IUQUHyoHLI4UgpBNaN2JrZ0He1jPu+vg==", "dev": true }, "node_modules/har-schema": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", "integrity": "sha512-Oqluz6zhGX8cyRaTQlFMPw80bSJVG2x/cFb8ZPhUILGgHka9SsokCCOQgpveePerqidZOrT14ipqfJb7ILcW5Q==", "engines": { "node": ">=4" @@ -5340,6 +5843,7 @@ }, "node_modules/har-validator": { "version": "5.1.5", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", "deprecated": "this library is no longer supported", "dependencies": { @@ -5352,6 +5856,7 @@ }, "node_modules/har-validator/node_modules/ajv": { "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "dependencies": { "fast-deep-equal": "^3.1.1", @@ -5366,10 +5871,12 @@ }, "node_modules/har-validator/node_modules/json-schema-traverse": { "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" }, "node_modules/hard-rejection": { "version": "2.1.0", + "resolved": "https://registry.npmjs.org/hard-rejection/-/hard-rejection-2.1.0.tgz", "integrity": "sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==", "dev": true, "engines": { @@ -5378,6 +5885,7 @@ }, "node_modules/has": { "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", "dependencies": { "function-bind": "^1.1.1" @@ -5388,6 +5896,7 @@ }, "node_modules/has-ansi": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", "integrity": "sha512-C8vBJ8DwUCx19vhm7urhTuUsr4/IyP6l4VzNQDv+ryHQObW3TTTp9yB68WpYgRe2bbaGuZ/se74IqFeVnMnLZg==", "dependencies": { "ansi-regex": "^2.0.0" @@ -5398,6 +5907,7 @@ }, "node_modules/has-ansi/node_modules/ansi-regex": { "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", "engines": { "node": ">=0.10.0" @@ -5405,6 +5915,7 @@ }, "node_modules/has-flag": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "engines": { "node": ">=8" @@ -5412,6 +5923,7 @@ }, "node_modules/has-symbols": { "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", "engines": { "node": ">= 0.4" @@ -5422,6 +5934,7 @@ }, "node_modules/has-tostringtag": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", "dependencies": { "has-symbols": "^1.0.2" @@ -5435,11 +5948,13 @@ }, "node_modules/has-unicode": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==", "dev": true }, "node_modules/has-yarn": { "version": "2.1.0", + "resolved": "https://registry.npmjs.org/has-yarn/-/has-yarn-2.1.0.tgz", "integrity": "sha512-UqBRqi4ju7T+TqGNdqAO0PaSVGsDGJUBQvk9eUWNGRY1CFGDzYhLWoM7JQEemnlvVcv/YEmc2wNW8BC24EnUsw==", "dev": true, "engines": { @@ -5448,6 +5963,7 @@ }, "node_modules/hasha": { "version": "5.2.2", + "resolved": "https://registry.npmjs.org/hasha/-/hasha-5.2.2.tgz", "integrity": "sha512-Hrp5vIK/xr5SkeN2onO32H0MgNZ0f17HRNH39WfL0SYUNOTZ5Lz1TJ8Pajo/87dYGEFlLMm7mIc/k/s6Bvz9HQ==", "dev": true, "dependencies": { @@ -5463,6 +5979,7 @@ }, "node_modules/hasha/node_modules/type-fest": { "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", "dev": true, "engines": { @@ -5471,6 +5988,7 @@ }, "node_modules/he": { "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", "dev": true, "bin": { @@ -5479,6 +5997,7 @@ }, "node_modules/hosted-git-info": { "version": "4.1.0", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz", "integrity": "sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==", "dev": true, "dependencies": { @@ -5488,34 +6007,21 @@ "node": ">=10" } }, - "node_modules/hosted-git-info/node_modules/lru-cache": { - "version": "6.0.0", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/hosted-git-info/node_modules/yallist": { - "version": "4.0.0", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, "node_modules/html-escaper": { "version": "2.0.2", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", "dev": true }, "node_modules/http-cache-semantics": { - "version": "4.1.0", - "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", + "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==", "dev": true }, "node_modules/http-proxy-agent": { "version": "5.0.0", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", "dev": true, "dependencies": { @@ -5529,11 +6035,13 @@ }, "node_modules/http-reasons": { "version": "0.1.0", + "resolved": "https://registry.npmjs.org/http-reasons/-/http-reasons-0.1.0.tgz", "integrity": "sha512-P6kYh0lKZ+y29T2Gqz+RlC9WBLhKe8kDmcJ+A+611jFfxdPsbMRQ5aNmFRM3lENqFkK+HTTL+tlQviAiv0AbLQ==", "dev": true }, "node_modules/http-signature": { "version": "1.2.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", "integrity": "sha512-CAbnr6Rz4CYQkLYUtSNXxQPUH2gK8f3iWexVlsnMeD+GjlsQ0Xsy1cOX+mN3dtxYomRy21CiOzU8Uhw6OwncEQ==", "dependencies": { "assert-plus": "^1.0.0", @@ -5547,6 +6055,7 @@ }, "node_modules/https-proxy-agent": { "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", "dev": true, "dependencies": { @@ -5559,6 +6068,7 @@ }, "node_modules/human-signals": { "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", "engines": { "node": ">=10.17.0" @@ -5566,6 +6076,7 @@ }, "node_modules/humanize-ms": { "version": "1.2.1", + "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", "integrity": "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==", "dev": true, "dependencies": { @@ -5574,6 +6085,7 @@ }, "node_modules/husky": { "version": "7.0.4", + "resolved": "https://registry.npmjs.org/husky/-/husky-7.0.4.tgz", "integrity": "sha512-vbaCKN2QLtP/vD4yvs6iz6hBEo6wkSzs8HpRah1Z6aGmF2KW5PdYuAd7uX5a+OyBZHBhd+TFLqgjUgytQr4RvQ==", "dev": true, "bin": { @@ -5588,6 +6100,7 @@ }, "node_modules/iconv-lite": { "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", "dependencies": { "safer-buffer": ">= 2.1.2 < 3" @@ -5597,11 +6110,27 @@ } }, "node_modules/ieee754": { - "version": "1.1.13", - "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==" + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] }, "node_modules/ignore": { "version": "5.2.4", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", "dev": true, "engines": { @@ -5610,10 +6139,12 @@ }, "node_modules/ignore-by-default": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz", "integrity": "sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==" }, "node_modules/ignore-walk": { "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-5.0.1.tgz", "integrity": "sha512-yemi4pMf51WKT7khInJqAvsIGzoqYXblnsz0ql8tM+yi1EKYTY1evX4NAbJrLL/Aanr2HyZeluqU+Oi7MGHokw==", "dev": true, "dependencies": { @@ -5625,6 +6156,7 @@ }, "node_modules/ignore-walk/node_modules/brace-expansion": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", "dev": true, "dependencies": { @@ -5633,6 +6165,7 @@ }, "node_modules/ignore-walk/node_modules/minimatch": { "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", "dev": true, "dependencies": { @@ -5644,10 +6177,12 @@ }, "node_modules/immutable": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.0.0.tgz", "integrity": "sha512-zIE9hX70qew5qTUjSS7wi1iwj/l7+m54KWU247nhM3v806UdGj1yDndXj+IOYxxtW9zyLI+xqFNZjTuDaLUqFw==" }, "node_modules/import-fresh": { "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", "dev": true, "dependencies": { @@ -5663,6 +6198,7 @@ }, "node_modules/import-fresh/node_modules/resolve-from": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", "dev": true, "engines": { @@ -5671,6 +6207,7 @@ }, "node_modules/import-lazy": { "version": "2.1.0", + "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-2.1.0.tgz", "integrity": "sha512-m7ZEHgtw69qOGw+jwxXkHlrlIPdTGkyh66zXZ1ajZbxkDBNjSY/LGbmjc7h0s2ELsUDTAhFr55TrPSSqJGPG0A==", "dev": true, "engines": { @@ -5679,6 +6216,7 @@ }, "node_modules/imurmurhash": { "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", "dev": true, "engines": { @@ -5686,19 +6224,22 @@ } }, "node_modules/indent-string": { - "version": "3.2.0", - "integrity": "sha512-BYqTHXTGUIvg7t1r4sJNKcbDZkL92nkXA8YtRpbjFHRHGDL/NtUeiBJMeE60kIFN/Mg8ESaWQvftaYMGJzQZCQ==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", "engines": { - "node": ">=4" + "node": ">=8" } }, "node_modules/infer-owner": { "version": "1.0.4", + "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz", "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==", "dev": true }, "node_modules/inflight": { "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", "dependencies": { "once": "^1.3.0", @@ -5707,15 +6248,18 @@ }, "node_modules/inherits": { "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" }, "node_modules/ini": { "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", "dev": true }, "node_modules/inquirer": { "version": "8.2.5", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-8.2.5.tgz", "integrity": "sha512-QAgPDQMEgrDssk1XiwwHoOGYF9BAbUcc1+j+FhEvaOt8/cKRqyLn0U5qA6F74fGhTMGxf92pOvPBeh29jQJDTQ==", "dependencies": { "ansi-escapes": "^4.2.1", @@ -5740,6 +6284,7 @@ }, "node_modules/inquirer/node_modules/chalk": { "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dependencies": { "ansi-styles": "^4.1.0", @@ -5752,22 +6297,9 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/inquirer/node_modules/log-symbols": { - "version": "4.1.0", - "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", - "dependencies": { - "chalk": "^4.1.0", - "is-unicode-supported": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/inquirer/node_modules/ora": { "version": "5.4.1", + "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==", "dependencies": { "bl": "^4.1.0", @@ -5789,11 +6321,13 @@ }, "node_modules/insync": { "version": "2.1.1", + "resolved": "https://registry.npmjs.org/insync/-/insync-2.1.1.tgz", "integrity": "sha512-UzUhOZFpCMM22Xlig9iUPqalf8n7c4eYScamce1C+jN3ad8FtmVm42ryMwVq0hAxHbwUhWFhPvTFQQpFdDUKkw==", "dev": true }, "node_modules/io-ts": { "version": "2.2.20", + "resolved": "https://registry.npmjs.org/io-ts/-/io-ts-2.2.20.tgz", "integrity": "sha512-Rq2BsYmtwS5vVttie4rqrOCIfHCS9TgpRLFpKQCM1wZBBRY9nWVGmEvm2FnDbSE2un1UE39DvFpTR5UL47YDcA==", "dev": true, "peerDependencies": { @@ -5802,11 +6336,13 @@ }, "node_modules/ip": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ip/-/ip-2.0.0.tgz", "integrity": "sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==", "dev": true }, "node_modules/is-arguments": { "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", "dependencies": { "call-bind": "^1.0.2", @@ -5821,11 +6357,13 @@ }, "node_modules/is-arrayish": { "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", "dev": true }, "node_modules/is-binary-path": { "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", "dependencies": { "binary-extensions": "^2.0.0" @@ -5836,6 +6374,7 @@ }, "node_modules/is-callable": { "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", "engines": { "node": ">= 0.4" @@ -5846,6 +6385,7 @@ }, "node_modules/is-ci": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz", "integrity": "sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==", "dev": true, "dependencies": { @@ -5857,11 +6397,13 @@ }, "node_modules/is-ci/node_modules/ci-info": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==", "dev": true }, "node_modules/is-core-module": { "version": "2.11.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.11.0.tgz", "integrity": "sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==", "dependencies": { "has": "^1.0.3" @@ -5872,6 +6414,7 @@ }, "node_modules/is-docker": { "version": "2.2.1", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", "bin": { "is-docker": "cli.js" @@ -5885,23 +6428,23 @@ }, "node_modules/is-extglob": { "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", "engines": { "node": ">=0.10.0" } }, "node_modules/is-fullwidth-code-point": { - "version": "4.0.0", - "integrity": "sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=8" } }, "node_modules/is-generator-function": { "version": "1.0.10", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", "dependencies": { "has-tostringtag": "^1.0.0" @@ -5915,6 +6458,7 @@ }, "node_modules/is-glob": { "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", "dependencies": { "is-extglob": "^2.1.1" @@ -5925,6 +6469,7 @@ }, "node_modules/is-installed-globally": { "version": "0.4.0", + "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.4.0.tgz", "integrity": "sha512-iwGqO3J21aaSkC7jWnHP/difazwS7SFeIqxv6wEtLU8Y5KlzFTjyqcSIT0d8s4+dDhKytsk9PJZ2BkS5eZwQRQ==", "dev": true, "dependencies": { @@ -5940,6 +6485,7 @@ }, "node_modules/is-installed-globally/node_modules/global-dirs": { "version": "3.0.1", + "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-3.0.1.tgz", "integrity": "sha512-NBcGGFbBA9s1VzD41QXDG+3++t9Mn5t1FpLdhESY6oKY4gYTFpX4wO3sqGUa0Srjtbfj3szX0RnemmrVRUdULA==", "dev": true, "dependencies": { @@ -5954,6 +6500,7 @@ }, "node_modules/is-installed-globally/node_modules/ini": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ini/-/ini-2.0.0.tgz", "integrity": "sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA==", "dev": true, "engines": { @@ -5962,6 +6509,7 @@ }, "node_modules/is-interactive": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==", "engines": { "node": ">=8" @@ -5969,11 +6517,13 @@ }, "node_modules/is-lambda": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-lambda/-/is-lambda-1.0.1.tgz", "integrity": "sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==", "dev": true }, "node_modules/is-npm": { "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-5.0.0.tgz", "integrity": "sha512-WW/rQLOazUq+ST/bCAVBp/2oMERWLsR7OrKyt052dNDk4DHcDE0/7QSXITlmi+VBcV13DfIbysG3tZJm5RfdBA==", "dev": true, "engines": { @@ -5985,6 +6535,7 @@ }, "node_modules/is-number": { "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "engines": { "node": ">=0.12.0" @@ -5992,6 +6543,7 @@ }, "node_modules/is-number-like": { "version": "1.0.8", + "resolved": "https://registry.npmjs.org/is-number-like/-/is-number-like-1.0.8.tgz", "integrity": "sha512-6rZi3ezCyFcn5L71ywzz2bS5b2Igl1En3eTlZlvKjpz1n3IZLAYMbKYAIQgFmEu0GENg92ziU/faEOA/aixjbA==", "dependencies": { "lodash.isfinite": "^3.3.2" @@ -5999,6 +6551,7 @@ }, "node_modules/is-obj": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", "dev": true, "engines": { @@ -6007,6 +6560,7 @@ }, "node_modules/is-object": { "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-object/-/is-object-1.0.2.tgz", "integrity": "sha512-2rRIahhZr2UWb45fIOuvZGpFtz0TyOZLf32KxBbSoUCeZR495zCKlWUKKUByk3geS2eAs7ZAABt0Y/Rx0GiQGA==", "dev": true, "funding": { @@ -6015,6 +6569,7 @@ }, "node_modules/is-observable": { "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-observable/-/is-observable-1.1.0.tgz", "integrity": "sha512-NqCa4Sa2d+u7BWc6CukaObG3Fh+CU9bvixbpcXYhy2VvYS7vVGIdAgnIS5Ks3A/cqk4rebLJ9s8zBstT2aKnIA==", "dependencies": { "symbol-observable": "^1.1.0" @@ -6025,6 +6580,7 @@ }, "node_modules/is-path-inside": { "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", "dev": true, "engines": { @@ -6033,6 +6589,7 @@ }, "node_modules/is-plain-obj": { "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", "integrity": "sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==", "dev": true, "engines": { @@ -6041,10 +6598,12 @@ }, "node_modules/is-promise": { "version": "2.2.2", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.2.2.tgz", "integrity": "sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==" }, "node_modules/is-stream": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", "engines": { "node": ">=8" @@ -6055,6 +6614,7 @@ }, "node_modules/is-text-path": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-text-path/-/is-text-path-1.0.1.tgz", "integrity": "sha512-xFuJpne9oFz5qDaodwmmG08e3CawH/2ZV8Qqza1Ko7Sk8POWbkRdwIoAWVhqvq0XeUzANEhKo2n0IXUGBm7A/w==", "dev": true, "dependencies": { @@ -6066,6 +6626,7 @@ }, "node_modules/is-typed-array": { "version": "1.1.10", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.10.tgz", "integrity": "sha512-PJqgEHiWZvMpaFZ3uTc8kHPM4+4ADTlDniuQL7cU/UDA0Ql7F70yGfHph3cLNe+c9toaigv+DFzTJKhc2CtO6A==", "dependencies": { "available-typed-arrays": "^1.0.5", @@ -6083,10 +6644,12 @@ }, "node_modules/is-typedarray": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==" }, "node_modules/is-unicode-supported": { "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", "engines": { "node": ">=10" @@ -6097,6 +6660,7 @@ }, "node_modules/is-windows": { "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", "dev": true, "engines": { @@ -6105,6 +6669,7 @@ }, "node_modules/is-wsl": { "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", "dependencies": { "is-docker": "^2.0.0" @@ -6115,19 +6680,23 @@ }, "node_modules/is-yarn-global": { "version": "0.3.0", + "resolved": "https://registry.npmjs.org/is-yarn-global/-/is-yarn-global-0.3.0.tgz", "integrity": "sha512-VjSeb/lHmkoyd8ryPVIKvOCn4D1koMqY+vqyjjUfc3xyKtP4dYOxM44sZrnqQSzSds3xyOrUTLTC9LVCVgLngw==", "dev": true }, "node_modules/isarray": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" }, "node_modules/isexe": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" }, "node_modules/isomorphic-fetch": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/isomorphic-fetch/-/isomorphic-fetch-3.0.0.tgz", "integrity": "sha512-qvUtwJ3j6qwsF3jLxkZ72qCgjMysPzDfeV240JHiGZsANBYd+EEuu35v7dfrJ9Up0Ak07D7GGSkGhCHTqg/5wA==", "dev": true, "dependencies": { @@ -6137,10 +6706,12 @@ }, "node_modules/isstream": { "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", "integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==" }, "node_modules/istanbul-lib-coverage": { "version": "3.2.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz", "integrity": "sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==", "dev": true, "engines": { @@ -6149,6 +6720,7 @@ }, "node_modules/istanbul-lib-hook": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-hook/-/istanbul-lib-hook-3.0.0.tgz", "integrity": "sha512-Pt/uge1Q9s+5VAZ+pCo16TYMWPBIl+oaNIjgLQxcX0itS6ueeaA+pEfThZpH8WxhFgCiEb8sAJY6MdUKgiIWaQ==", "dev": true, "dependencies": { @@ -6160,6 +6732,7 @@ }, "node_modules/istanbul-lib-instrument": { "version": "5.2.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", "dev": true, "dependencies": { @@ -6175,6 +6748,7 @@ }, "node_modules/istanbul-lib-instrument/node_modules/semver": { "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", "dev": true, "bin": { @@ -6183,6 +6757,7 @@ }, "node_modules/istanbul-lib-processinfo": { "version": "2.0.3", + "resolved": "https://registry.npmjs.org/istanbul-lib-processinfo/-/istanbul-lib-processinfo-2.0.3.tgz", "integrity": "sha512-NkwHbo3E00oybX6NGJi6ar0B29vxyvNwoC7eJ4G4Yq28UfY758Hgn/heV8VRFhevPED4LXfFz0DQ8z/0kw9zMg==", "dev": true, "dependencies": { @@ -6199,6 +6774,7 @@ }, "node_modules/istanbul-lib-processinfo/node_modules/p-map": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-3.0.0.tgz", "integrity": "sha512-d3qXVTF/s+W+CdJ5A29wywV2n8CQQYahlgz2bFiA+4eVNJbHJodPZ+/gXwPGh0bOqA+j8S+6+ckmvLGPk1QpxQ==", "dev": true, "dependencies": { @@ -6210,6 +6786,7 @@ }, "node_modules/istanbul-lib-report": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", "integrity": "sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw==", "dev": true, "dependencies": { @@ -6223,6 +6800,7 @@ }, "node_modules/istanbul-lib-source-maps": { "version": "4.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", "dev": true, "dependencies": { @@ -6236,6 +6814,7 @@ }, "node_modules/istanbul-reports": { "version": "3.1.5", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.5.tgz", "integrity": "sha512-nUsEMa9pBt/NOHqbcbeJEgqIlY/K7rVWUX6Lql2orY5e9roQOthbR3vtY4zzf2orPELg80fnxxk9zUyPlgwD1w==", "dev": true, "dependencies": { @@ -6248,6 +6827,7 @@ }, "node_modules/jest-diff": { "version": "28.1.3", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-28.1.3.tgz", "integrity": "sha512-8RqP1B/OXzjjTWkqMX67iqgwBVJRgCyKD3L9nq+6ZqJMdvjE8RgHktqZ6jNrkdMT+dJuYNI3rhQpxaz7drJHfw==", "dev": true, "dependencies": { @@ -6262,6 +6842,7 @@ }, "node_modules/jest-get-type": { "version": "28.0.2", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-28.0.2.tgz", "integrity": "sha512-ioj2w9/DxSYHfOm5lJKCdcAmPJzQXmbM/Url3rhlghrPvT3tt+7a/+oXc9azkKmLvoiXjtV83bEWqi+vs5nlPA==", "dev": true, "engines": { @@ -6270,6 +6851,7 @@ }, "node_modules/jest-haste-map": { "version": "28.1.3", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-28.1.3.tgz", "integrity": "sha512-3S+RQWDXccXDKSWnkHa/dPwt+2qwA8CJzR61w3FoYCvoo3Pn8tvGcysmMF0Bj0EX5RYvAI2EIvC57OmotfdtKA==", "dev": true, "dependencies": { @@ -6294,6 +6876,7 @@ }, "node_modules/jest-matcher-utils": { "version": "28.1.3", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-28.1.3.tgz", "integrity": "sha512-kQeJ7qHemKfbzKoGjHHrRKH6atgxMk8Enkk2iPQ3XwO6oE/KYD8lMYOziCkeSB9G4adPM4nR1DE8Tf5JeWH6Bw==", "dev": true, "dependencies": { @@ -6308,6 +6891,7 @@ }, "node_modules/jest-message-util": { "version": "28.1.3", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-28.1.3.tgz", "integrity": "sha512-PFdn9Iewbt575zKPf1286Ht9EPoJmYT7P0kY+RibeYZ2XtOr53pDLEFoTWXbd1h4JiGiWpTBC84fc8xMXQMb7g==", "dev": true, "dependencies": { @@ -6327,6 +6911,7 @@ }, "node_modules/jest-regex-util": { "version": "28.0.2", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-28.0.2.tgz", "integrity": "sha512-4s0IgyNIy0y9FK+cjoVYoxamT7Zeo7MhzqRGx7YDYmaQn1wucY9rotiGkBzzcMXTtjrCAP/f7f+E0F7+fxPNdw==", "dev": true, "engines": { @@ -6335,6 +6920,7 @@ }, "node_modules/jest-snapshot": { "version": "28.1.3", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-28.1.3.tgz", "integrity": "sha512-4lzMgtiNlc3DU/8lZfmqxN3AYD6GGLbl+72rdBpXvcV+whX7mDrREzkPdp2RnmfIiWBg1YbuFSkXduF2JcafJg==", "dev": true, "dependencies": { @@ -6368,6 +6954,7 @@ }, "node_modules/jest-util": { "version": "28.1.3", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-28.1.3.tgz", "integrity": "sha512-XdqfpHwpcSRko/C35uLYFM2emRAltIIKZiJ9eAmhjsj0CqZMa0p1ib0R5fWIqGhn1a103DebTbpqIaP1qCQ6tQ==", "dev": true, "dependencies": { @@ -6384,6 +6971,7 @@ }, "node_modules/jest-worker": { "version": "28.1.3", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-28.1.3.tgz", "integrity": "sha512-CqRA220YV/6jCo8VWvAt1KKx6eek1VIHMPeLEbpcfSfkEeWyBNppynM/o6q+Wmw+sOhos2ml34wZbSX3G13//g==", "dev": true, "dependencies": { @@ -6397,6 +6985,7 @@ }, "node_modules/jest-worker/node_modules/supports-color": { "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", "dev": true, "dependencies": { @@ -6411,11 +7000,13 @@ }, "node_modules/jju": { "version": "1.4.0", + "resolved": "https://registry.npmjs.org/jju/-/jju-1.4.0.tgz", "integrity": "sha512-8wb9Yw966OSxApiCt0K3yNJL8pnNeIv+OEq2YMidz4FKP6nonSRoOXc80iXY4JaN2FC11B9qsNmDsm+ZOfMROA==", "dev": true }, "node_modules/jmespath": { "version": "0.16.0", + "resolved": "https://registry.npmjs.org/jmespath/-/jmespath-0.16.0.tgz", "integrity": "sha512-9FzQjJ7MATs1tSpnco1K6ayiYE3figslrXA72G2HQ/n76RzvYlofyi5QM+iX4YRs/pu3yzxlVQSST23+dMDknw==", "engines": { "node": ">= 0.6.0" @@ -6423,11 +7014,13 @@ }, "node_modules/js-tokens": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", "dev": true }, "node_modules/js-yaml": { "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", "dependencies": { "argparse": "^2.0.1" @@ -6438,10 +7031,12 @@ }, "node_modules/jsbn": { "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", "integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==" }, "node_modules/jsesc": { "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", "dev": true, "bin": { @@ -6453,21 +7048,25 @@ }, "node_modules/json-buffer": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz", "integrity": "sha512-CuUqjv0FUZIdXkHPI8MezCnFCdaTAacej1TZYulLoAg1h/PhwkdXFN4V/gzY4g+fMBCOV2xF+rp7t2XD2ns/NQ==", "dev": true }, "node_modules/json-parse-better-errors": { "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", "dev": true }, "node_modules/json-parse-even-better-errors": { "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", "dev": true }, "node_modules/json-parse-helpfulerror": { "version": "1.0.3", + "resolved": "https://registry.npmjs.org/json-parse-helpfulerror/-/json-parse-helpfulerror-1.0.3.tgz", "integrity": "sha512-XgP0FGR77+QhUxjXkwOMkC94k3WtqEBfcnjWqhRd82qTat4SWKRE+9kUnynz/shm3I4ea2+qISvTIeGTNU7kJg==", "dev": true, "dependencies": { @@ -6476,6 +7075,7 @@ }, "node_modules/json-pointer": { "version": "0.6.2", + "resolved": "https://registry.npmjs.org/json-pointer/-/json-pointer-0.6.2.tgz", "integrity": "sha512-vLWcKbOaXlO+jvRy4qNd+TI1QUPZzfJj1tpJ3vAXDych5XJf93ftpUKe5pKCrzyIIwgBJcOcCVRUfqQP25afBw==", "dev": true, "dependencies": { @@ -6484,18 +7084,27 @@ }, "node_modules/json-promise": { "version": "1.1.8", + "resolved": "https://registry.npmjs.org/json-promise/-/json-promise-1.1.8.tgz", "integrity": "sha512-rz31P/7VfYnjQFrF60zpPTT0egMPlc8ZvIQHWs4ZtNZNnAXRmXo6oS+6eyWr5sEMG03OVhklNrTXxiIRYzoUgQ==", "dev": true, "dependencies": { "bluebird": "*" } }, + "node_modules/json-promise/node_modules/bluebird": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-2.2.2.tgz", + "integrity": "sha512-NqzuS2y44FmP++Ihv6/PgXpNRB+c282TKq0URBTQdA+EqPpR1Qu44QY8H8667LA39iOIaVHpmRPI4gpthYT8Ug==", + "dev": true + }, "node_modules/json-schema": { "version": "0.4.0", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==" }, "node_modules/json-schema-compare": { "version": "0.2.2", + "resolved": "https://registry.npmjs.org/json-schema-compare/-/json-schema-compare-0.2.2.tgz", "integrity": "sha512-c4WYmDKyJXhs7WWvAWm3uIYnfyWFoIp+JEoX34rctVvEkMYCPGhXtvmFFXiffBbxfZsvQ0RNnV5H7GvDF5HCqQ==", "dev": true, "dependencies": { @@ -6504,6 +7113,7 @@ }, "node_modules/json-schema-faker": { "version": "0.5.0-rcv.40", + "resolved": "https://registry.npmjs.org/json-schema-faker/-/json-schema-faker-0.5.0-rcv.40.tgz", "integrity": "sha512-BczZvu03jKrGh3ovCWrHusiX6MwiaKK2WZeyomKBNA8Nm/n7aBYz0mub1CnONB6cgxOZTNxx4afNmLblbUmZbA==", "dev": true, "dependencies": { @@ -6516,6 +7126,7 @@ }, "node_modules/json-schema-ref-parser": { "version": "6.1.0", + "resolved": "https://registry.npmjs.org/json-schema-ref-parser/-/json-schema-ref-parser-6.1.0.tgz", "integrity": "sha512-pXe9H1m6IgIpXmE5JSb8epilNTGsmTb2iPohAXpOdhqGFbQjNeHHsZxU+C8w6T81GZxSPFLeUoqDJmzxx5IGuw==", "deprecated": "Please switch to @apidevtools/json-schema-ref-parser", "dev": true, @@ -6527,6 +7138,7 @@ }, "node_modules/json-schema-ref-parser/node_modules/argparse": { "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", "dev": true, "dependencies": { @@ -6535,6 +7147,7 @@ }, "node_modules/json-schema-ref-parser/node_modules/js-yaml": { "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", "dev": true, "dependencies": { @@ -6547,14 +7160,17 @@ }, "node_modules/json-schema-traverse": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" }, "node_modules/json-stringify-safe": { "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==" }, "node_modules/json5": { "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", "dev": true, "bin": { @@ -6566,11 +7182,13 @@ }, "node_modules/jsonc-parser": { "version": "2.2.1", + "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-2.2.1.tgz", "integrity": "sha512-o6/yDBYccGvTz1+QFevz6l6OBZ2+fMVu2JZ9CIhzsYRX4mjaK5IyX9eldUdCmga16zlgQxyrj5pt9kzuj2C02w==", "dev": true }, "node_modules/jsonfile": { "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", "dependencies": { "universalify": "^2.0.0" @@ -6581,11 +7199,13 @@ }, "node_modules/jsonlines": { "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsonlines/-/jsonlines-0.1.1.tgz", "integrity": "sha512-ekDrAGso79Cvf+dtm+mL8OBI2bmAOt3gssYs833De/C9NmIpWDWyUO4zPgB5x2/OhY366dkhgfPMYfwZF7yOZA==", "dev": true }, "node_modules/jsonparse": { "version": "1.3.1", + "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", "integrity": "sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==", "dev": true, "engines": [ @@ -6594,6 +7214,7 @@ }, "node_modules/jsonpath-plus": { "version": "5.1.0", + "resolved": "https://registry.npmjs.org/jsonpath-plus/-/jsonpath-plus-5.1.0.tgz", "integrity": "sha512-890w2Pjtj0iswAxalRlt2kHthi6HKrXEfZcn+ZNZptv7F3rUGIeDuZo+C+h4vXBHLEsVjJrHeCm35nYeZLzSBQ==", "dev": true, "engines": { @@ -6602,11 +7223,13 @@ }, "node_modules/jsonpointer.js": { "version": "0.4.0", + "resolved": "https://registry.npmjs.org/jsonpointer.js/-/jsonpointer.js-0.4.0.tgz", "integrity": "sha512-2bf/1crAmPpsmj1I6rDT6W0SOErkrNBpb555xNWcMVWYrX6VnXpG0GRMQ2shvOHwafpfse8q0gnzPFYVH6Tqdg==", "dev": true }, "node_modules/JSONStream": { "version": "1.3.5", + "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz", "integrity": "sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==", "dev": true, "dependencies": { @@ -6622,6 +7245,7 @@ }, "node_modules/jsprim": { "version": "1.4.2", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.2.tgz", "integrity": "sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==", "dependencies": { "assert-plus": "1.0.0", @@ -6635,11 +7259,13 @@ }, "node_modules/just-extend": { "version": "4.2.1", + "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-4.2.1.tgz", "integrity": "sha512-g3UB796vUFIY90VIv/WX3L2c8CS2MdWUww3CNrYmqza1Fg0DURc2K/O4YrnklBdQarSJ/y8JnJYDGc+1iumQjg==", "dev": true }, "node_modules/keyv": { "version": "3.1.0", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.1.0.tgz", "integrity": "sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA==", "dev": true, "dependencies": { @@ -6648,6 +7274,7 @@ }, "node_modules/kind-of": { "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", "dev": true, "engines": { @@ -6656,6 +7283,7 @@ }, "node_modules/kleur": { "version": "3.0.3", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", "dev": true, "engines": { @@ -6664,6 +7292,7 @@ }, "node_modules/latest-version": { "version": "5.1.0", + "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-5.1.0.tgz", "integrity": "sha512-weT+r0kTkRQdCdYCNtkMwWXQTMEswKrFBkm4ckQOMVhhqhIMI1UT2hMj+1iigIhgSZm5gTmrRXBNoGUgaTY1xA==", "dev": true, "dependencies": { @@ -6675,6 +7304,7 @@ }, "node_modules/lazystream": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.1.tgz", "integrity": "sha512-b94GiNHQNy6JNTrt5w6zNyffMrNkXZb3KTkCZJb2V1xaEGCk093vkZ2jk3tpaeP33/OiXC+WvK9AxUebnf5nbw==", "dependencies": { "readable-stream": "^2.0.5" @@ -6684,8 +7314,9 @@ } }, "node_modules/lazystream/node_modules/readable-stream": { - "version": "2.3.7", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", "dependencies": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", @@ -6698,17 +7329,12 @@ }, "node_modules/lazystream/node_modules/safe-buffer": { "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" }, - "node_modules/lazystream/node_modules/string_decoder": { - "version": "1.1.1", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, "node_modules/libnpmconfig": { "version": "1.2.1", + "resolved": "https://registry.npmjs.org/libnpmconfig/-/libnpmconfig-1.2.1.tgz", "integrity": "sha512-9esX8rTQAHqarx6qeZqmGQKBNZR5OIbl/Ayr0qQDy3oXja2iFVQQI81R6GZ2a02bSNZ9p3YOGX1O6HHCb1X7kA==", "deprecated": "This module is not used anymore. npm config is parsed by npm itself and by @npmcli/config", "dev": true, @@ -6720,6 +7346,7 @@ }, "node_modules/libnpmconfig/node_modules/find-up": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", "dev": true, "dependencies": { @@ -6731,6 +7358,7 @@ }, "node_modules/libnpmconfig/node_modules/locate-path": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", "dev": true, "dependencies": { @@ -6741,22 +7369,9 @@ "node": ">=6" } }, - "node_modules/libnpmconfig/node_modules/p-limit": { - "version": "2.3.0", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/libnpmconfig/node_modules/p-locate": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", "dev": true, "dependencies": { @@ -6768,6 +7383,7 @@ }, "node_modules/libnpmconfig/node_modules/path-exists": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", "dev": true, "engines": { @@ -6776,6 +7392,7 @@ }, "node_modules/lilconfig": { "version": "2.0.5", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.0.5.tgz", "integrity": "sha512-xaYmXZtTHPAw5m+xLN8ab9C+3a8YmV3asNSPOATITbtwrfbwaLJj8h66H1WMIpALCkqsIzK3h7oQ+PdX+LQ9Eg==", "engines": { "node": ">=10" @@ -6783,11 +7400,13 @@ }, "node_modules/lines-and-columns": { "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", "dev": true }, "node_modules/lint-staged": { "version": "12.5.0", + "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-12.5.0.tgz", "integrity": "sha512-BKLUjWDsKquV/JuIcoQW4MSAI3ggwEImF1+sB4zaKvyVx1wBk3FsG7UK9bpnmBTN1pm7EH2BBcMwINJzCRv12g==", "dependencies": { "cli-truncate": "^3.1.0", @@ -6817,6 +7436,7 @@ }, "node_modules/lint-staged/node_modules/commander": { "version": "9.5.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-9.5.0.tgz", "integrity": "sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==", "engines": { "node": "^12.20.0 || >=14" @@ -6824,6 +7444,7 @@ }, "node_modules/lint-staged/node_modules/supports-color": { "version": "9.3.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-9.3.1.tgz", "integrity": "sha512-knBY82pjmnIzK3NifMo3RxEIRD9E0kIzV4BKcyTZ9+9kWgLMxd4PrsTSMoFQUabgRBbF8KOLRDCyKgNV+iK44Q==", "engines": { "node": ">=12" @@ -6834,6 +7455,7 @@ }, "node_modules/liquid-json": { "version": "0.3.1", + "resolved": "https://registry.npmjs.org/liquid-json/-/liquid-json-0.3.1.tgz", "integrity": "sha512-wUayTU8MS827Dam6MxgD72Ui+KOSF+u/eIqpatOtjnvgJ0+mnDq33uC2M7J0tPK+upe/DpUAuK4JUU89iBoNKQ==", "dev": true, "engines": { @@ -6842,11 +7464,13 @@ }, "node_modules/listenercount": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/listenercount/-/listenercount-1.0.1.tgz", "integrity": "sha512-3mk/Zag0+IJxeDrxSgaDPy4zZ3w05PRZeJNnlWhzFz5OkX49J4krc+A8X2d2M69vGMBEX0uyl8M+W+8gH+kBqQ==", "dev": true }, "node_modules/listr": { "version": "0.14.3", + "resolved": "https://registry.npmjs.org/listr/-/listr-0.14.3.tgz", "integrity": "sha512-RmAl7su35BFd/xoMamRjpIE4j3v+L28o8CT5YhAXQJm1fD+1l9ngXY8JAQRJ+tFK2i5njvi0iRUKV09vPwA0iA==", "dependencies": { "@samverschueren/stream-to-observable": "^0.3.0", @@ -6865,6 +7489,7 @@ }, "node_modules/listr-silent-renderer": { "version": "1.1.1", + "resolved": "https://registry.npmjs.org/listr-silent-renderer/-/listr-silent-renderer-1.1.1.tgz", "integrity": "sha512-L26cIFm7/oZeSNVhWB6faeorXhMg4HNlb/dS/7jHhr708jxlXrtrBWo4YUxZQkc6dGoxEAe6J/D3juTRBUzjtA==", "engines": { "node": ">=4" @@ -6872,6 +7497,7 @@ }, "node_modules/listr-update-renderer": { "version": "0.5.0", + "resolved": "https://registry.npmjs.org/listr-update-renderer/-/listr-update-renderer-0.5.0.tgz", "integrity": "sha512-tKRsZpKz8GSGqoI/+caPmfrypiaq+OQCbd+CovEC24uk1h952lVj5sC7SqyFUm+OaJ5HN/a1YLt5cit2FMNsFA==", "dependencies": { "chalk": "^1.1.3", @@ -6890,8 +7516,17 @@ "listr": "^0.14.2" } }, + "node_modules/listr-update-renderer/node_modules/ansi-escapes": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz", + "integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==", + "engines": { + "node": ">=4" + } + }, "node_modules/listr-update-renderer/node_modules/ansi-regex": { "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", "engines": { "node": ">=0.10.0" @@ -6899,6 +7534,7 @@ }, "node_modules/listr-update-renderer/node_modules/ansi-styles": { "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", "integrity": "sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA==", "engines": { "node": ">=0.10.0" @@ -6906,6 +7542,7 @@ }, "node_modules/listr-update-renderer/node_modules/chalk": { "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", "integrity": "sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A==", "dependencies": { "ansi-styles": "^2.2.1", @@ -6918,8 +7555,20 @@ "node": ">=0.10.0" } }, + "node_modules/listr-update-renderer/node_modules/cli-cursor": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", + "integrity": "sha512-8lgKz8LmCRYZZQDpRyT2m5rKJ08TnU4tR9FFFW2rxpxR1FzWi4PQ/NfyODchAatHaUgnSPVcx/R5w6NuTBzFiw==", + "dependencies": { + "restore-cursor": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/listr-update-renderer/node_modules/cli-truncate": { "version": "0.2.1", + "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-0.2.1.tgz", "integrity": "sha512-f4r4yJnbT++qUPI9NR4XLDLq41gQ+uqnPItWG0F5ZkehuNiTTa3EY0S4AqTSUOeJ7/zU41oWPQSNkW5BqPL9bg==", "dependencies": { "slice-ansi": "0.0.4", @@ -6931,6 +7580,7 @@ }, "node_modules/listr-update-renderer/node_modules/figures": { "version": "1.7.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz", "integrity": "sha512-UxKlfCRuCBxSXU4C6t9scbDyWZ4VlaFFdojKtzJuSkuOBQ5CNFum+zZXFwHjo+CxBC1t6zlYPgHIgFjL8ggoEQ==", "dependencies": { "escape-string-regexp": "^1.0.5", @@ -6940,8 +7590,17 @@ "node": ">=0.10.0" } }, + "node_modules/listr-update-renderer/node_modules/indent-string": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-3.2.0.tgz", + "integrity": "sha512-BYqTHXTGUIvg7t1r4sJNKcbDZkL92nkXA8YtRpbjFHRHGDL/NtUeiBJMeE60kIFN/Mg8ESaWQvftaYMGJzQZCQ==", + "engines": { + "node": ">=4" + } + }, "node_modules/listr-update-renderer/node_modules/is-fullwidth-code-point": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", "integrity": "sha512-1pqUqRjkhPJ9miNq9SwMfdvi6lBJcd6eFxvfaivQhaH3SgisfiuudvFntdKOmxuee/77l+FPjKrQjWvmPjWrRw==", "dependencies": { "number-is-nan": "^1.0.0" @@ -6950,8 +7609,64 @@ "node": ">=0.10.0" } }, + "node_modules/listr-update-renderer/node_modules/log-symbols": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-1.0.2.tgz", + "integrity": "sha512-mmPrW0Fh2fxOzdBbFv4g1m6pR72haFLPJ2G5SJEELf1y+iaQrDG6cWCPjy54RHYbZAt7X+ls690Kw62AdWXBzQ==", + "dependencies": { + "chalk": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/listr-update-renderer/node_modules/log-update": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/log-update/-/log-update-2.3.0.tgz", + "integrity": "sha512-vlP11XfFGyeNQlmEn9tJ66rEW1coA/79m5z6BCkudjbAGE83uhAcGYrBFwfs3AdLiLzGRusRPAbSPK9xZteCmg==", + "dependencies": { + "ansi-escapes": "^3.0.0", + "cli-cursor": "^2.0.0", + "wrap-ansi": "^3.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/listr-update-renderer/node_modules/mimic-fn": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", + "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", + "engines": { + "node": ">=4" + } + }, + "node_modules/listr-update-renderer/node_modules/onetime": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", + "integrity": "sha512-oyyPpiMaKARvvcgip+JV+7zci5L8D1W9RZIz2l1o08AM3pfspitVWnPt3mzHcBPp12oYMTy0pqrFs/C+m3EwsQ==", + "dependencies": { + "mimic-fn": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/listr-update-renderer/node_modules/restore-cursor": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", + "integrity": "sha512-6IzJLuGi4+R14vwagDHX+JrXmPVtPpn4mffDJ1UdR7/Edm87fl6yi8mMBIVvFtJaNTUvjughmW4hwLhRG7gC1Q==", + "dependencies": { + "onetime": "^2.0.0", + "signal-exit": "^3.0.2" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/listr-update-renderer/node_modules/slice-ansi": { "version": "0.0.4", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-0.0.4.tgz", "integrity": "sha512-up04hB2hR92PgjpyU3y/eg91yIBILyjVY26NvvciY3EVVPjybkMszMpXQ9QAkcS3I5rtJBDLoTxxg+qvW8c7rw==", "engines": { "node": ">=0.10.0" @@ -6959,6 +7674,7 @@ }, "node_modules/listr-update-renderer/node_modules/string-width": { "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", "integrity": "sha512-0XsVpQLnVCXHJfyEs8tC0zpTVIr5PKKsQtkT29IwupnPTjtPmQ3xT/4yCREF9hYkV/3M3kzcUTSAZT6a6h81tw==", "dependencies": { "code-point-at": "^1.0.0", @@ -6971,6 +7687,7 @@ }, "node_modules/listr-update-renderer/node_modules/strip-ansi": { "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", "integrity": "sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==", "dependencies": { "ansi-regex": "^2.0.0" @@ -6981,17 +7698,70 @@ }, "node_modules/listr-update-renderer/node_modules/supports-color": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", "integrity": "sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g==", "engines": { "node": ">=0.8.0" } }, - "node_modules/listr-verbose-renderer": { - "version": "0.5.0", - "integrity": "sha512-04PDPqSlsqIOaaaGZ+41vq5FejI9auqTInicFRndCBgE3bXG8D6W1I+mWhk+1nqbHmyhla/6BUrd5OSiHwKRXw==", + "node_modules/listr-update-renderer/node_modules/wrap-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-3.0.1.tgz", + "integrity": "sha512-iXR3tDXpbnTpzjKSylUJRkLuOrEC7hwEB221cgn6wtF8wpmz28puFXAEfPT5zrjM3wahygB//VuWEr1vTkDcNQ==", "dependencies": { - "chalk": "^2.4.1", - "cli-cursor": "^2.1.0", + "string-width": "^2.1.1", + "strip-ansi": "^4.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/listr-update-renderer/node_modules/wrap-ansi/node_modules/ansi-regex": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.1.tgz", + "integrity": "sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw==", + "engines": { + "node": ">=4" + } + }, + "node_modules/listr-update-renderer/node_modules/wrap-ansi/node_modules/is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==", + "engines": { + "node": ">=4" + } + }, + "node_modules/listr-update-renderer/node_modules/wrap-ansi/node_modules/string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dependencies": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/listr-update-renderer/node_modules/wrap-ansi/node_modules/strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha512-4XaJ2zQdCzROZDivEVIDPkcQn8LMFSa8kj8Gxb/Lnwzv9A8VctNZ+lfivC/sV3ivW8ElJTERXZoPBRrZKkNKow==", + "dependencies": { + "ansi-regex": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/listr-verbose-renderer": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/listr-verbose-renderer/-/listr-verbose-renderer-0.5.0.tgz", + "integrity": "sha512-04PDPqSlsqIOaaaGZ+41vq5FejI9auqTInicFRndCBgE3bXG8D6W1I+mWhk+1nqbHmyhla/6BUrd5OSiHwKRXw==", + "dependencies": { + "chalk": "^2.4.1", + "cli-cursor": "^2.1.0", "date-fns": "^1.27.2", "figures": "^2.0.0" }, @@ -7001,6 +7771,7 @@ }, "node_modules/listr-verbose-renderer/node_modules/ansi-styles": { "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", "dependencies": { "color-convert": "^1.9.0" @@ -7011,6 +7782,7 @@ }, "node_modules/listr-verbose-renderer/node_modules/chalk": { "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "dependencies": { "ansi-styles": "^3.2.1", @@ -7023,6 +7795,7 @@ }, "node_modules/listr-verbose-renderer/node_modules/cli-cursor": { "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", "integrity": "sha512-8lgKz8LmCRYZZQDpRyT2m5rKJ08TnU4tR9FFFW2rxpxR1FzWi4PQ/NfyODchAatHaUgnSPVcx/R5w6NuTBzFiw==", "dependencies": { "restore-cursor": "^2.0.0" @@ -7033,6 +7806,7 @@ }, "node_modules/listr-verbose-renderer/node_modules/color-convert": { "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", "dependencies": { "color-name": "1.1.3" @@ -7040,14 +7814,17 @@ }, "node_modules/listr-verbose-renderer/node_modules/color-name": { "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" }, "node_modules/listr-verbose-renderer/node_modules/date-fns": { "version": "1.30.1", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-1.30.1.tgz", "integrity": "sha512-hBSVCvSmWC+QypYObzwGOd9wqdDpOt+0wl0KbU+R+uuZBS1jN8VsD1ss3irQDknRj5NvxiTF6oj/nDRnN/UQNw==" }, "node_modules/listr-verbose-renderer/node_modules/figures": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", "integrity": "sha512-Oa2M9atig69ZkfwiApY8F2Yy+tzMbazyvqv21R0NsSC8floSOC09BbT1ITWAdoMGQvJ/aZnR1KMwdx9tvHnTNA==", "dependencies": { "escape-string-regexp": "^1.0.5" @@ -7058,6 +7835,7 @@ }, "node_modules/listr-verbose-renderer/node_modules/has-flag": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", "engines": { "node": ">=4" @@ -7065,6 +7843,7 @@ }, "node_modules/listr-verbose-renderer/node_modules/mimic-fn": { "version": "1.2.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", "engines": { "node": ">=4" @@ -7072,6 +7851,7 @@ }, "node_modules/listr-verbose-renderer/node_modules/onetime": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", "integrity": "sha512-oyyPpiMaKARvvcgip+JV+7zci5L8D1W9RZIz2l1o08AM3pfspitVWnPt3mzHcBPp12oYMTy0pqrFs/C+m3EwsQ==", "dependencies": { "mimic-fn": "^1.0.0" @@ -7082,6 +7862,7 @@ }, "node_modules/listr-verbose-renderer/node_modules/restore-cursor": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", "integrity": "sha512-6IzJLuGi4+R14vwagDHX+JrXmPVtPpn4mffDJ1UdR7/Edm87fl6yi8mMBIVvFtJaNTUvjughmW4hwLhRG7gC1Q==", "dependencies": { "onetime": "^2.0.0", @@ -7093,6 +7874,7 @@ }, "node_modules/listr-verbose-renderer/node_modules/supports-color": { "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", "dependencies": { "has-flag": "^3.0.0" @@ -7103,13 +7885,23 @@ }, "node_modules/listr/node_modules/is-stream": { "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", "integrity": "sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ==", "engines": { "node": ">=0.10.0" } }, + "node_modules/listr/node_modules/p-map": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-2.1.0.tgz", + "integrity": "sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==", + "engines": { + "node": ">=6" + } + }, "node_modules/listr/node_modules/rxjs": { "version": "6.6.7", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz", "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==", "dependencies": { "tslib": "^1.9.0" @@ -7120,10 +7912,12 @@ }, "node_modules/listr/node_modules/tslib": { "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" }, "node_modules/listr2": { "version": "4.0.5", + "resolved": "https://registry.npmjs.org/listr2/-/listr2-4.0.5.tgz", "integrity": "sha512-juGHV1doQdpNT3GSTs9IUN43QJb7KHdF9uqg7Vufs/tG9VTzpFphqF4pm/ICdAABGQxsyNn9CiYA3StkI6jpwA==", "dependencies": { "cli-truncate": "^2.1.0", @@ -7149,6 +7943,7 @@ }, "node_modules/listr2/node_modules/cli-truncate": { "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-2.1.0.tgz", "integrity": "sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg==", "dependencies": { "slice-ansi": "^3.0.0", @@ -7161,71 +7956,9 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/listr2/node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "engines": { - "node": ">=8" - } - }, - "node_modules/listr2/node_modules/log-update": { - "version": "4.0.0", - "integrity": "sha512-9fkkDevMefjg0mmzWFBW8YkFP91OrizzkW3diF7CpG+S2EYdy4+TVfGwz1zeF8x7hCx1ovSPTOE9Ngib74qqUg==", - "dependencies": { - "ansi-escapes": "^4.3.0", - "cli-cursor": "^3.1.0", - "slice-ansi": "^4.0.0", - "wrap-ansi": "^6.2.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/listr2/node_modules/log-update/node_modules/slice-ansi": { - "version": "4.0.0", - "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", - "dependencies": { - "ansi-styles": "^4.0.0", - "astral-regex": "^2.0.0", - "is-fullwidth-code-point": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/slice-ansi?sponsor=1" - } - }, - "node_modules/listr2/node_modules/log-update/node_modules/wrap-ansi": { - "version": "6.2.0", - "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/listr2/node_modules/p-map": { - "version": "4.0.0", - "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", - "dependencies": { - "aggregate-error": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/listr2/node_modules/slice-ansi": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-3.0.0.tgz", "integrity": "sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ==", "dependencies": { "ansi-styles": "^4.0.0", @@ -7238,6 +7971,7 @@ }, "node_modules/load-json-file": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", "integrity": "sha512-Kx8hMakjX03tiGTLAIdJ+lL0htKnXjEZN6hk/tozf/WOuYGdZBJrZ+rCJRbVCugsjB3jMLn9746NsQIf5VjBMw==", "dev": true, "dependencies": { @@ -7252,6 +7986,7 @@ }, "node_modules/load-json-file/node_modules/parse-json": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", "integrity": "sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==", "dev": true, "dependencies": { @@ -7262,251 +7997,174 @@ "node": ">=4" } }, - "node_modules/load-json-file/node_modules/strip-bom": { - "version": "3.0.0", - "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", - "dev": true, - "engines": { - "node": ">=4" - } - }, "node_modules/locate-path": { - "version": "6.0.0", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", "dev": true, "dependencies": { - "p-locate": "^5.0.0" + "p-locate": "^4.1.0" }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=8" } }, "node_modules/lodash": { "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" }, "node_modules/lodash.camelcase": { "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==", "dev": true }, "node_modules/lodash.defaults": { "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz", "integrity": "sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ==" }, "node_modules/lodash.difference": { "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.difference/-/lodash.difference-4.5.0.tgz", "integrity": "sha512-dS2j+W26TQ7taQBGN8Lbbq04ssV3emRw4NY58WErlTO29pIqS0HmoT5aJ9+TUQ1N3G+JOZSji4eugsWwGp9yPA==" }, "node_modules/lodash.flatten": { "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz", "integrity": "sha512-C5N2Z3DgnnKr0LOpv/hKCgKdb7ZZwafIrsesve6lmzvZIRZRGaZ/l6Q8+2W7NaT+ZwO3fFlSCzCzrDCFdJfZ4g==" }, "node_modules/lodash.flattendeep": { "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz", "integrity": "sha512-uHaJFihxmJcEX3kT4I23ABqKKalJ/zDrDg0lsFtc1h+3uw49SIJ5beyhx5ExVRti3AvKoOJngIj7xz3oylPdWQ==", "dev": true }, "node_modules/lodash.get": { "version": "4.4.2", + "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", "integrity": "sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==", "dev": true }, "node_modules/lodash.isequalwith": { "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.isequalwith/-/lodash.isequalwith-4.4.0.tgz", "integrity": "sha512-dcZON0IalGBpRmJBmMkaoV7d3I80R2O+FrzsZyHdNSFrANq/cgDqKQNmAHE8UEj4+QYWwwhkQOVdLHiAopzlsQ==", "dev": true }, "node_modules/lodash.isfinite": { "version": "3.3.2", + "resolved": "https://registry.npmjs.org/lodash.isfinite/-/lodash.isfinite-3.3.2.tgz", "integrity": "sha512-7FGG40uhC8Mm633uKW1r58aElFlBlxCrg9JfSi3P6aYiWmfiWF0PgMd86ZUsxE5GwWPdHoS2+48bwTh2VPkIQA==" }, "node_modules/lodash.ismatch": { "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.ismatch/-/lodash.ismatch-4.4.0.tgz", "integrity": "sha512-fPMfXjGQEV9Xsq/8MTSgUf255gawYRbjwMyDbcvDhXgV7enSZA0hynz6vMPnpAb5iONEzBHBPsT+0zes5Z301g==", "dev": true }, "node_modules/lodash.isplainobject": { "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==" }, "node_modules/lodash.pick": { "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.pick/-/lodash.pick-4.4.0.tgz", "integrity": "sha512-hXt6Ul/5yWjfklSGvLQl8vM//l3FtyHZeuelpzK6mm99pNvN9yTDruNZPEJZD1oWrqo+izBmB7oUfWgcCX7s4Q==", "dev": true }, "node_modules/lodash.pickby": { "version": "4.6.0", + "resolved": "https://registry.npmjs.org/lodash.pickby/-/lodash.pickby-4.6.0.tgz", "integrity": "sha512-AZV+GsS/6ckvPOVQPXSiFFacKvKB4kOQu6ynt9wz0F3LO4R9Ij4K1ddYsIytDpSgLz88JHd9P+oaLeej5/Sl7Q==", "dev": true }, "node_modules/lodash.union": { "version": "4.6.0", + "resolved": "https://registry.npmjs.org/lodash.union/-/lodash.union-4.6.0.tgz", "integrity": "sha512-c4pB2CdGrGdjMKYLA+XiRDO7Y0PRQbm/Gzg8qMj+QH+pFVAoTp5sBpO0odL3FjoPCGjK96p6qsP+yQoiLoOBcw==" }, "node_modules/log-symbols": { - "version": "1.0.2", - "integrity": "sha512-mmPrW0Fh2fxOzdBbFv4g1m6pR72haFLPJ2G5SJEELf1y+iaQrDG6cWCPjy54RHYbZAt7X+ls690Kw62AdWXBzQ==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", "dependencies": { - "chalk": "^1.0.0" + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" }, "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/log-symbols/node_modules/ansi-regex": { - "version": "2.1.1", - "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/log-symbols/node_modules/ansi-styles": { - "version": "2.2.1", - "integrity": "sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA==", - "engines": { - "node": ">=0.10.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/log-symbols/node_modules/chalk": { - "version": "1.1.3", - "integrity": "sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A==", + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dependencies": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/log-symbols/node_modules/strip-ansi": { - "version": "3.0.1", - "integrity": "sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==", - "dependencies": { - "ansi-regex": "^2.0.0" + "node": ">=10" }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/log-symbols/node_modules/supports-color": { - "version": "2.0.0", - "integrity": "sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g==", - "engines": { - "node": ">=0.8.0" + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, "node_modules/log-update": { - "version": "2.3.0", - "integrity": "sha512-vlP11XfFGyeNQlmEn9tJ66rEW1coA/79m5z6BCkudjbAGE83uhAcGYrBFwfs3AdLiLzGRusRPAbSPK9xZteCmg==", - "dependencies": { - "ansi-escapes": "^3.0.0", - "cli-cursor": "^2.0.0", - "wrap-ansi": "^3.0.1" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/log-update/node_modules/ansi-escapes": { - "version": "3.2.0", - "integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==", - "engines": { - "node": ">=4" - } - }, - "node_modules/log-update/node_modules/ansi-regex": { - "version": "3.0.1", - "integrity": "sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw==", - "engines": { - "node": ">=4" - } - }, - "node_modules/log-update/node_modules/cli-cursor": { - "version": "2.1.0", - "integrity": "sha512-8lgKz8LmCRYZZQDpRyT2m5rKJ08TnU4tR9FFFW2rxpxR1FzWi4PQ/NfyODchAatHaUgnSPVcx/R5w6NuTBzFiw==", - "dependencies": { - "restore-cursor": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/log-update/node_modules/is-fullwidth-code-point": { - "version": "2.0.0", - "integrity": "sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==", - "engines": { - "node": ">=4" - } - }, - "node_modules/log-update/node_modules/mimic-fn": { - "version": "1.2.0", - "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", - "engines": { - "node": ">=4" - } - }, - "node_modules/log-update/node_modules/onetime": { - "version": "2.0.1", - "integrity": "sha512-oyyPpiMaKARvvcgip+JV+7zci5L8D1W9RZIz2l1o08AM3pfspitVWnPt3mzHcBPp12oYMTy0pqrFs/C+m3EwsQ==", - "dependencies": { - "mimic-fn": "^1.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/log-update/node_modules/restore-cursor": { - "version": "2.0.0", - "integrity": "sha512-6IzJLuGi4+R14vwagDHX+JrXmPVtPpn4mffDJ1UdR7/Edm87fl6yi8mMBIVvFtJaNTUvjughmW4hwLhRG7gC1Q==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/log-update/-/log-update-4.0.0.tgz", + "integrity": "sha512-9fkkDevMefjg0mmzWFBW8YkFP91OrizzkW3diF7CpG+S2EYdy4+TVfGwz1zeF8x7hCx1ovSPTOE9Ngib74qqUg==", "dependencies": { - "onetime": "^2.0.0", - "signal-exit": "^3.0.2" + "ansi-escapes": "^4.3.0", + "cli-cursor": "^3.1.0", + "slice-ansi": "^4.0.0", + "wrap-ansi": "^6.2.0" }, "engines": { - "node": ">=4" - } - }, - "node_modules/log-update/node_modules/string-width": { - "version": "2.1.1", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", - "dependencies": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" + "node": ">=10" }, - "engines": { - "node": ">=4" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/log-update/node_modules/strip-ansi": { + "node_modules/log-update/node_modules/slice-ansi": { "version": "4.0.0", - "integrity": "sha512-4XaJ2zQdCzROZDivEVIDPkcQn8LMFSa8kj8Gxb/Lnwzv9A8VctNZ+lfivC/sV3ivW8ElJTERXZoPBRrZKkNKow==", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", + "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", "dependencies": { - "ansi-regex": "^3.0.0" + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" }, "engines": { - "node": ">=4" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" } }, "node_modules/log-update/node_modules/wrap-ansi": { - "version": "3.0.1", - "integrity": "sha512-iXR3tDXpbnTpzjKSylUJRkLuOrEC7hwEB221cgn6wtF8wpmz28puFXAEfPT5zrjM3wahygB//VuWEr1vTkDcNQ==", + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", "dependencies": { - "string-width": "^2.1.1", - "strip-ansi": "^4.0.0" + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" }, "engines": { - "node": ">=4" + "node": ">=8" } }, "node_modules/loupe": { "version": "2.3.6", + "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.6.tgz", "integrity": "sha512-RaPMZKiMy8/JruncMU5Bt6na1eftNoo++R4Y+N2FrxkDVTrGvcyzFTsaGif4QTeKESheMGegbhw6iUAq+5A8zA==", "dev": true, "dependencies": { @@ -7515,6 +8173,7 @@ }, "node_modules/lowercase-keys": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==", "dev": true, "engines": { @@ -7522,15 +8181,20 @@ } }, "node_modules/lru-cache": { - "version": "5.1.1", - "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", "dev": true, "dependencies": { - "yallist": "^3.0.2" + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" } }, "node_modules/make-dir": { "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", "dev": true, "dependencies": { @@ -7545,6 +8209,7 @@ }, "node_modules/make-dir/node_modules/semver": { "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", "dev": true, "bin": { @@ -7553,11 +8218,13 @@ }, "node_modules/make-error": { "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", "dev": true }, "node_modules/make-fetch-happen": { "version": "10.2.1", + "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-10.2.1.tgz", "integrity": "sha512-NgOPbRiaQM10DYXvN3/hhGVI2M5MtITFryzBGxHM5p4wnFxsVCbxkrBrDsk+EZ5OB4jEOT7AjDxtdF+KVEFT7w==", "dev": true, "dependencies": { @@ -7583,8 +8250,9 @@ } }, "node_modules/make-fetch-happen/node_modules/lru-cache": { - "version": "7.14.1", - "integrity": "sha512-ysxwsnTKdAx96aTRdhDOCQfDgbHnt8SK0KY8SEjO0wHinhWOFTESbjVCMPbU1uGXg/ch4lifqx0wfjOawU2+WA==", + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", + "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", "dev": true, "engines": { "node": ">=12" @@ -7592,6 +8260,7 @@ }, "node_modules/makeerror": { "version": "1.0.12", + "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", "dev": true, "dependencies": { @@ -7600,6 +8269,7 @@ }, "node_modules/map-obj": { "version": "4.3.0", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-4.3.0.tgz", "integrity": "sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==", "dev": true, "engines": { @@ -7611,6 +8281,7 @@ }, "node_modules/media-typer": { "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", "dev": true, "engines": { @@ -7619,6 +8290,7 @@ }, "node_modules/meow": { "version": "8.1.2", + "resolved": "https://registry.npmjs.org/meow/-/meow-8.1.2.tgz", "integrity": "sha512-r85E3NdZ+mpYk1C6RjPFEMSE+s1iZMuHtsHAqY0DT3jZczl0diWUZ8g6oU7h0M9cD2EL+PzaYghhCLzR0ZNn5Q==", "dev": true, "dependencies": { @@ -7643,6 +8315,7 @@ }, "node_modules/meow/node_modules/type-fest": { "version": "0.18.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.18.1.tgz", "integrity": "sha512-OIAYXk8+ISY+qTOwkHtKqzAuxchoMiD9Udx+FSGQDuiRR+PJKJHc2NJAXlbhkGwTt/4/nKZxELY1w3ReWOL8mw==", "dev": true, "engines": { @@ -7654,15 +8327,18 @@ }, "node_modules/merge-descriptors": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==", "dev": true }, "node_modules/merge-stream": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==" }, "node_modules/merge2": { "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", "dev": true, "engines": { @@ -7671,6 +8347,7 @@ }, "node_modules/micri": { "version": "4.5.1", + "resolved": "https://registry.npmjs.org/micri/-/micri-4.5.1.tgz", "integrity": "sha512-AtvnSBGFglNr+iqs5gufpHT9xRXUabgu9vYEnQYPXSBs+nLSBvmUS5Mzg+3LJ9eQBrNA1o5M49WeqiX1f+d2sg==", "dev": true, "dependencies": { @@ -7682,6 +8359,7 @@ }, "node_modules/micromatch": { "version": "4.0.5", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", "dependencies": { "braces": "^3.0.2", @@ -7693,6 +8371,7 @@ }, "node_modules/mime-db": { "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", "engines": { "node": ">= 0.6" @@ -7700,6 +8379,7 @@ }, "node_modules/mime-format": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mime-format/-/mime-format-2.0.1.tgz", "integrity": "sha512-XxU3ngPbEnrYnNbIX+lYSaYg0M01v6p2ntd2YaFksTu0vayaw5OJvbdRyWs07EYRlLED5qadUZ+xo+XhOvFhwg==", "dev": true, "dependencies": { @@ -7708,6 +8388,7 @@ }, "node_modules/mime-types": { "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", "dependencies": { "mime-db": "1.52.0" @@ -7718,6 +8399,7 @@ }, "node_modules/mimic-fn": { "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", "engines": { "node": ">=6" @@ -7725,6 +8407,7 @@ }, "node_modules/mimic-response": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", "dev": true, "engines": { @@ -7733,6 +8416,7 @@ }, "node_modules/min-indent": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", "dev": true, "engines": { @@ -7741,6 +8425,7 @@ }, "node_modules/minimatch": { "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dependencies": { "brace-expansion": "^1.1.7" @@ -7751,11 +8436,13 @@ }, "node_modules/minimist": { "version": "1.2.6", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==", "devOptional": true }, "node_modules/minimist-options": { "version": "4.1.0", + "resolved": "https://registry.npmjs.org/minimist-options/-/minimist-options-4.1.0.tgz", "integrity": "sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==", "dev": true, "dependencies": { @@ -7769,6 +8456,7 @@ }, "node_modules/minipass": { "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", "dev": true, "dependencies": { @@ -7780,6 +8468,7 @@ }, "node_modules/minipass-collect": { "version": "1.0.2", + "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-1.0.2.tgz", "integrity": "sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==", "dev": true, "dependencies": { @@ -7791,6 +8480,7 @@ }, "node_modules/minipass-fetch": { "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-2.1.2.tgz", "integrity": "sha512-LT49Zi2/WMROHYoqGgdlQIZh8mLPZmOrN2NdJjMXxYe4nkN6FUyuPuOAOedNJDrx0IRGg9+4guZewtp8hE6TxA==", "dev": true, "dependencies": { @@ -7807,6 +8497,7 @@ }, "node_modules/minipass-flush": { "version": "1.0.5", + "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz", "integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==", "dev": true, "dependencies": { @@ -7818,6 +8509,7 @@ }, "node_modules/minipass-json-stream": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minipass-json-stream/-/minipass-json-stream-1.0.1.tgz", "integrity": "sha512-ODqY18UZt/I8k+b7rl2AENgbWE8IDYam+undIJONvigAz8KR5GWblsFTEfQs0WODsjbSXWlm+JHEv8Gr6Tfdbg==", "dev": true, "dependencies": { @@ -7827,6 +8519,7 @@ }, "node_modules/minipass-pipeline": { "version": "1.2.4", + "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz", "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==", "dev": true, "dependencies": { @@ -7838,6 +8531,7 @@ }, "node_modules/minipass-sized": { "version": "1.0.3", + "resolved": "https://registry.npmjs.org/minipass-sized/-/minipass-sized-1.0.3.tgz", "integrity": "sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==", "dev": true, "dependencies": { @@ -7847,13 +8541,9 @@ "node": ">=8" } }, - "node_modules/minipass/node_modules/yallist": { - "version": "4.0.0", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, "node_modules/minizlib": { "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", "dev": true, "dependencies": { @@ -7864,13 +8554,9 @@ "node": ">= 8" } }, - "node_modules/minizlib/node_modules/yallist": { - "version": "4.0.0", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, "node_modules/mkdirp": { "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", "devOptional": true, "dependencies": { @@ -7882,6 +8568,7 @@ }, "node_modules/mocha": { "version": "9.2.2", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-9.2.2.tgz", "integrity": "sha512-L6XC3EdwT6YrIk0yXpavvLkn8h+EU+Y5UcCHKECyMbdUIxyMuZj4bX4U9e1nvnvUUvQVsV2VHQr5zLdcUkhW/g==", "dev": true, "dependencies": { @@ -7924,6 +8611,7 @@ }, "node_modules/mocha-chai-jest-snapshot": { "version": "1.1.4", + "resolved": "https://registry.npmjs.org/mocha-chai-jest-snapshot/-/mocha-chai-jest-snapshot-1.1.4.tgz", "integrity": "sha512-ybwtS10P8BXDJQn9B3QyQA8Lxr/CcYxtuyWKk1PxD9vJorH8VL3edB7re4GcG9dRAdDPE/B0BsfwmCo6W43O7w==", "dev": true, "dependencies": { @@ -7941,6 +8629,7 @@ }, "node_modules/mocha-chai-jest-snapshot/node_modules/chalk": { "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, "dependencies": { @@ -7956,6 +8645,7 @@ }, "node_modules/mocha.parallel": { "version": "0.15.6", + "resolved": "https://registry.npmjs.org/mocha.parallel/-/mocha.parallel-0.15.6.tgz", "integrity": "sha512-pWph+QieKGjk7cHY2hB78wyKJDOQLyOMDuBLQLrFL7riJb8qbQBlCY3XztFHv0D1d4I1gCpiwFNjd4LhVOXPew==", "dev": true, "dependencies": { @@ -7968,37 +8658,13 @@ }, "node_modules/mocha.parallel/node_modules/bluebird": { "version": "2.11.0", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-2.11.0.tgz", "integrity": "sha512-UfFSr22dmHPQqPP9XWHRhq+gWnHCYguQGkXQlbyPtW5qTnhFWA8/iXg765tH0cAjy7l/zPJ1aBTO0g5XgA7kvQ==", "dev": true }, - "node_modules/mocha/node_modules/chalk": { - "version": "4.1.2", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/mocha/node_modules/chalk/node_modules/supports-color": { - "version": "7.2.0", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/mocha/node_modules/cliui": { "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", "dev": true, "dependencies": { @@ -8009,6 +8675,7 @@ }, "node_modules/mocha/node_modules/debug": { "version": "4.3.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz", "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==", "dev": true, "dependencies": { @@ -8025,11 +8692,22 @@ }, "node_modules/mocha/node_modules/debug/node_modules/ms": { "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true }, + "node_modules/mocha/node_modules/diff": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", + "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", + "dev": true, + "engines": { + "node": ">=0.3.1" + } + }, "node_modules/mocha/node_modules/escape-string-regexp": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", "dev": true, "engines": { @@ -8039,8 +8717,25 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/mocha/node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/mocha/node_modules/glob": { "version": "7.2.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", "dev": true, "dependencies": { @@ -8060,6 +8755,7 @@ }, "node_modules/mocha/node_modules/glob/node_modules/minimatch": { "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, "dependencies": { @@ -8069,13 +8765,13 @@ "node": "*" } }, - "node_modules/mocha/node_modules/log-symbols": { - "version": "4.1.0", - "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", + "node_modules/mocha/node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", "dev": true, "dependencies": { - "chalk": "^4.1.0", - "is-unicode-supported": "^0.1.0" + "p-locate": "^5.0.0" }, "engines": { "node": ">=10" @@ -8086,6 +8782,7 @@ }, "node_modules/mocha/node_modules/minimatch": { "version": "4.2.1", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-4.2.1.tgz", "integrity": "sha512-9Uq1ChtSZO+Mxa/CL1eGizn2vRn3MlLgzhT0Iz8zaY8NdvxvB0d5QdPFmCKf7JKA9Lerx5vRrnwO03jsSfGG9g==", "dev": true, "dependencies": { @@ -8097,11 +8794,43 @@ }, "node_modules/mocha/node_modules/ms": { "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "dev": true }, + "node_modules/mocha/node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/mocha/node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/mocha/node_modules/supports-color": { "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", "dev": true, "dependencies": { @@ -8116,6 +8845,7 @@ }, "node_modules/mocha/node_modules/yargs": { "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", "dev": true, "dependencies": { @@ -8133,6 +8863,7 @@ }, "node_modules/mocha/node_modules/yargs-parser": { "version": "20.2.4", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", "dev": true, "engines": { @@ -8141,6 +8872,7 @@ }, "node_modules/modify-values": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/modify-values/-/modify-values-1.0.1.tgz", "integrity": "sha512-xV2bxeN6F7oYjZWTe/YPAy6MN2M+sL4u/Rlm2AHCIVGfo2p1yGmBHQ6vHehl4bRTZBdHu3TSkWdYgkwpYzAGSw==", "dev": true, "engines": { @@ -8149,11 +8881,13 @@ }, "node_modules/module-not-found-error": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/module-not-found-error/-/module-not-found-error-1.0.1.tgz", "integrity": "sha512-pEk4ECWQXV6z2zjhRZUongnLJNUeGQJ3w6OQ5ctGwD+i5o93qjRQUk2Rt6VdNeu3sEP0AB4LcfvdebpxBRVr4g==", "dev": true }, "node_modules/moment": { "version": "2.29.4", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz", "integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==", "optional": true, "engines": { @@ -8162,10 +8896,12 @@ }, "node_modules/ms": { "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, "node_modules/mustache": { "version": "4.2.0", + "resolved": "https://registry.npmjs.org/mustache/-/mustache-4.2.0.tgz", "integrity": "sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ==", "bin": { "mustache": "bin/mustache" @@ -8173,10 +8909,12 @@ }, "node_modules/mute-stream": { "version": "0.0.8", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==" }, "node_modules/mv": { "version": "2.1.1", + "resolved": "https://registry.npmjs.org/mv/-/mv-2.1.1.tgz", "integrity": "sha512-at/ZndSy3xEGJ8i0ygALh8ru9qy7gWW1cmkaqBN29JmMlIvM//MEO9y1sk/avxuwnPcfhkejkLsuPxH81BrkSg==", "optional": true, "dependencies": { @@ -8190,6 +8928,7 @@ }, "node_modules/mv/node_modules/glob": { "version": "6.0.4", + "resolved": "https://registry.npmjs.org/glob/-/glob-6.0.4.tgz", "integrity": "sha512-MKZeRNyYZAVVVG1oZeLaWie1uweH40m9AZwIwxyPbTSX4hHrVYSzLg0Ro5Z5R7XKkIX+Cc6oD1rqeDJnwsB8/A==", "optional": true, "dependencies": { @@ -8205,6 +8944,7 @@ }, "node_modules/mv/node_modules/rimraf": { "version": "2.4.5", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.4.5.tgz", "integrity": "sha512-J5xnxTyqaiw06JjMftq7L9ouA448dw/E7dKghkP9WpKNuwmARNNg+Gk8/u5ryb9N/Yo2+z3MCwuqFK/+qPOPfQ==", "optional": true, "dependencies": { @@ -8216,11 +8956,13 @@ }, "node_modules/nan": { "version": "2.17.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.17.0.tgz", "integrity": "sha512-2ZTgtl0nJsO0KQCjEpxcIr5D+Yv90plTitZt9JBfQvVJDS5seMl3FOvsh3+9CoYWXf/1l5OaZzzF6nDm4cagaQ==", "optional": true }, "node_modules/nanoid": { "version": "3.3.1", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.1.tgz", "integrity": "sha512-n6Vs/3KGyxPQd6uO0eH4Bv0ojGSUvuLlIHtC3Y0kEO23YRge8H9x1GCzLn28YX0H66pMkxuaeESFq4tKISKwdw==", "dev": true, "bin": { @@ -8232,11 +8974,13 @@ }, "node_modules/natural-compare": { "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", "dev": true }, "node_modules/ncp": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ncp/-/ncp-2.0.0.tgz", "integrity": "sha512-zIdGUrPRFTUELUvr3Gmc7KZ2Sw/h1PiVM0Af/oHB6zgnV1ikqSfRk+TOufi79aHYCW3NiOXmr1BP5nWbzojLaA==", "devOptional": true, "bin": { @@ -8245,6 +8989,7 @@ }, "node_modules/negotiator": { "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", "dev": true, "engines": { @@ -8253,11 +8998,13 @@ }, "node_modules/neo-async": { "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", "dev": true }, "node_modules/nise": { "version": "5.1.4", + "resolved": "https://registry.npmjs.org/nise/-/nise-5.1.4.tgz", "integrity": "sha512-8+Ib8rRJ4L0o3kfmyVCL7gzrohyDe0cMFTBa2d364yIrEGMEoetznKJx899YxjybU6bL9SQkYPSBBs1gyYs8Xg==", "dev": true, "dependencies": { @@ -8270,6 +9017,7 @@ }, "node_modules/nise/node_modules/@sinonjs/commons": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-2.0.0.tgz", "integrity": "sha512-uLa0j859mMrg2slwQYdO/AkrOfmH+X6LTVmNTS9CqexuE2IvVORIkSpJLqePAbEnKJ77aMmCwr1NUZ57120Xcg==", "dev": true, "dependencies": { @@ -8278,6 +9026,7 @@ }, "node_modules/nise/node_modules/@sinonjs/fake-timers": { "version": "10.0.2", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.0.2.tgz", "integrity": "sha512-SwUDyjWnah1AaNl7kxsa7cfLhlTYoiyhDAIgyh+El30YvXs/o7OLXpYH88Zdhyx9JExKrmHDJ+10bwIcY80Jmw==", "dev": true, "dependencies": { @@ -8285,8 +9034,9 @@ } }, "node_modules/node-fetch": { - "version": "2.6.8", - "integrity": "sha512-RZ6dBYuj8dRSfxpUSu+NsdF1dpPpluJxwOp+6IoDp/sH2QNDSvurYsAa+F1WxY2RjA1iP93xhcsUoYbF2XBqVg==", + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.9.tgz", + "integrity": "sha512-DJm/CJkZkRjKKj4Zi4BsKVZh3ValV5IR5s7LVZnW+6YMh0W1BfNA8XSs6DLMGYlId5F3KnA70uu2qepcR08Qqg==", "dev": true, "dependencies": { "whatwg-url": "^5.0.0" @@ -8305,6 +9055,7 @@ }, "node_modules/node-gyp": { "version": "9.3.1", + "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-9.3.1.tgz", "integrity": "sha512-4Q16ZCqq3g8awk6UplT7AuxQ35XN4R/yf/+wSAwcBUAjg7l58RTactWaP8fIDTi0FzI7YcVLujwExakZlfWkXg==", "dev": true, "dependencies": { @@ -8328,11 +9079,13 @@ }, "node_modules/node-int64": { "version": "0.4.0", + "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==", "dev": true }, "node_modules/node-preload": { "version": "0.2.1", + "resolved": "https://registry.npmjs.org/node-preload/-/node-preload-0.2.1.tgz", "integrity": "sha512-RM5oyBy45cLEoHqCeh+MNuFAxO0vTFBLskvQbOKnEE7YTTSN4tbN8QWDIPQ6L+WvKsB/qLEGpYe2ZZ9d4W9OIQ==", "dev": true, "dependencies": { @@ -8343,12 +9096,14 @@ } }, "node_modules/node-releases": { - "version": "2.0.8", - "integrity": "sha512-dFSmB8fFHEH/s81Xi+Y/15DQY6VHW81nXRj86EMSL3lmuTmK1e+aT4wrFCkTbm+gSwkw4KpX+rT/pMM2c1mF+A==", + "version": "2.0.10", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.10.tgz", + "integrity": "sha512-5GFldHPXVG/YZmFzJvKK2zDSzPKhEp0+ZR5SVaoSag9fsL5YgHbUHDfnG5494ISANDcK4KwPXAx2xqVEydmd7w==", "dev": true }, "node_modules/nodemon": { "version": "2.0.20", + "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-2.0.20.tgz", "integrity": "sha512-Km2mWHKKY5GzRg6i1j5OxOHQtuvVsgskLfigG25yTtbyfRGn/GNvIbRyOf1PSCKJ2aT/58TiuUsuOU5UToVViw==", "dependencies": { "chokidar": "^3.5.2", @@ -8375,6 +9130,7 @@ }, "node_modules/nodemon/node_modules/debug": { "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", "dependencies": { "ms": "^2.1.1" @@ -8382,6 +9138,7 @@ }, "node_modules/nodemon/node_modules/has-flag": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", "engines": { "node": ">=4" @@ -8389,6 +9146,7 @@ }, "node_modules/nodemon/node_modules/semver": { "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", "bin": { "semver": "bin/semver" @@ -8396,6 +9154,7 @@ }, "node_modules/nodemon/node_modules/supports-color": { "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", "dependencies": { "has-flag": "^3.0.0" @@ -8406,6 +9165,7 @@ }, "node_modules/noms": { "version": "0.0.0", + "resolved": "https://registry.npmjs.org/noms/-/noms-0.0.0.tgz", "integrity": "sha512-lNDU9VJaOPxUmXcLb+HQFeUgQQPtMI24Gt6hgfuMHRJgMRHMF/qZ4HJD3GDru4sSw9IQl2jPjAYnQrdIeLbwow==", "dev": true, "dependencies": { @@ -8415,11 +9175,13 @@ }, "node_modules/noms/node_modules/isarray": { "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==", "dev": true }, "node_modules/noms/node_modules/readable-stream": { "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", "integrity": "sha512-ok1qVCJuRkNmvebYikljxJA/UEsKwLl2nI1OmaqAu4/UE+h0wKCHok4XkL/gvi39OacXvw59RJUOFUkDib2rHg==", "dev": true, "dependencies": { @@ -8431,11 +9193,13 @@ }, "node_modules/noms/node_modules/string_decoder": { "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", "integrity": "sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ==", "dev": true }, "node_modules/nopt": { "version": "6.0.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-6.0.0.tgz", "integrity": "sha512-ZwLpbTgdhuZUnZzjd7nb1ZV+4DoiC6/sfiVKok72ym/4Tlf+DFdlHYmT2JPmcNNWV6Pi3SDf1kT+A4r9RTuT9g==", "dev": true, "dependencies": { @@ -8450,6 +9214,7 @@ }, "node_modules/normalize-package-data": { "version": "3.0.3", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-3.0.3.tgz", "integrity": "sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==", "dev": true, "dependencies": { @@ -8464,6 +9229,7 @@ }, "node_modules/normalize-path": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", "engines": { "node": ">=0.10.0" @@ -8471,6 +9237,7 @@ }, "node_modules/normalize-url": { "version": "4.5.1", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.1.tgz", "integrity": "sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA==", "dev": true, "engines": { @@ -8479,6 +9246,7 @@ }, "node_modules/npm-bundle": { "version": "3.0.3", + "resolved": "https://registry.npmjs.org/npm-bundle/-/npm-bundle-3.0.3.tgz", "integrity": "sha512-fHF7FR32YNgjqi0MQMLnE78Ff9/wYd4/7/Cke3dLLi2QzETKotIiWGCxwDoXAZDWVoTuVRYQa2ZdiZPuBL7QnA==", "dev": true, "dependencies": { @@ -8494,6 +9262,7 @@ }, "node_modules/npm-bundle/node_modules/glob": { "version": "6.0.4", + "resolved": "https://registry.npmjs.org/glob/-/glob-6.0.4.tgz", "integrity": "sha512-MKZeRNyYZAVVVG1oZeLaWie1uweH40m9AZwIwxyPbTSX4hHrVYSzLg0Ro5Z5R7XKkIX+Cc6oD1rqeDJnwsB8/A==", "dev": true, "dependencies": { @@ -8509,6 +9278,7 @@ }, "node_modules/npm-bundle/node_modules/rimraf": { "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", "dev": true, "dependencies": { @@ -8520,6 +9290,7 @@ }, "node_modules/npm-bundle/node_modules/rimraf/node_modules/glob": { "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", "dev": true, "dependencies": { @@ -8539,14 +9310,22 @@ }, "node_modules/npm-bundled": { "version": "1.1.2", + "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-1.1.2.tgz", "integrity": "sha512-x5DHup0SuyQcmL3s7Rx/YQ8sbw/Hzg0rj48eN0dV7hf5cmQq5PXIeioroH3raV1QC1yh3uTYuMThvEQF3iKgGQ==", "dev": true, "dependencies": { "npm-normalize-package-bin": "^1.0.1" } }, + "node_modules/npm-bundled/node_modules/npm-normalize-package-bin": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-1.0.1.tgz", + "integrity": "sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA==", + "dev": true + }, "node_modules/npm-check-updates": { "version": "12.5.12", + "resolved": "https://registry.npmjs.org/npm-check-updates/-/npm-check-updates-12.5.12.tgz", "integrity": "sha512-JAFs+kKokZmYPRzhSHgIpKashX6vSGGXYo0VJXNaKV/nLnq3ZKI0nTVou9OwTix+PFfLAWTEJ6T/byGxkDlhWA==", "dev": true, "dependencies": { @@ -8590,6 +9369,7 @@ }, "node_modules/npm-check-updates/node_modules/brace-expansion": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", "dev": true, "dependencies": { @@ -8598,6 +9378,7 @@ }, "node_modules/npm-check-updates/node_modules/chalk": { "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, "dependencies": { @@ -8613,14 +9394,32 @@ }, "node_modules/npm-check-updates/node_modules/commander": { "version": "9.5.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-9.5.0.tgz", "integrity": "sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==", "dev": true, "engines": { "node": "^12.20.0 || >=14" } }, + "node_modules/npm-check-updates/node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/npm-check-updates/node_modules/hosted-git-info": { "version": "5.2.1", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-5.2.1.tgz", "integrity": "sha512-xIcQYMnhcx2Nr4JTjsFmwwnr9vldugPy9uVm0o87bjqqWMv9GaqsTeT+i99wTl0mk1uLxJtHxLb8kymqTENQsw==", "dev": true, "dependencies": { @@ -8630,9 +9429,25 @@ "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, + "node_modules/npm-check-updates/node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/npm-check-updates/node_modules/lru-cache": { - "version": "7.14.1", - "integrity": "sha512-ysxwsnTKdAx96aTRdhDOCQfDgbHnt8SK0KY8SEjO0wHinhWOFTESbjVCMPbU1uGXg/ch4lifqx0wfjOawU2+WA==", + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", + "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", "dev": true, "engines": { "node": ">=12" @@ -8640,6 +9455,7 @@ }, "node_modules/npm-check-updates/node_modules/minimatch": { "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", "dev": true, "dependencies": { @@ -8649,12 +9465,28 @@ "node": ">=10" } }, - "node_modules/npm-check-updates/node_modules/p-map": { - "version": "4.0.0", - "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", + "node_modules/npm-check-updates/node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", "dev": true, "dependencies": { - "aggregate-error": "^3.0.0" + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/npm-check-updates/node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "dependencies": { + "p-limit": "^3.0.2" }, "engines": { "node": ">=10" @@ -8665,6 +9497,7 @@ }, "node_modules/npm-install-checks": { "version": "5.0.0", + "resolved": "https://registry.npmjs.org/npm-install-checks/-/npm-install-checks-5.0.0.tgz", "integrity": "sha512-65lUsMI8ztHCxFz5ckCEC44DRvEGdZX5usQFriauxHEwt7upv1FKaQEmAtU0YnOAdwuNWCmk64xYiQABNrEyLA==", "dev": true, "dependencies": { @@ -8675,12 +9508,17 @@ } }, "node_modules/npm-normalize-package-bin": { - "version": "1.0.1", - "integrity": "sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA==", - "dev": true + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-2.0.0.tgz", + "integrity": "sha512-awzfKUO7v0FscrSpRoogyNm0sajikhBWpU0QMrW09AMi9n1PoKU6WaIqUzuJSQnpciZZmJ/jMZ2Egfmb/9LiWQ==", + "dev": true, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } }, "node_modules/npm-package-arg": { "version": "9.1.2", + "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-9.1.2.tgz", "integrity": "sha512-pzd9rLEx4TfNJkovvlBSLGhq31gGu2QDexFPWT19yCDh0JgnRhlBLNo5759N0AJmBk+kQ9Y/hXoLnlgFD+ukmg==", "dev": true, "dependencies": { @@ -8695,6 +9533,7 @@ }, "node_modules/npm-package-arg/node_modules/hosted-git-info": { "version": "5.2.1", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-5.2.1.tgz", "integrity": "sha512-xIcQYMnhcx2Nr4JTjsFmwwnr9vldugPy9uVm0o87bjqqWMv9GaqsTeT+i99wTl0mk1uLxJtHxLb8kymqTENQsw==", "dev": true, "dependencies": { @@ -8705,8 +9544,9 @@ } }, "node_modules/npm-package-arg/node_modules/lru-cache": { - "version": "7.14.1", - "integrity": "sha512-ysxwsnTKdAx96aTRdhDOCQfDgbHnt8SK0KY8SEjO0wHinhWOFTESbjVCMPbU1uGXg/ch4lifqx0wfjOawU2+WA==", + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", + "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", "dev": true, "engines": { "node": ">=12" @@ -8714,6 +9554,7 @@ }, "node_modules/npm-packlist": { "version": "5.1.3", + "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-5.1.3.tgz", "integrity": "sha512-263/0NGrn32YFYi4J533qzrQ/krmmrWwhKkzwTuM4f/07ug51odoaNjUexxO4vxlzURHcmYMH1QjvHjsNDKLVg==", "dev": true, "dependencies": { @@ -8731,6 +9572,7 @@ }, "node_modules/npm-packlist/node_modules/brace-expansion": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", "dev": true, "dependencies": { @@ -8739,6 +9581,7 @@ }, "node_modules/npm-packlist/node_modules/glob": { "version": "8.1.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", "dev": true, "dependencies": { @@ -8757,6 +9600,7 @@ }, "node_modules/npm-packlist/node_modules/minimatch": { "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", "dev": true, "dependencies": { @@ -8768,6 +9612,7 @@ }, "node_modules/npm-packlist/node_modules/npm-bundled": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-2.0.1.tgz", "integrity": "sha512-gZLxXdjEzE/+mOstGDqR6b0EkhJ+kM6fxM6vUuckuctuVPh80Q6pw/rSZj9s4Gex9GxWtIicO1pc8DB9KZWudw==", "dev": true, "dependencies": { @@ -8777,16 +9622,9 @@ "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, - "node_modules/npm-packlist/node_modules/npm-normalize-package-bin": { - "version": "2.0.0", - "integrity": "sha512-awzfKUO7v0FscrSpRoogyNm0sajikhBWpU0QMrW09AMi9n1PoKU6WaIqUzuJSQnpciZZmJ/jMZ2Egfmb/9LiWQ==", - "dev": true, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, "node_modules/npm-pick-manifest": { "version": "7.0.2", + "resolved": "https://registry.npmjs.org/npm-pick-manifest/-/npm-pick-manifest-7.0.2.tgz", "integrity": "sha512-gk37SyRmlIjvTfcYl6RzDbSmS9Y4TOBXfsPnoYqTHARNgWbyDiCSMLUpmALDj4jjcTZpURiEfsSHJj9k7EV4Rw==", "dev": true, "dependencies": { @@ -8799,16 +9637,9 @@ "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, - "node_modules/npm-pick-manifest/node_modules/npm-normalize-package-bin": { - "version": "2.0.0", - "integrity": "sha512-awzfKUO7v0FscrSpRoogyNm0sajikhBWpU0QMrW09AMi9n1PoKU6WaIqUzuJSQnpciZZmJ/jMZ2Egfmb/9LiWQ==", - "dev": true, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, "node_modules/npm-registry-fetch": { "version": "13.3.1", + "resolved": "https://registry.npmjs.org/npm-registry-fetch/-/npm-registry-fetch-13.3.1.tgz", "integrity": "sha512-eukJPi++DKRTjSBRcDZSDDsGqRK3ehbxfFUcgaRd0Yp6kRwOwh2WVn0r+8rMB4nnuzvAk6rQVzl6K5CkYOmnvw==", "dev": true, "dependencies": { @@ -8826,6 +9657,7 @@ }, "node_modules/npm-run-path": { "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", "dependencies": { "path-key": "^3.0.0" @@ -8836,6 +9668,7 @@ }, "node_modules/npmlog": { "version": "6.0.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-6.0.2.tgz", "integrity": "sha512-/vBvz5Jfr9dT/aFWd0FIRf+T/Q2WBsLENygUaFUqstqsycmZAP/t5BvFJTK0viFmSUxiUKTUplWy5vt+rvKIxg==", "dev": true, "dependencies": { @@ -8850,6 +9683,7 @@ }, "node_modules/number-is-nan": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", "integrity": "sha512-4jbtZXNAsfZbAHiiqjLPBiCl16dES1zI4Hpzzxw61Tk+loF+sBDBKx1ICKKKwIqQ7M0mFn1TmkN7euSncWgHiQ==", "engines": { "node": ">=0.10.0" @@ -8857,6 +9691,7 @@ }, "node_modules/nyc": { "version": "15.1.0", + "resolved": "https://registry.npmjs.org/nyc/-/nyc-15.1.0.tgz", "integrity": "sha512-jMW04n9SxKdKi1ZMGhvUTHBN0EICCRkHemEoE5jm6mTYcqcdas0ATzgUgejlQUHMvpnOZqGB5Xxsv9KxJW1j8A==", "dev": true, "dependencies": { @@ -8897,6 +9732,7 @@ }, "node_modules/nyc/node_modules/cliui": { "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", "dev": true, "dependencies": { @@ -8905,20 +9741,9 @@ "wrap-ansi": "^6.2.0" } }, - "node_modules/nyc/node_modules/find-up": { - "version": "4.1.0", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, - "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/nyc/node_modules/istanbul-lib-instrument": { "version": "4.0.3", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-4.0.3.tgz", "integrity": "sha512-BXgQl9kf4WTCPCCpmFGoJkz/+uhvm7h7PFKUYxh7qarQd3ER33vHG//qaE8eN25l07YqZPpHXU9I09l/RD5aGQ==", "dev": true, "dependencies": { @@ -8931,44 +9756,9 @@ "node": ">=8" } }, - "node_modules/nyc/node_modules/locate-path": { - "version": "5.0.0", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, - "dependencies": { - "p-locate": "^4.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/nyc/node_modules/p-limit": { - "version": "2.3.0", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/nyc/node_modules/p-locate": { - "version": "4.1.0", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, - "dependencies": { - "p-limit": "^2.2.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/nyc/node_modules/p-map": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-3.0.0.tgz", "integrity": "sha512-d3qXVTF/s+W+CdJ5A29wywV2n8CQQYahlgz2bFiA+4eVNJbHJodPZ+/gXwPGh0bOqA+j8S+6+ckmvLGPk1QpxQ==", "dev": true, "dependencies": { @@ -8980,6 +9770,7 @@ }, "node_modules/nyc/node_modules/semver": { "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", "dev": true, "bin": { @@ -8988,6 +9779,7 @@ }, "node_modules/nyc/node_modules/wrap-ansi": { "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", "dev": true, "dependencies": { @@ -9001,11 +9793,13 @@ }, "node_modules/nyc/node_modules/y18n": { "version": "4.0.3", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", "dev": true }, "node_modules/nyc/node_modules/yargs": { "version": "15.4.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", "dev": true, "dependencies": { @@ -9027,6 +9821,7 @@ }, "node_modules/nyc/node_modules/yargs-parser": { "version": "18.1.3", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", "dev": true, "dependencies": { @@ -9039,6 +9834,7 @@ }, "node_modules/oauth-sign": { "version": "0.9.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", "engines": { "node": "*" @@ -9046,6 +9842,7 @@ }, "node_modules/object-assign": { "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", "engines": { "node": ">=0.10.0" @@ -9053,6 +9850,7 @@ }, "node_modules/object-inspect": { "version": "1.12.3", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz", "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==", "funding": { "url": "https://github.com/sponsors/ljharb" @@ -9060,6 +9858,7 @@ }, "node_modules/once": { "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", "dependencies": { "wrappy": "1" @@ -9067,6 +9866,7 @@ }, "node_modules/onetime": { "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", "dependencies": { "mimic-fn": "^2.1.0" @@ -9080,6 +9880,7 @@ }, "node_modules/ono": { "version": "4.0.11", + "resolved": "https://registry.npmjs.org/ono/-/ono-4.0.11.tgz", "integrity": "sha512-jQ31cORBFE6td25deYeD80wxKBMj+zBmHTrVxnc6CKhx8gho6ipmWM5zj/oeoqioZ99yqBls9Z/9Nss7J26G2g==", "dev": true, "dependencies": { @@ -9088,6 +9889,7 @@ }, "node_modules/open": { "version": "8.4.0", + "resolved": "https://registry.npmjs.org/open/-/open-8.4.0.tgz", "integrity": "sha512-XgFPPM+B28FtCCgSb9I+s9szOC1vZRSwgWsRUA5ylIxRTgKozqjOCrVOqGsYABPYK5qnfqClxZTFBa8PKt2v6Q==", "dependencies": { "define-lazy-prop": "^2.0.0", @@ -9103,6 +9905,7 @@ }, "node_modules/openapi3-ts": { "version": "2.0.2", + "resolved": "https://registry.npmjs.org/openapi3-ts/-/openapi3-ts-2.0.2.tgz", "integrity": "sha512-TxhYBMoqx9frXyOgnRHufjQfPXomTIHYKhSKJ6jHfj13kS8OEIhvmE8CTuQyKtjjWttAjX5DPxM1vmalEpo8Qw==", "dev": true, "dependencies": { @@ -9111,6 +9914,7 @@ }, "node_modules/ora": { "version": "3.4.0", + "resolved": "https://registry.npmjs.org/ora/-/ora-3.4.0.tgz", "integrity": "sha512-eNwHudNbO1folBP3JsZ19v9azXWtQZjICdr3Q0TDPIaeBQ3mXLrh54wM+er0+hSp+dWKf+Z8KM58CYzEyIYxYg==", "dependencies": { "chalk": "^2.4.2", @@ -9126,6 +9930,7 @@ }, "node_modules/ora/node_modules/ansi-regex": { "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz", "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==", "engines": { "node": ">=6" @@ -9133,6 +9938,7 @@ }, "node_modules/ora/node_modules/ansi-styles": { "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", "dependencies": { "color-convert": "^1.9.0" @@ -9143,6 +9949,7 @@ }, "node_modules/ora/node_modules/chalk": { "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "dependencies": { "ansi-styles": "^3.2.1", @@ -9155,6 +9962,7 @@ }, "node_modules/ora/node_modules/cli-cursor": { "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", "integrity": "sha512-8lgKz8LmCRYZZQDpRyT2m5rKJ08TnU4tR9FFFW2rxpxR1FzWi4PQ/NfyODchAatHaUgnSPVcx/R5w6NuTBzFiw==", "dependencies": { "restore-cursor": "^2.0.0" @@ -9165,6 +9973,7 @@ }, "node_modules/ora/node_modules/color-convert": { "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", "dependencies": { "color-name": "1.1.3" @@ -9172,10 +9981,12 @@ }, "node_modules/ora/node_modules/color-name": { "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" }, "node_modules/ora/node_modules/has-flag": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", "engines": { "node": ">=4" @@ -9183,6 +9994,7 @@ }, "node_modules/ora/node_modules/log-symbols": { "version": "2.2.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz", "integrity": "sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==", "dependencies": { "chalk": "^2.0.1" @@ -9193,6 +10005,7 @@ }, "node_modules/ora/node_modules/mimic-fn": { "version": "1.2.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", "engines": { "node": ">=4" @@ -9200,6 +10013,7 @@ }, "node_modules/ora/node_modules/onetime": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", "integrity": "sha512-oyyPpiMaKARvvcgip+JV+7zci5L8D1W9RZIz2l1o08AM3pfspitVWnPt3mzHcBPp12oYMTy0pqrFs/C+m3EwsQ==", "dependencies": { "mimic-fn": "^1.0.0" @@ -9210,6 +10024,7 @@ }, "node_modules/ora/node_modules/restore-cursor": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", "integrity": "sha512-6IzJLuGi4+R14vwagDHX+JrXmPVtPpn4mffDJ1UdR7/Edm87fl6yi8mMBIVvFtJaNTUvjughmW4hwLhRG7gC1Q==", "dependencies": { "onetime": "^2.0.0", @@ -9221,6 +10036,7 @@ }, "node_modules/ora/node_modules/strip-ansi": { "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", "dependencies": { "ansi-regex": "^4.1.0" @@ -9231,6 +10047,7 @@ }, "node_modules/ora/node_modules/supports-color": { "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", "dependencies": { "has-flag": "^3.0.0" @@ -9241,6 +10058,7 @@ }, "node_modules/os-tmpdir": { "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", "integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==", "engines": { "node": ">=0.10.0" @@ -9248,6 +10066,7 @@ }, "node_modules/p-cancelable": { "version": "1.1.0", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-1.1.0.tgz", "integrity": "sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw==", "dev": true, "engines": { @@ -9255,25 +10074,38 @@ } }, "node_modules/p-limit": { - "version": "3.1.0", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", "dev": true, "dependencies": { - "yocto-queue": "^0.1.0" + "p-try": "^2.0.0" }, "engines": { - "node": ">=10" + "node": ">=6" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/p-locate": { - "version": "5.0.0", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", "dev": true, "dependencies": { - "p-limit": "^3.0.2" + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/p-map": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", + "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", + "dependencies": { + "aggregate-error": "^3.0.0" }, "engines": { "node": ">=10" @@ -9282,15 +10114,9 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/p-map": { - "version": "2.1.0", - "integrity": "sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==", - "engines": { - "node": ">=6" - } - }, "node_modules/p-try": { "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", "dev": true, "engines": { @@ -9299,6 +10125,7 @@ }, "node_modules/package-hash": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/package-hash/-/package-hash-4.0.0.tgz", "integrity": "sha512-whdkPIooSu/bASggZ96BWVvZTRMOFxnyUG5PnTSGKoJE2gd5mbVNmR2Nj20QFzxYYgAXpoqC+AiXzl+UMRh7zQ==", "dev": true, "dependencies": { @@ -9313,6 +10140,7 @@ }, "node_modules/package-json": { "version": "6.5.0", + "resolved": "https://registry.npmjs.org/package-json/-/package-json-6.5.0.tgz", "integrity": "sha512-k3bdm2n25tkyxcjSKzB5x8kfVxlMdgsbPr0GkZcwHsLpba6cBjqCt1KlcChKEvxHIcTB1FVMuwoijZ26xex5MQ==", "dev": true, "dependencies": { @@ -9327,6 +10155,7 @@ }, "node_modules/package-json/node_modules/semver": { "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", "dev": true, "bin": { @@ -9335,6 +10164,7 @@ }, "node_modules/pacote": { "version": "13.6.2", + "resolved": "https://registry.npmjs.org/pacote/-/pacote-13.6.2.tgz", "integrity": "sha512-Gu8fU3GsvOPkak2CkbojR7vjs3k3P9cA6uazKTHdsdV0gpCEQq2opelnEv30KRQWgVzP5Vd/5umjcedma3MKtg==", "dev": true, "dependencies": { @@ -9369,6 +10199,7 @@ }, "node_modules/pacote/node_modules/mkdirp": { "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", "dev": true, "bin": { @@ -9380,6 +10211,7 @@ }, "node_modules/parent-module": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", "dev": true, "dependencies": { @@ -9391,6 +10223,7 @@ }, "node_modules/parse-github-url": { "version": "1.0.2", + "resolved": "https://registry.npmjs.org/parse-github-url/-/parse-github-url-1.0.2.tgz", "integrity": "sha512-kgBf6avCbO3Cn6+RnzRGLkUsv4ZVqv/VfAYkRsyBcgkshNvVBkRn1FEZcW0Jb+npXQWm2vHPnnOqFteZxRRGNw==", "dev": true, "bin": { @@ -9402,6 +10235,7 @@ }, "node_modules/parse-json": { "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", "dev": true, "dependencies": { @@ -9419,6 +10253,7 @@ }, "node_modules/parse-prefer-header": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/parse-prefer-header/-/parse-prefer-header-1.0.0.tgz", "integrity": "sha512-+WJ3ncCrKOExuxF06XyKWS8bLkLttnlm6YPMZIFIUXNd09Xy0N2JISudxCaY+luDm43yTnHMHVU3zte4G2gN4g==", "dev": true, "dependencies": { @@ -9427,6 +10262,7 @@ }, "node_modules/path-exists": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", "dev": true, "engines": { @@ -9435,6 +10271,7 @@ }, "node_modules/path-is-absolute": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", "engines": { "node": ">=0.10.0" @@ -9442,6 +10279,7 @@ }, "node_modules/path-key": { "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", "engines": { "node": ">=8" @@ -9449,10 +10287,12 @@ }, "node_modules/path-parse": { "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" }, "node_modules/path-to-regexp": { "version": "1.8.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz", "integrity": "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==", "dev": true, "dependencies": { @@ -9461,11 +10301,13 @@ }, "node_modules/path-to-regexp/node_modules/isarray": { "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==", "dev": true }, "node_modules/path-type": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", "dev": true, "engines": { @@ -9474,6 +10316,7 @@ }, "node_modules/pathval": { "version": "1.1.1", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", "dev": true, "engines": { @@ -9482,15 +10325,18 @@ }, "node_modules/performance-now": { "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", "integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==" }, "node_modules/picocolors": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", "dev": true }, "node_modules/picomatch": { "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", "engines": { "node": ">=8.6" @@ -9501,6 +10347,7 @@ }, "node_modules/pidtree": { "version": "0.5.0", + "resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.5.0.tgz", "integrity": "sha512-9nxspIM7OpZuhBxPg73Zvyq7j1QMPMPsGKTqRc2XOaFQauDvoNz9fM1Wdkjmeo7l9GXOZiRs97sPkuayl39wjA==", "bin": { "pidtree": "bin/pidtree.js" @@ -9511,6 +10358,7 @@ }, "node_modules/pify": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==", "dev": true, "engines": { @@ -9519,6 +10367,7 @@ }, "node_modules/pino": { "version": "6.14.0", + "resolved": "https://registry.npmjs.org/pino/-/pino-6.14.0.tgz", "integrity": "sha512-iuhEDel3Z3hF9Jfe44DPXR8l07bhjuFY3GMHIXbjnY9XcafbyDDwl2sN2vw2GjMPf5Nkoe+OFao7ffn9SXaKDg==", "dev": true, "dependencies": { @@ -9536,11 +10385,13 @@ }, "node_modules/pino-std-serializers": { "version": "3.2.0", + "resolved": "https://registry.npmjs.org/pino-std-serializers/-/pino-std-serializers-3.2.0.tgz", "integrity": "sha512-EqX4pwDPrt3MuOAAUBMU0Tk5kR/YcCM5fNPEzgCO2zJ5HfX0vbiH9HbJglnyeQsN96Kznae6MWD47pZB5avTrg==", "dev": true }, "node_modules/pirates": { "version": "4.0.5", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.5.tgz", "integrity": "sha512-8V9+HQPupnaXMA23c5hvl69zXvTwTzyAYasnkb0Tts4XvO4CliqONMOnvlq26rkhLC3nWDFBJf73LU1e1VZLaQ==", "dev": true, "engines": { @@ -9549,6 +10400,7 @@ }, "node_modules/pkg-conf": { "version": "2.1.0", + "resolved": "https://registry.npmjs.org/pkg-conf/-/pkg-conf-2.1.0.tgz", "integrity": "sha512-C+VUP+8jis7EsQZIhDYmS5qlNtjv2yP4SNtjXK9AP1ZcTRlnSfuumaTnRfYZnYgUUYVIKqL0fRvmUGDV2fmp6g==", "dev": true, "dependencies": { @@ -9561,6 +10413,7 @@ }, "node_modules/pkg-conf/node_modules/find-up": { "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", "integrity": "sha512-NWzkk0jSJtTt08+FBFMvXoeZnOJD+jTtsRmBYbAIzJdX6l7dLgR7CTubCM5/eDdPUBvLCeVasP1brfVR/9/EZQ==", "dev": true, "dependencies": { @@ -9572,6 +10425,7 @@ }, "node_modules/pkg-conf/node_modules/locate-path": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", "integrity": "sha512-NCI2kiDkyR7VeEKm27Kda/iQHyKJe1Bu0FlTbYp3CqJu+9IFe9bLyAjMxf5ZDDbEg+iMPzB5zYyUTSm8wVTKmA==", "dev": true, "dependencies": { @@ -9584,6 +10438,7 @@ }, "node_modules/pkg-conf/node_modules/p-limit": { "version": "1.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", "dev": true, "dependencies": { @@ -9595,6 +10450,7 @@ }, "node_modules/pkg-conf/node_modules/p-locate": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", "integrity": "sha512-nQja7m7gSKuewoVRen45CtVfODR3crN3goVQ0DDZ9N3yHxgpkuBhZqsaiotSQRrADUrne346peY7kT3TSACykg==", "dev": true, "dependencies": { @@ -9606,6 +10462,7 @@ }, "node_modules/pkg-conf/node_modules/p-try": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", "integrity": "sha512-U1etNYuMJoIz3ZXSrrySFjsXQTWOx2/jdi86L+2pRvph/qMKL6sbcCYdH23fqsbm8TH2Gn0OybpT4eSFlCVHww==", "dev": true, "engines": { @@ -9614,6 +10471,7 @@ }, "node_modules/pkg-conf/node_modules/path-exists": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", "dev": true, "engines": { @@ -9622,6 +10480,7 @@ }, "node_modules/pkg-dir": { "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", "dev": true, "dependencies": { @@ -9631,56 +10490,9 @@ "node": ">=8" } }, - "node_modules/pkg-dir/node_modules/find-up": { - "version": "4.1.0", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, - "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/pkg-dir/node_modules/locate-path": { - "version": "5.0.0", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, - "dependencies": { - "p-locate": "^4.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/pkg-dir/node_modules/p-limit": { - "version": "2.3.0", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/pkg-dir/node_modules/p-locate": { - "version": "4.1.0", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, - "dependencies": { - "p-limit": "^2.2.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/portscanner": { "version": "2.2.0", + "resolved": "https://registry.npmjs.org/portscanner/-/portscanner-2.2.0.tgz", "integrity": "sha512-IFroCz/59Lqa2uBvzK3bKDbDDIEaAY8XJ1jFxcLWTqosrsc32//P4VuSB2vZXoHiHqOmx8B5L5hnKOxL/7FlPw==", "dependencies": { "async": "^2.6.0", @@ -9693,6 +10505,7 @@ }, "node_modules/postman-collection": { "version": "4.1.3", + "resolved": "https://registry.npmjs.org/postman-collection/-/postman-collection-4.1.3.tgz", "integrity": "sha512-shoe2I/GGiigsdlU5+crS2frEJqQ6tgCck1+9aaPN9pQ3Kj7bt7NJdcqrn26ScciCfQymzSLG7TL9ZQZc6i05w==", "dev": true, "dependencies": { @@ -9714,6 +10527,7 @@ }, "node_modules/postman-collection/node_modules/iconv-lite": { "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", "dev": true, "dependencies": { @@ -9723,19 +10537,9 @@ "node": ">=0.10.0" } }, - "node_modules/postman-collection/node_modules/lru-cache": { - "version": "6.0.0", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/postman-collection/node_modules/semver": { "version": "7.3.7", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", "dev": true, "dependencies": { @@ -9748,13 +10552,9 @@ "node": ">=10" } }, - "node_modules/postman-collection/node_modules/yallist": { - "version": "4.0.0", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, "node_modules/postman-url-encoder": { "version": "3.0.5", + "resolved": "https://registry.npmjs.org/postman-url-encoder/-/postman-url-encoder-3.0.5.tgz", "integrity": "sha512-jOrdVvzUXBC7C+9gkIkpDJ3HIxOHTIqjpQ4C1EMt1ZGeMvSEpbFCKq23DEfgsj46vMnDgyQf+1ZLp2Wm+bKSsA==", "dev": true, "dependencies": { @@ -9766,6 +10566,7 @@ }, "node_modules/prepend-http": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz", "integrity": "sha512-ravE6m9Atw9Z/jjttRUZ+clIXogdghyZAuWJ3qEzjT+jI/dL1ifAqhZeC5VHzQp1MSt1+jxKkFNemj/iO7tVUA==", "dev": true, "engines": { @@ -9774,6 +10575,7 @@ }, "node_modules/prettier": { "version": "2.8.3", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.3.tgz", "integrity": "sha512-tJ/oJ4amDihPoufT5sM0Z1SKEuKay8LfVAMlbbhnnkvt6BUserZylqo2PN+p9KeljLr0OHa2rXHU1T8reeoTrw==", "dev": true, "bin": { @@ -9788,6 +10590,7 @@ }, "node_modules/pretty-bytes": { "version": "5.6.0", + "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-5.6.0.tgz", "integrity": "sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg==", "engines": { "node": ">=6" @@ -9798,6 +10601,7 @@ }, "node_modules/pretty-data": { "version": "0.40.0", + "resolved": "https://registry.npmjs.org/pretty-data/-/pretty-data-0.40.0.tgz", "integrity": "sha512-YFLnEdDEDnkt/GEhet5CYZHCvALw6+Elyb/tp8kQG03ZSIuzeaDWpZYndCXwgqu4NAjh1PI534dhDS1mHarRnQ==", "dev": true, "engines": { @@ -9806,6 +10610,7 @@ }, "node_modules/pretty-format": { "version": "28.1.3", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-28.1.3.tgz", "integrity": "sha512-8gFb/To0OmxHR9+ZTb14Df2vNxdGCX8g1xWGUTqUw5TiZvcQf5sHKObd5UcPyLLyowNwDAMTF3XWOG1B6mxl1Q==", "dev": true, "dependencies": { @@ -9820,6 +10625,7 @@ }, "node_modules/pretty-format/node_modules/ansi-styles": { "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", "dev": true, "engines": { @@ -9831,6 +10637,7 @@ }, "node_modules/proc-log": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/proc-log/-/proc-log-2.0.1.tgz", "integrity": "sha512-Kcmo2FhfDTXdcbfDH76N7uBYHINxc/8GW7UAVuVP9I+Va3uHSerrnKV6dLooga/gh7GlgzuCCr/eoldnL1muGw==", "dev": true, "engines": { @@ -9839,10 +10646,12 @@ }, "node_modules/process-nextick-args": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" }, "node_modules/process-on-spawn": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/process-on-spawn/-/process-on-spawn-1.0.0.tgz", "integrity": "sha512-1WsPDsUSMmZH5LeMLegqkPDrsGgsWwk1Exipy2hvB0o/F0ASzbpIctSCcZIK1ykJvtTJULEH+20WOFjMvGnCTg==", "dev": true, "dependencies": { @@ -9854,11 +10663,13 @@ }, "node_modules/process-warning": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/process-warning/-/process-warning-1.0.0.tgz", "integrity": "sha512-du4wfLyj4yCZq1VupnVSZmRsPJsNuxoDQFdCFHLaYiEbFBD7QE0a+I4D7hOxrVnh78QE/YipFAj9lXHiXocV+Q==", "dev": true }, "node_modules/progress": { "version": "2.0.3", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", "dev": true, "engines": { @@ -9867,11 +10678,13 @@ }, "node_modules/promise-inflight": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", "integrity": "sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==", "dev": true }, "node_modules/promise-retry": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz", "integrity": "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==", "dev": true, "dependencies": { @@ -9884,6 +10697,7 @@ }, "node_modules/prompts": { "version": "2.4.2", + "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", "dev": true, "dependencies": { @@ -9896,6 +10710,7 @@ }, "node_modules/proxyquire": { "version": "2.1.3", + "resolved": "https://registry.npmjs.org/proxyquire/-/proxyquire-2.1.3.tgz", "integrity": "sha512-BQWfCqYM+QINd+yawJz23tbBM40VIGXOdDw3X344KcclI/gtBbdWF6SlQ4nK/bYhF9d27KYug9WzljHC6B9Ysg==", "dev": true, "dependencies": { @@ -9906,14 +10721,17 @@ }, "node_modules/psl": { "version": "1.9.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz", "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==" }, "node_modules/pstree.remy": { "version": "1.1.8", + "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz", "integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==" }, "node_modules/pump": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", "dev": true, "dependencies": { @@ -9923,6 +10741,7 @@ }, "node_modules/punycode": { "version": "2.3.0", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", "engines": { "node": ">=6" @@ -9930,6 +10749,7 @@ }, "node_modules/pupa": { "version": "2.1.1", + "resolved": "https://registry.npmjs.org/pupa/-/pupa-2.1.1.tgz", "integrity": "sha512-l1jNAspIBSFqbT+y+5FosojNpVpF94nlI+wDUpqP9enwOTfHx9f0gh5nB96vl+6yTpsJsypeNrwfzPrKuHB41A==", "dev": true, "dependencies": { @@ -9941,6 +10761,7 @@ }, "node_modules/q": { "version": "1.5.1", + "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", "integrity": "sha512-kV/CThkXo6xyFEZUugw/+pIOywXcDbFYgSct5cT3gqlbkBE1SJdwy6UQoZvodiWF/ckQLZyDE/Bu1M6gVu5lVw==", "dev": true, "engines": { @@ -9950,6 +10771,7 @@ }, "node_modules/qs": { "version": "6.5.3", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.3.tgz", "integrity": "sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==", "engines": { "node": ">=0.6" @@ -9957,6 +10779,7 @@ }, "node_modules/querystring": { "version": "0.2.0", + "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", "integrity": "sha512-X/xY82scca2tau62i9mDyU9K+I+djTMUsvwf7xnUX5GLvVzgJybOJf4Y6o9Zx3oJK/LSXg5tTZBjwzqVPaPO2g==", "deprecated": "The querystring API is considered Legacy. new code should use the URLSearchParams API instead.", "engines": { @@ -9965,6 +10788,7 @@ }, "node_modules/queue-microtask": { "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", "dev": true, "funding": [ @@ -9984,11 +10808,13 @@ }, "node_modules/quick-format-unescaped": { "version": "4.0.4", + "resolved": "https://registry.npmjs.org/quick-format-unescaped/-/quick-format-unescaped-4.0.4.tgz", "integrity": "sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==", "dev": true }, "node_modules/quick-lru": { "version": "4.0.1", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-4.0.1.tgz", "integrity": "sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==", "dev": true, "engines": { @@ -9997,6 +10823,7 @@ }, "node_modules/ramda": { "version": "0.28.0", + "resolved": "https://registry.npmjs.org/ramda/-/ramda-0.28.0.tgz", "integrity": "sha512-9QnLuG/kPVgWvMQ4aODhsBUFKOUmnbUnsSXACv+NCQZcHbeb+v8Lodp8OVxtRULN1/xOyYLLaL6npE6dMq5QTA==", "funding": { "type": "opencollective", @@ -10005,6 +10832,7 @@ }, "node_modules/randombytes": { "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", "dev": true, "dependencies": { @@ -10013,6 +10841,7 @@ }, "node_modules/rc": { "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", "dev": true, "dependencies": { @@ -10027,6 +10856,7 @@ }, "node_modules/rc-config-loader": { "version": "4.1.2", + "resolved": "https://registry.npmjs.org/rc-config-loader/-/rc-config-loader-4.1.2.tgz", "integrity": "sha512-qKTnVWFl9OQYKATPzdfaZIbTxcHziQl92zYSxYC6umhOqyAsoj8H8Gq/+aFjAso68sBdjTz3A7omqeAkkF1MWg==", "dev": true, "dependencies": { @@ -10038,6 +10868,7 @@ }, "node_modules/rc/node_modules/strip-json-comments": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", "dev": true, "engines": { @@ -10046,11 +10877,13 @@ }, "node_modules/react-is": { "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", "dev": true }, "node_modules/read-package-json": { "version": "5.0.2", + "resolved": "https://registry.npmjs.org/read-package-json/-/read-package-json-5.0.2.tgz", "integrity": "sha512-BSzugrt4kQ/Z0krro8zhTwV1Kd79ue25IhNN/VtHFy1mG/6Tluyi+msc0UpwaoQzxSHa28mntAjIZY6kEgfR9Q==", "dev": true, "dependencies": { @@ -10065,6 +10898,7 @@ }, "node_modules/read-package-json-fast": { "version": "2.0.3", + "resolved": "https://registry.npmjs.org/read-package-json-fast/-/read-package-json-fast-2.0.3.tgz", "integrity": "sha512-W/BKtbL+dUjTuRL2vziuYhp76s5HZ9qQhd/dKfWIZveD0O40453QNyZhC0e63lqZrAQ4jiOapVoeJ7JrszenQQ==", "dev": true, "dependencies": { @@ -10075,8 +10909,15 @@ "node": ">=10" } }, + "node_modules/read-package-json-fast/node_modules/npm-normalize-package-bin": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-1.0.1.tgz", + "integrity": "sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA==", + "dev": true + }, "node_modules/read-package-json/node_modules/brace-expansion": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", "dev": true, "dependencies": { @@ -10085,6 +10926,7 @@ }, "node_modules/read-package-json/node_modules/glob": { "version": "8.1.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", "dev": true, "dependencies": { @@ -10103,6 +10945,7 @@ }, "node_modules/read-package-json/node_modules/hosted-git-info": { "version": "5.2.1", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-5.2.1.tgz", "integrity": "sha512-xIcQYMnhcx2Nr4JTjsFmwwnr9vldugPy9uVm0o87bjqqWMv9GaqsTeT+i99wTl0mk1uLxJtHxLb8kymqTENQsw==", "dev": true, "dependencies": { @@ -10113,8 +10956,9 @@ } }, "node_modules/read-package-json/node_modules/lru-cache": { - "version": "7.14.1", - "integrity": "sha512-ysxwsnTKdAx96aTRdhDOCQfDgbHnt8SK0KY8SEjO0wHinhWOFTESbjVCMPbU1uGXg/ch4lifqx0wfjOawU2+WA==", + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", + "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", "dev": true, "engines": { "node": ">=12" @@ -10122,6 +10966,7 @@ }, "node_modules/read-package-json/node_modules/minimatch": { "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", "dev": true, "dependencies": { @@ -10133,6 +10978,7 @@ }, "node_modules/read-package-json/node_modules/normalize-package-data": { "version": "4.0.1", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-4.0.1.tgz", "integrity": "sha512-EBk5QKKuocMJhB3BILuKhmaPjI8vNRSpIfO9woLC6NyHVkKKdVEdAO1mrT0ZfxNR1lKwCcTkuZfmGIFdizZ8Pg==", "dev": true, "dependencies": { @@ -10145,16 +10991,9 @@ "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, - "node_modules/read-package-json/node_modules/npm-normalize-package-bin": { - "version": "2.0.0", - "integrity": "sha512-awzfKUO7v0FscrSpRoogyNm0sajikhBWpU0QMrW09AMi9n1PoKU6WaIqUzuJSQnpciZZmJ/jMZ2Egfmb/9LiWQ==", - "dev": true, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, "node_modules/read-pkg": { "version": "5.2.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", "dev": true, "dependencies": { @@ -10169,6 +11008,7 @@ }, "node_modules/read-pkg-up": { "version": "7.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz", "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==", "dev": true, "dependencies": { @@ -10183,56 +11023,9 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/read-pkg-up/node_modules/find-up": { - "version": "4.1.0", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, - "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/read-pkg-up/node_modules/locate-path": { - "version": "5.0.0", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, - "dependencies": { - "p-locate": "^4.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/read-pkg-up/node_modules/p-limit": { - "version": "2.3.0", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/read-pkg-up/node_modules/p-locate": { - "version": "4.1.0", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, - "dependencies": { - "p-limit": "^2.2.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/read-pkg-up/node_modules/type-fest": { "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", "dev": true, "engines": { @@ -10241,11 +11034,13 @@ }, "node_modules/read-pkg/node_modules/hosted-git-info": { "version": "2.8.9", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", "dev": true }, "node_modules/read-pkg/node_modules/normalize-package-data": { "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", "dev": true, "dependencies": { @@ -10257,6 +11052,7 @@ }, "node_modules/read-pkg/node_modules/semver": { "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", "dev": true, "bin": { @@ -10265,6 +11061,7 @@ }, "node_modules/read-pkg/node_modules/type-fest": { "version": "0.6.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", "dev": true, "engines": { @@ -10273,6 +11070,7 @@ }, "node_modules/readable-stream": { "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", "dependencies": { "inherits": "^2.0.3", @@ -10285,6 +11083,7 @@ }, "node_modules/readdir-glob": { "version": "1.1.2", + "resolved": "https://registry.npmjs.org/readdir-glob/-/readdir-glob-1.1.2.tgz", "integrity": "sha512-6RLVvwJtVwEDfPdn6X6Ille4/lxGl0ATOY4FN/B9nxQcgOazvvI0nodiD19ScKq0PvA/29VpaOQML36o5IzZWA==", "dependencies": { "minimatch": "^5.1.0" @@ -10292,6 +11091,7 @@ }, "node_modules/readdir-glob/node_modules/brace-expansion": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", "dependencies": { "balanced-match": "^1.0.0" @@ -10299,6 +11099,7 @@ }, "node_modules/readdir-glob/node_modules/minimatch": { "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", "dependencies": { "brace-expansion": "^2.0.1" @@ -10309,6 +11110,7 @@ }, "node_modules/readdirp": { "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", "dependencies": { "picomatch": "^2.2.1" @@ -10319,6 +11121,7 @@ }, "node_modules/redent": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz", "integrity": "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==", "dev": true, "dependencies": { @@ -10329,16 +11132,9 @@ "node": ">=8" } }, - "node_modules/redent/node_modules/indent-string": { - "version": "4.0.0", - "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/registry-auth-token": { "version": "4.2.2", + "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-4.2.2.tgz", "integrity": "sha512-PC5ZysNb42zpFME6D/XlIgtNGdTl8bBOCw90xQLVMpzuuubJKYDWFAEuUNc+Cn8Z8724tg2SDhDRrkVEsqfDMg==", "dev": true, "dependencies": { @@ -10350,6 +11146,7 @@ }, "node_modules/registry-url": { "version": "5.1.0", + "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-5.1.0.tgz", "integrity": "sha512-8acYXXTI0AkQv6RAOjE3vOaIXZkT9wo4LOFbBKYQEEnnMNBpKqdUrI6S4NT0KPIo/WVvJ5tE/X5LF/TQUf0ekw==", "dev": true, "dependencies": { @@ -10361,6 +11158,7 @@ }, "node_modules/release-zalgo": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/release-zalgo/-/release-zalgo-1.0.0.tgz", "integrity": "sha512-gUAyHVHPPC5wdqX/LG4LWtRYtgjxyX78oanFNTMMyFEfOqdC54s3eE82imuWKbOeqYht2CrNf64Qb8vgmmtZGA==", "dev": true, "dependencies": { @@ -10372,6 +11170,7 @@ }, "node_modules/remote-git-tags": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/remote-git-tags/-/remote-git-tags-3.0.0.tgz", "integrity": "sha512-C9hAO4eoEsX+OXA4rla66pXZQ+TLQ8T9dttgQj18yuKlPMTVkIkdYXvlMC55IuUsIkV6DpmQYi10JKFLaU+l7w==", "dev": true, "engines": { @@ -10380,6 +11179,7 @@ }, "node_modules/request": { "version": "2.88.2", + "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", "deprecated": "request has been deprecated, see https://github.com/request/request/issues/3142", "dependencies": { @@ -10410,6 +11210,7 @@ }, "node_modules/request/node_modules/uuid": { "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", "bin": { @@ -10418,6 +11219,7 @@ }, "node_modules/require-directory": { "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", "engines": { "node": ">=0.10.0" @@ -10425,6 +11227,7 @@ }, "node_modules/require-from-string": { "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", "engines": { "node": ">=0.10.0" @@ -10432,11 +11235,13 @@ }, "node_modules/require-main-filename": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", "dev": true }, "node_modules/resolve": { "version": "1.22.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", "dependencies": { "is-core-module": "^2.9.0", @@ -10452,6 +11257,7 @@ }, "node_modules/resolve-from": { "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", "dev": true, "engines": { @@ -10460,6 +11266,7 @@ }, "node_modules/resolve-global": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/resolve-global/-/resolve-global-1.0.0.tgz", "integrity": "sha512-zFa12V4OLtT5XUX/Q4VLvTfBf+Ok0SPc1FNGM/z9ctUdiU618qwKpWnd0CHs3+RqROfyEg/DhuHbMWYqcgljEw==", "dev": true, "dependencies": { @@ -10471,6 +11278,7 @@ }, "node_modules/responselike": { "version": "1.0.2", + "resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz", "integrity": "sha512-/Fpe5guzJk1gPqdJLJR5u7eG/gNY4nImjbRDaVWVMRhne55TCmj2i9Q+54PBRfatRC8v/rIiv9BN0pMd9OV5EQ==", "dev": true, "dependencies": { @@ -10479,6 +11287,7 @@ }, "node_modules/restore-cursor": { "version": "3.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", "dependencies": { "onetime": "^5.1.0", @@ -10490,6 +11299,7 @@ }, "node_modules/retry": { "version": "0.12.0", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==", "dev": true, "engines": { @@ -10498,6 +11308,7 @@ }, "node_modules/reusify": { "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", "dev": true, "engines": { @@ -10507,10 +11318,12 @@ }, "node_modules/rfdc": { "version": "1.3.0", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz", "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==" }, "node_modules/rimraf": { "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", "dependencies": { "glob": "^7.1.3" @@ -10524,6 +11337,7 @@ }, "node_modules/run-async": { "version": "2.4.1", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz", "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==", "engines": { "node": ">=0.12.0" @@ -10531,6 +11345,7 @@ }, "node_modules/run-parallel": { "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", "dev": true, "funding": [ @@ -10553,6 +11368,7 @@ }, "node_modules/rxjs": { "version": "7.8.0", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.0.tgz", "integrity": "sha512-F2+gxDshqmIub1KdvZkaEfGDwLNpPvk9Fs6LD/MyQxNgMds/WH9OdDDXOmxUZpME+iSK3rQCctkL0DYyytUqMg==", "dependencies": { "tslib": "^2.1.0" @@ -10560,6 +11376,7 @@ }, "node_modules/safe-buffer": { "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", "funding": [ { @@ -10578,24 +11395,29 @@ }, "node_modules/safe-json-stringify": { "version": "1.2.0", + "resolved": "https://registry.npmjs.org/safe-json-stringify/-/safe-json-stringify-1.2.0.tgz", "integrity": "sha512-gH8eh2nZudPQO6TytOvbxnuhYBOvDBBLW52tz5q6X58lJcd/tkmqFR+5Z9adS8aJtURSXWThWy/xJtJwixErvg==", "optional": true }, "node_modules/safe-stable-stringify": { "version": "1.1.1", + "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-1.1.1.tgz", "integrity": "sha512-ERq4hUjKDbJfE4+XtZLFPCDi8Vb1JqaxAPTxWFLBx8XcAlf9Bda/ZJdVezs/NAfsMQScyIlUMx+Yeu7P7rx5jw==", "dev": true }, "node_modules/safer-buffer": { "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, "node_modules/sax": { "version": "1.2.1", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.1.tgz", "integrity": "sha512-8I2a3LovHTOpm7NV5yOyO8IHqgVsfK4+UuySrXU8YXkSRX7k6hCV9b3HrkKCr3nMpgj+0bmocaJJWpvp1oc7ZA==" }, "node_modules/semaphore": { "version": "1.1.0", + "resolved": "https://registry.npmjs.org/semaphore/-/semaphore-1.1.0.tgz", "integrity": "sha512-O4OZEaNtkMd/K0i6js9SL+gqy0ZCBMgUvlSqHKi4IBdjhe7wB8pwztUk1BbZ1fmrvpwFrPbHzqd2w5pTcJH6LA==", "dev": true, "engines": { @@ -10604,6 +11426,7 @@ }, "node_modules/semver": { "version": "7.3.8", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", "dependencies": { "lru-cache": "^6.0.0" @@ -10617,6 +11440,7 @@ }, "node_modules/semver-diff": { "version": "3.1.1", + "resolved": "https://registry.npmjs.org/semver-diff/-/semver-diff-3.1.1.tgz", "integrity": "sha512-GX0Ix/CJcHyB8c4ykpHGIAvLyOwOobtM/8d+TQkAd81/bEjgPHrfba41Vpesr7jX/t8Uh+R3EX9eAS5be+jQYg==", "dev": true, "dependencies": { @@ -10628,6 +11452,7 @@ }, "node_modules/semver-diff/node_modules/semver": { "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", "dev": true, "bin": { @@ -10636,11 +11461,13 @@ }, "node_modules/semver-utils": { "version": "1.1.4", + "resolved": "https://registry.npmjs.org/semver-utils/-/semver-utils-1.1.4.tgz", "integrity": "sha512-EjnoLE5OGmDAVV/8YDoN5KiajNadjzIp9BAHOhYeQHt7j0UWxjmgsx4YD48wp4Ue1Qogq38F1GNUJNqF1kKKxA==", "dev": true }, "node_modules/semver/node_modules/lru-cache": { "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", "dependencies": { "yallist": "^4.0.0" @@ -10651,10 +11478,12 @@ }, "node_modules/semver/node_modules/yallist": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" }, "node_modules/serialize-javascript": { "version": "6.0.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", "dev": true, "dependencies": { @@ -10663,16 +11492,19 @@ }, "node_modules/set-blocking": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", "dev": true }, "node_modules/setimmediate": { "version": "1.0.5", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==", "dev": true }, "node_modules/shebang-command": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", "dependencies": { "shebang-regex": "^3.0.0" @@ -10683,6 +11515,7 @@ }, "node_modules/shebang-regex": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", "engines": { "node": ">=8" @@ -10690,10 +11523,12 @@ }, "node_modules/signal-exit": { "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" }, "node_modules/signale": { "version": "1.4.0", + "resolved": "https://registry.npmjs.org/signale/-/signale-1.4.0.tgz", "integrity": "sha512-iuh+gPf28RkltuJC7W5MRi6XAjTDCAPC/prJUpQoG4vIP3MJZ+GTydVnodXA7pwvTKb2cA0m9OFZW/cdWy/I/w==", "dev": true, "dependencies": { @@ -10707,6 +11542,7 @@ }, "node_modules/signale/node_modules/ansi-styles": { "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", "dev": true, "dependencies": { @@ -10718,6 +11554,7 @@ }, "node_modules/signale/node_modules/chalk": { "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "dev": true, "dependencies": { @@ -10731,6 +11568,7 @@ }, "node_modules/signale/node_modules/color-convert": { "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", "dev": true, "dependencies": { @@ -10739,11 +11577,13 @@ }, "node_modules/signale/node_modules/color-name": { "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", "dev": true }, "node_modules/signale/node_modules/figures": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", "integrity": "sha512-Oa2M9atig69ZkfwiApY8F2Yy+tzMbazyvqv21R0NsSC8floSOC09BbT1ITWAdoMGQvJ/aZnR1KMwdx9tvHnTNA==", "dev": true, "dependencies": { @@ -10755,6 +11595,7 @@ }, "node_modules/signale/node_modules/has-flag": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", "dev": true, "engines": { @@ -10763,6 +11604,7 @@ }, "node_modules/signale/node_modules/supports-color": { "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", "dev": true, "dependencies": { @@ -10774,6 +11616,7 @@ }, "node_modules/simple-update-notifier": { "version": "1.1.0", + "resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-1.1.0.tgz", "integrity": "sha512-VpsrsJSUcJEseSbMHkrsrAVSdvVS5I96Qo1QAQ4FxQ9wXFcB+pjj7FB7/us9+GcgfW4ziHtYMc1J0PLczb55mg==", "dependencies": { "semver": "~7.0.0" @@ -10784,6 +11627,7 @@ }, "node_modules/simple-update-notifier/node_modules/semver": { "version": "7.0.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.0.0.tgz", "integrity": "sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==", "bin": { "semver": "bin/semver.js" @@ -10791,6 +11635,7 @@ }, "node_modules/sinon": { "version": "13.0.2", + "resolved": "https://registry.npmjs.org/sinon/-/sinon-13.0.2.tgz", "integrity": "sha512-KvOrztAVqzSJWMDoxM4vM+GPys1df2VBoXm+YciyB/OLMamfS3VXh3oGh5WtrAGSzrgczNWFFY22oKb7Fi5eeA==", "dev": true, "dependencies": { @@ -10808,6 +11653,7 @@ }, "node_modules/sinon-chai": { "version": "3.7.0", + "resolved": "https://registry.npmjs.org/sinon-chai/-/sinon-chai-3.7.0.tgz", "integrity": "sha512-mf5NURdUaSdnatJx3uhoBOrY9dtL19fiOtAdT1Azxg3+lNJFiuN0uzaU3xX1LeAfL17kHQhTAJgpsfhbMJMY2g==", "dev": true, "peerDependencies": { @@ -10815,13 +11661,24 @@ "sinon": ">=4.0.0" } }, + "node_modules/sinon/node_modules/diff": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-5.1.0.tgz", + "integrity": "sha512-D+mk+qE8VC/PAUrlAU34N+VfXev0ghe5ywmpqrawphmVZc1bEfn56uo9qpyGp1p4xpzOHkSW4ztBd6L7Xx4ACw==", + "dev": true, + "engines": { + "node": ">=0.3.1" + } + }, "node_modules/sisteransi": { "version": "1.0.5", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", "dev": true }, "node_modules/slash": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", "dev": true, "engines": { @@ -10830,6 +11687,7 @@ }, "node_modules/slice-ansi": { "version": "5.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-5.0.0.tgz", "integrity": "sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==", "dependencies": { "ansi-styles": "^6.0.0", @@ -10844,6 +11702,7 @@ }, "node_modules/slice-ansi/node_modules/ansi-styles": { "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", "engines": { "node": ">=12" @@ -10852,8 +11711,20 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, + "node_modules/slice-ansi/node_modules/is-fullwidth-code-point": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz", + "integrity": "sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/smart-buffer": { "version": "4.2.0", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", "dev": true, "engines": { @@ -10863,6 +11734,7 @@ }, "node_modules/socks": { "version": "2.7.1", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.7.1.tgz", "integrity": "sha512-7maUZy1N7uo6+WVEX6psASxtNlKaNVMlGQKkG/63nEDdLOWNbiUMoLK7X4uYoLhQstau72mLgfEWcXcwsaHbYQ==", "dev": true, "dependencies": { @@ -10876,6 +11748,7 @@ }, "node_modules/socks-proxy-agent": { "version": "7.0.0", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-7.0.0.tgz", "integrity": "sha512-Fgl0YPZ902wEsAyiQ+idGd1A7rSFx/ayC1CQVMw5P+EQx2V0SgpGtf6OKFhVjPflPUl9YMmEOnmfjCdMUsygww==", "dev": true, "dependencies": { @@ -10889,6 +11762,7 @@ }, "node_modules/sonic-boom": { "version": "1.4.1", + "resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-1.4.1.tgz", "integrity": "sha512-LRHh/A8tpW7ru89lrlkU4AszXt1dbwSjVWguGrmlxE7tawVmDBlI1PILMkXAxJTwqhgsEeTHzj36D5CmHgQmNg==", "dev": true, "dependencies": { @@ -10898,6 +11772,7 @@ }, "node_modules/source-map": { "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "engines": { "node": ">=0.10.0" @@ -10905,6 +11780,7 @@ }, "node_modules/source-map-support": { "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", "dependencies": { "buffer-from": "^1.0.0", @@ -10913,6 +11789,7 @@ }, "node_modules/spawn-please": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/spawn-please/-/spawn-please-1.0.0.tgz", "integrity": "sha512-Kz33ip6NRNKuyTRo3aDWyWxeGeM0ORDO552Fs6E1nj4pLWPkl37SrRtTnq+MEopVaqgmaO6bAvVS+v64BJ5M/A==", "dev": true, "engines": { @@ -10921,6 +11798,7 @@ }, "node_modules/spawn-wrap": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/spawn-wrap/-/spawn-wrap-2.0.0.tgz", "integrity": "sha512-EeajNjfN9zMnULLwhZZQU3GWBoFNkbngTUPfaawT4RkMiviTxcX0qfhVbGey39mfctfDHkWtuecgQ8NJcyQWHg==", "dev": true, "dependencies": { @@ -10936,8 +11814,9 @@ } }, "node_modules/spdx-correct": { - "version": "3.1.1", - "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz", + "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==", "dev": true, "dependencies": { "spdx-expression-parse": "^3.0.0", @@ -10946,11 +11825,13 @@ }, "node_modules/spdx-exceptions": { "version": "2.3.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", "dev": true }, "node_modules/spdx-expression-parse": { "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", "dev": true, "dependencies": { @@ -10959,12 +11840,14 @@ } }, "node_modules/spdx-license-ids": { - "version": "3.0.12", - "integrity": "sha512-rr+VVSXtRhO4OHbXUiAF7xW3Bo9DuuF6C5jH+q/x15j2jniycgKbxU09Hr0WqlSLUs4i4ltHGXqTe7VHclYWyA==", + "version": "3.0.13", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.13.tgz", + "integrity": "sha512-XkD+zwiqXHikFZm4AX/7JSCXA98U5Db4AFd5XUg/+9UNtnH75+Z9KxtpYiJZx36mUDVOwH83pl7yvCer6ewM3w==", "dev": true }, "node_modules/split": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/split/-/split-1.0.1.tgz", "integrity": "sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg==", "dev": true, "dependencies": { @@ -10976,6 +11859,7 @@ }, "node_modules/split2": { "version": "3.2.2", + "resolved": "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz", "integrity": "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==", "dev": true, "dependencies": { @@ -10984,11 +11868,13 @@ }, "node_modules/sprintf-js": { "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", "dev": true }, "node_modules/sshpk": { "version": "1.17.0", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.17.0.tgz", "integrity": "sha512-/9HIEs1ZXGhSPE8X6Ccm7Nam1z8KcoCqPdI7ecm1N33EzAetWahvQWVqLZtaZQ+IDKX4IyA2o0gBzqIMkAagHQ==", "dependencies": { "asn1": "~0.2.3", @@ -11012,6 +11898,7 @@ }, "node_modules/ssri": { "version": "9.0.1", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-9.0.1.tgz", "integrity": "sha512-o57Wcn66jMQvfHG1FlYbWeZWW/dHZhJXjpIcTfXldXEk5nz5lStPo3mK0OJQfGR3RbZUlbISexbljkJzuEj/8Q==", "dev": true, "dependencies": { @@ -11023,6 +11910,7 @@ }, "node_modules/stack-utils": { "version": "2.0.6", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==", "dev": true, "dependencies": { @@ -11034,6 +11922,7 @@ }, "node_modules/stack-utils/node_modules/escape-string-regexp": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", "dev": true, "engines": { @@ -11042,6 +11931,7 @@ }, "node_modules/standard-version": { "version": "9.5.0", + "resolved": "https://registry.npmjs.org/standard-version/-/standard-version-9.5.0.tgz", "integrity": "sha512-3zWJ/mmZQsOaO+fOlsa0+QK90pwhNd042qEcw6hKFNoLFs7peGyvPffpEBbK/DSGPbyOvli0mUIFv5A4qTjh2Q==", "dev": true, "dependencies": { @@ -11069,6 +11959,7 @@ }, "node_modules/standard-version/node_modules/ansi-styles": { "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", "dev": true, "dependencies": { @@ -11080,6 +11971,7 @@ }, "node_modules/standard-version/node_modules/chalk": { "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "dev": true, "dependencies": { @@ -11093,6 +11985,7 @@ }, "node_modules/standard-version/node_modules/cliui": { "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", "dev": true, "dependencies": { @@ -11103,6 +11996,7 @@ }, "node_modules/standard-version/node_modules/color-convert": { "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", "dev": true, "dependencies": { @@ -11111,19 +12005,83 @@ }, "node_modules/standard-version/node_modules/color-name": { "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", "dev": true }, + "node_modules/standard-version/node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/standard-version/node_modules/has-flag": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", "dev": true, "engines": { "node": ">=4" } }, + "node_modules/standard-version/node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/standard-version/node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/standard-version/node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/standard-version/node_modules/supports-color": { "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", "dev": true, "dependencies": { @@ -11135,6 +12093,7 @@ }, "node_modules/standard-version/node_modules/yargs": { "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", "dev": true, "dependencies": { @@ -11151,14 +12110,21 @@ } }, "node_modules/string_decoder": { - "version": "1.3.0", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "dependencies": { - "safe-buffer": "~5.2.0" + "safe-buffer": "~5.1.0" } }, + "node_modules/string_decoder/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, "node_modules/string-argv": { "version": "0.3.1", + "resolved": "https://registry.npmjs.org/string-argv/-/string-argv-0.3.1.tgz", "integrity": "sha512-a1uQGz7IyVy9YwhqjZIZu1c8JO8dNIe20xBmSS6qu9kv++k3JGzCVmprbNN5Kn+BgzD5E7YYwg1CcjuJMRNsvg==", "engines": { "node": ">=0.6.19" @@ -11166,6 +12132,7 @@ }, "node_modules/string-width": { "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "dependencies": { "emoji-regex": "^8.0.0", @@ -11176,21 +12143,16 @@ "node": ">=8" } }, - "node_modules/string-width/node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "engines": { - "node": ">=8" - } - }, "node_modules/stringify-package": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/stringify-package/-/stringify-package-1.0.1.tgz", "integrity": "sha512-sa4DUQsYciMP1xhKWGuFM04fB0LG/9DlluZoSVywUMRNvzid6XucHK0/90xGxRoHrAaROrcHK1aPKaijCtSrhg==", "deprecated": "This module is not used anymore, and has been replaced by @npmcli/package-json", "dev": true }, "node_modules/strip-ansi": { "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dependencies": { "ansi-regex": "^5.0.1" @@ -11200,15 +12162,17 @@ } }, "node_modules/strip-bom": { - "version": "4.0.0", - "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", "dev": true, "engines": { - "node": ">=8" + "node": ">=4" } }, "node_modules/strip-final-newline": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", "engines": { "node": ">=6" @@ -11216,6 +12180,7 @@ }, "node_modules/strip-indent": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==", "dev": true, "dependencies": { @@ -11227,6 +12192,7 @@ }, "node_modules/strip-json-comments": { "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", "dev": true, "engines": { @@ -11238,11 +12204,13 @@ }, "node_modules/strnum": { "version": "1.0.5", + "resolved": "https://registry.npmjs.org/strnum/-/strnum-1.0.5.tgz", "integrity": "sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA==", "dev": true }, "node_modules/supports-color": { "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dependencies": { "has-flag": "^4.0.0" @@ -11253,6 +12221,7 @@ }, "node_modules/supports-preserve-symlinks-flag": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", "engines": { "node": ">= 0.4" @@ -11263,6 +12232,7 @@ }, "node_modules/symbol-observable": { "version": "1.2.0", + "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.2.0.tgz", "integrity": "sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ==", "engines": { "node": ">=0.10.0" @@ -11270,6 +12240,7 @@ }, "node_modules/tar": { "version": "6.1.13", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.13.tgz", "integrity": "sha512-jdIBIN6LTIe2jqzay/2vtYLlBHa3JF42ot3h1dW8Q0PaAG4v8rm0cvpVePtau5C6OKXGGcgO9q2AMNSWxiLqKw==", "dev": true, "dependencies": { @@ -11286,6 +12257,7 @@ }, "node_modules/tar-stream": { "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", "dependencies": { "bl": "^4.0.3", @@ -11299,18 +12271,17 @@ } }, "node_modules/tar/node_modules/minipass": { - "version": "4.0.0", - "integrity": "sha512-g2Uuh2jEKoht+zvO6vJqXmYpflPqzRBT+Th2h01DKh5z7wbY/AZ2gCQ78cP70YoHPyFdY30YBV5WxgLOEwOykw==", + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-4.2.5.tgz", + "integrity": "sha512-+yQl7SX3bIT83Lhb4BVorMAHVuqsskxRdlmO9kTpyukp8vsm2Sn/fUOV9xlnG8/a5JsypJzap21lz/y3FBMJ8Q==", "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, "engines": { "node": ">=8" } }, "node_modules/tar/node_modules/mkdirp": { "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", "dev": true, "bin": { @@ -11320,13 +12291,9 @@ "node": ">=10" } }, - "node_modules/tar/node_modules/yallist": { - "version": "4.0.0", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, "node_modules/test-exclude": { "version": "6.0.0", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", "dev": true, "dependencies": { @@ -11340,6 +12307,7 @@ }, "node_modules/text-extensions": { "version": "1.9.0", + "resolved": "https://registry.npmjs.org/text-extensions/-/text-extensions-1.9.0.tgz", "integrity": "sha512-wiBrwC1EhBelW12Zy26JeOUkQ5mRu+5o8rpsJk5+2t+Y5vE7e842qtZDQ2g1NpX/29HdyFeJ4nSIhI47ENSxlQ==", "dev": true, "engines": { @@ -11348,10 +12316,12 @@ }, "node_modules/through": { "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==" }, "node_modules/through2": { "version": "4.0.2", + "resolved": "https://registry.npmjs.org/through2/-/through2-4.0.2.tgz", "integrity": "sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==", "dev": true, "dependencies": { @@ -11360,6 +12330,7 @@ }, "node_modules/tmp": { "version": "0.2.1", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz", "integrity": "sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==", "dependencies": { "rimraf": "^3.0.0" @@ -11370,11 +12341,13 @@ }, "node_modules/tmpl": { "version": "1.0.5", + "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==", "dev": true }, "node_modules/to-fast-properties": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", "dev": true, "engines": { @@ -11383,6 +12356,7 @@ }, "node_modules/to-readable-stream": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/to-readable-stream/-/to-readable-stream-1.0.0.tgz", "integrity": "sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q==", "dev": true, "engines": { @@ -11391,6 +12365,7 @@ }, "node_modules/to-regex-range": { "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", "dependencies": { "is-number": "^7.0.0" @@ -11401,6 +12376,7 @@ }, "node_modules/touch": { "version": "3.1.0", + "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.0.tgz", "integrity": "sha512-WBx8Uy5TLtOSRtIq+M03/sKDrXCLHxwDcquSP2c43Le03/9serjQBIztjRz6FkJez9D/hleyAXTBGLwwZUw9lA==", "dependencies": { "nopt": "~1.0.10" @@ -11411,6 +12387,7 @@ }, "node_modules/touch/node_modules/nopt": { "version": "1.0.10", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz", "integrity": "sha512-NWmpvLSqUrgrAC9HCuxEvb+PSloHpqVu+FqcO4eeF2h5qYRhA7ev6KvelyQAKtegUbC6RypJnlEOhd8vloNKYg==", "dependencies": { "abbrev": "1" @@ -11424,6 +12401,7 @@ }, "node_modules/tough-cookie": { "version": "2.5.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", "dependencies": { "psl": "^1.1.28", @@ -11435,11 +12413,13 @@ }, "node_modules/tr46": { "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", "dev": true }, "node_modules/traverse": { "version": "0.3.9", + "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.3.9.tgz", "integrity": "sha512-iawgk0hLP3SxGKDfnDJf8wTz4p2qImnyihM5Hh/sGvQ3K37dPi/w8sRhdNIxYA1TwFwc5mDhIJq+O0RsvXBKdQ==", "dev": true, "engines": { @@ -11448,6 +12428,7 @@ }, "node_modules/trim-newlines": { "version": "3.0.1", + "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-3.0.1.tgz", "integrity": "sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==", "dev": true, "engines": { @@ -11456,6 +12437,7 @@ }, "node_modules/ts-node": { "version": "10.9.1", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz", "integrity": "sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==", "dev": true, "dependencies": { @@ -11496,25 +12478,20 @@ } } }, - "node_modules/ts-node/node_modules/diff": { - "version": "4.0.2", - "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", - "dev": true, - "engines": { - "node": ">=0.3.1" - } - }, "node_modules/ts-toolbelt": { "version": "6.15.5", + "resolved": "https://registry.npmjs.org/ts-toolbelt/-/ts-toolbelt-6.15.5.tgz", "integrity": "sha512-FZIXf1ksVyLcfr7M317jbB67XFJhOO1YqdTcuGaq9q5jLUoTikukZ+98TPjKiP2jC5CgmYdWWYs0s2nLSU0/1A==", "dev": true }, "node_modules/tslib": { "version": "2.5.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" }, "node_modules/tunnel-agent": { "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", "dependencies": { "safe-buffer": "^5.0.1" @@ -11525,6 +12502,7 @@ }, "node_modules/tv4": { "version": "1.3.0", + "resolved": "https://registry.npmjs.org/tv4/-/tv4-1.3.0.tgz", "integrity": "sha512-afizzfpJgvPr+eDkREK4MxJ/+r8nEEHcmitwgnPUqpaP+FpwQyadnxNoSACbgc/b1LsZYtODGoPiFxQrgJgjvw==", "dev": true, "engines": { @@ -11533,10 +12511,12 @@ }, "node_modules/tweetnacl": { "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", "integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==" }, "node_modules/type-detect": { "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", "dev": true, "engines": { @@ -11545,6 +12525,7 @@ }, "node_modules/type-fest": { "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", "engines": { "node": ">=10" @@ -11555,6 +12536,7 @@ }, "node_modules/type-is": { "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", "dev": true, "dependencies": { @@ -11567,11 +12549,13 @@ }, "node_modules/typedarray": { "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==", "dev": true }, "node_modules/typedarray-to-buffer": { "version": "3.1.5", + "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", "dev": true, "dependencies": { @@ -11580,6 +12564,7 @@ }, "node_modules/typescript": { "version": "4.9.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.4.tgz", "integrity": "sha512-Uz+dTXYzxXXbsFpM86Wh3dKCxrQqUcVMxwU54orwlJjOpO3ao8L7j5lH+dWfTwgCwIuM9GQ2kvVotzYJMXTBZg==", "dev": true, "bin": { @@ -11592,6 +12577,7 @@ }, "node_modules/uglify-js": { "version": "3.17.4", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.17.4.tgz", "integrity": "sha512-T9q82TJI9e/C1TAxYvfb16xO120tMVFZrGA3f9/P4424DNu6ypK103y0GPFVa17yotwSyZW5iYXgjYHkGrJW/g==", "dev": true, "optional": true, @@ -11604,10 +12590,12 @@ }, "node_modules/undefsafe": { "version": "2.0.5", + "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz", "integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==" }, "node_modules/unique-filename": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-2.0.1.tgz", "integrity": "sha512-ODWHtkkdx3IAR+veKxFV+VBkUMcN+FaqzUUd7IZzt+0zhDZFPFxhlqwPF3YQvMHx1TD0tdgYl+kuPnJ8E6ql7A==", "dev": true, "dependencies": { @@ -11619,6 +12607,7 @@ }, "node_modules/unique-slug": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-3.0.0.tgz", "integrity": "sha512-8EyMynh679x/0gqE9fT9oilG+qEt+ibFyqjuVTsZn1+CMxH+XLlpvr2UZx4nVcCwTpx81nICr2JQFkM+HPLq4w==", "dev": true, "dependencies": { @@ -11630,6 +12619,7 @@ }, "node_modules/unique-string": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz", "integrity": "sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==", "dev": true, "dependencies": { @@ -11641,6 +12631,7 @@ }, "node_modules/universalify": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", "engines": { "node": ">= 10.0.0" @@ -11648,6 +12639,7 @@ }, "node_modules/untildify": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/untildify/-/untildify-4.0.0.tgz", "integrity": "sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==", "dev": true, "engines": { @@ -11656,6 +12648,7 @@ }, "node_modules/unzipper": { "version": "0.10.11", + "resolved": "https://registry.npmjs.org/unzipper/-/unzipper-0.10.11.tgz", "integrity": "sha512-+BrAq2oFqWod5IESRjL3S8baohbevGcVA+teAIOYWM3pDVdseogqbzhhvvmiyQrUNKFUnDMtELW3X8ykbyDCJw==", "dev": true, "dependencies": { @@ -11671,14 +12664,10 @@ "setimmediate": "~1.0.4" } }, - "node_modules/unzipper/node_modules/bluebird": { - "version": "3.4.7", - "integrity": "sha512-iD3898SR7sWVRHbiQv+sHUtHnMvC1o3nW5rAcqnq3uOn07DSAppZYUkIGslDz6gXC7HfunPe7YVBgoEJASPcHA==", - "dev": true - }, "node_modules/unzipper/node_modules/readable-stream": { - "version": "2.3.7", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", "dev": true, "dependencies": { "core-util-is": "~1.0.0", @@ -11692,19 +12681,13 @@ }, "node_modules/unzipper/node_modules/safe-buffer": { "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", "dev": true }, - "node_modules/unzipper/node_modules/string_decoder": { - "version": "1.1.1", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, "node_modules/update-browserslist-db": { "version": "1.0.10", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.10.tgz", "integrity": "sha512-OztqDenkfFkbSG+tRxBeAnCVPckDBcvibKd35yDONx6OU8N7sqgwc7rCbkJ/WcYtVRZ4ba68d6byhC21GFh7sQ==", "dev": true, "funding": [ @@ -11730,6 +12713,7 @@ }, "node_modules/update-notifier": { "version": "5.1.0", + "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-5.1.0.tgz", "integrity": "sha512-ItnICHbeMh9GqUy31hFPrD1kcuZ3rpxDZbf4KUDavXwS0bW5m7SLbDQpGX3UYr072cbrF5hFUs3r5tUsPwjfHw==", "dev": true, "dependencies": { @@ -11757,6 +12741,7 @@ }, "node_modules/update-notifier/node_modules/chalk": { "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, "dependencies": { @@ -11772,6 +12757,7 @@ }, "node_modules/uri-js": { "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", "dependencies": { "punycode": "^2.1.0" @@ -11779,16 +12765,19 @@ }, "node_modules/uri-template-lite": { "version": "22.9.0", + "resolved": "https://registry.npmjs.org/uri-template-lite/-/uri-template-lite-22.9.0.tgz", "integrity": "sha512-cmGZaykSWEQ5UXKaGKnUS8zFvfp8j1Jvn7dlq3P7tGd5XeybXcfo0xnVBRWiNEp80nO1GYgCLwoaRJ8WMmmk3Q==", "dev": true }, "node_modules/urijs": { "version": "1.19.11", + "resolved": "https://registry.npmjs.org/urijs/-/urijs-1.19.11.tgz", "integrity": "sha512-HXgFDgDommxn5/bIv0cnQZsPhHDA90NPHD6+c/v21U5+Sx5hoP8+dP9IZXBU1gIfvdRfhG8cel9QNPeionfcCQ==", "dev": true }, "node_modules/url": { "version": "0.10.3", + "resolved": "https://registry.npmjs.org/url/-/url-0.10.3.tgz", "integrity": "sha512-hzSUW2q06EqL1gKM/a+obYHLIO6ct2hwPuviqTTOcfFVc61UbfJ2Q32+uGL/HCPxKqrdGB5QUwIe7UqlDgwsOQ==", "dependencies": { "punycode": "1.3.2", @@ -11797,6 +12786,7 @@ }, "node_modules/url-parse-lax": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-3.0.0.tgz", "integrity": "sha512-NjFKA0DidqPa5ciFcSrXnAltTtzz84ogy+NebPvfEgAck0+TNg4UJ4IN+fB7zRZfbgUf0syOo9MDxFkDSMuFaQ==", "dev": true, "dependencies": { @@ -11808,10 +12798,12 @@ }, "node_modules/url/node_modules/punycode": { "version": "1.3.2", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", "integrity": "sha512-RofWgt/7fL5wP1Y7fxE7/EmTLzQVnB0ycyibJ0OOHIlJqTNzglYFxVwETOcIoJqJmpDXJ9xImDv+Fq34F/d4Dw==" }, "node_modules/util": { "version": "0.12.5", + "resolved": "https://registry.npmjs.org/util/-/util-0.12.5.tgz", "integrity": "sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==", "dependencies": { "inherits": "^2.0.3", @@ -11823,10 +12815,12 @@ }, "node_modules/util-deprecate": { "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" }, "node_modules/utility-types": { "version": "3.10.0", + "resolved": "https://registry.npmjs.org/utility-types/-/utility-types-3.10.0.tgz", "integrity": "sha512-O11mqxmi7wMKCo6HKFt5AhO4BwY3VV68YU07tgxfz8zJTIxr4BpsezN49Ffwy9j3ZpwwJp4fkRwjRzq3uWE6Rg==", "dev": true, "engines": { @@ -11835,6 +12829,7 @@ }, "node_modules/uuid": { "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", "bin": { "uuid": "dist/bin/uuid" @@ -11842,15 +12837,18 @@ }, "node_modules/v8-compile-cache-lib": { "version": "3.0.1", + "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", "dev": true }, "node_modules/valid-url": { "version": "1.0.9", + "resolved": "https://registry.npmjs.org/valid-url/-/valid-url-1.0.9.tgz", "integrity": "sha512-QQDsV8OnSf5Uc30CKSwG9lnhMPe6exHtTXLRYX8uMwKENy640pU+2BgBL0LRbDh/eYRahNCS7aewCx0wf3NYVA==" }, "node_modules/validate-npm-package-license": { "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", "dev": true, "dependencies": { @@ -11860,6 +12858,7 @@ }, "node_modules/validate-npm-package-name": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-4.0.0.tgz", "integrity": "sha512-mzR0L8ZDktZjpX4OB46KT+56MAhl4EIazWP/+G/HPGuvfdaqg4YsCdtOm6U9+LOFyYDoh4dpnpxZRB9MQQns5Q==", "dev": true, "dependencies": { @@ -11871,16 +12870,19 @@ }, "node_modules/validate.io-array": { "version": "1.0.6", + "resolved": "https://registry.npmjs.org/validate.io-array/-/validate.io-array-1.0.6.tgz", "integrity": "sha512-DeOy7CnPEziggrOO5CZhVKJw6S3Yi7e9e65R1Nl/RTN1vTQKnzjfvks0/8kQ40FP/dsjRAOd4hxmJ7uLa6vxkg==", "dev": true }, "node_modules/validate.io-function": { "version": "1.0.2", + "resolved": "https://registry.npmjs.org/validate.io-function/-/validate.io-function-1.0.2.tgz", "integrity": "sha512-LlFybRJEriSuBnUhQyG5bwglhh50EpTL2ul23MPIuR1odjO7XaMLFV8vHGwp7AZciFxtYOeiSCT5st+XSPONiQ==", "dev": true }, "node_modules/validate.io-integer": { "version": "1.0.5", + "resolved": "https://registry.npmjs.org/validate.io-integer/-/validate.io-integer-1.0.5.tgz", "integrity": "sha512-22izsYSLojN/P6bppBqhgUDjCkr5RY2jd+N2a3DCAUey8ydvrZ/OkGvFPR7qfOpwR2LC5p4Ngzxz36g5Vgr/hQ==", "dev": true, "dependencies": { @@ -11889,6 +12891,7 @@ }, "node_modules/validate.io-integer-array": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/validate.io-integer-array/-/validate.io-integer-array-1.0.0.tgz", "integrity": "sha512-mTrMk/1ytQHtCY0oNO3dztafHYyGU88KL+jRxWuzfOmQb+4qqnWmI+gykvGp8usKZOM0H7keJHEbRaFiYA0VrA==", "dev": true, "dependencies": { @@ -11898,11 +12901,13 @@ }, "node_modules/validate.io-number": { "version": "1.0.3", + "resolved": "https://registry.npmjs.org/validate.io-number/-/validate.io-number-1.0.3.tgz", "integrity": "sha512-kRAyotcbNaSYoDnXvb4MHg/0a1egJdLwS6oJ38TJY7aw9n93Fl/3blIXdyYvPOp55CNxywooG/3BcrwNrBpcSg==", "dev": true }, "node_modules/verror": { "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", "integrity": "sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==", "engines": [ "node >=0.6.0" @@ -11915,6 +12920,7 @@ }, "node_modules/walker": { "version": "1.0.8", + "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==", "dev": true, "dependencies": { @@ -11923,6 +12929,7 @@ }, "node_modules/wcwidth": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", "integrity": "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==", "dependencies": { "defaults": "^1.0.3" @@ -11930,16 +12937,19 @@ }, "node_modules/webidl-conversions": { "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", "dev": true }, "node_modules/whatwg-fetch": { "version": "3.6.2", + "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.6.2.tgz", "integrity": "sha512-bJlen0FcuU/0EMLrdbJ7zOnW6ITZLrZMIarMUVmdKtsGvZna8vxKYaexICWPfZ8qwf9fzNq+UEIZrnSaApt6RA==", "dev": true }, "node_modules/whatwg-url": { "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", "dev": true, "dependencies": { @@ -11949,6 +12959,7 @@ }, "node_modules/which": { "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", "dependencies": { "isexe": "^2.0.0" @@ -11962,11 +12973,13 @@ }, "node_modules/which-module": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", "integrity": "sha512-B+enWhmw6cjfVC7kS8Pj9pCrKSc5txArRyaYGe088shv/FGWH+0Rjx/xPgtsWfsUtS27FkP697E4DDhgrgoc0Q==", "dev": true }, "node_modules/which-typed-array": { "version": "1.1.9", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.9.tgz", "integrity": "sha512-w9c4xkx6mPidwp7180ckYWfMmvxpjlZuIudNtDf4N/tTAUB8VJbX25qZoAsrtGuYNnGw3pa0AXgbGKRB8/EceA==", "dependencies": { "available-typed-arrays": "^1.0.5", @@ -11985,6 +12998,7 @@ }, "node_modules/wide-align": { "version": "1.1.5", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", "dev": true, "dependencies": { @@ -11993,6 +13007,7 @@ }, "node_modules/widest-line": { "version": "3.1.0", + "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz", "integrity": "sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==", "dev": true, "dependencies": { @@ -12004,16 +13019,19 @@ }, "node_modules/wordwrap": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==", "dev": true }, "node_modules/workerpool": { "version": "6.2.0", + "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.0.tgz", "integrity": "sha512-Rsk5qQHJ9eowMH28Jwhe8HEbmdYDX4lwoMWshiCXugjtHqMD9ZbiqSDLxcsfdqsETPzVUtX5s1Z5kStiIM6l4A==", "dev": true }, "node_modules/wrap-ansi": { "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", "dependencies": { "ansi-styles": "^4.0.0", @@ -12029,10 +13047,12 @@ }, "node_modules/wrappy": { "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" }, "node_modules/write-file-atomic": { "version": "4.0.2", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz", "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==", "dev": true, "dependencies": { @@ -12045,6 +13065,7 @@ }, "node_modules/xdg-basedir": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-4.0.0.tgz", "integrity": "sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q==", "dev": true, "engines": { @@ -12053,6 +13074,7 @@ }, "node_modules/xml2js": { "version": "0.4.19", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.19.tgz", "integrity": "sha512-esZnJZJOiJR9wWKMyuvSE1y6Dq5LCuJanqhxslH2bxM6duahNZ+HMpCLhBQGZkbX6xRf8x1Y2eJlgt2q3qo49Q==", "dependencies": { "sax": ">=0.6.0", @@ -12061,6 +13083,7 @@ }, "node_modules/xmlbuilder": { "version": "9.0.7", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-9.0.7.tgz", "integrity": "sha512-7YXTQc3P2l9+0rjaUbLwMKRhtmwg1M1eDf6nag7urC7pIPYLD9W/jmzQ4ptRSUbodw5S0jfoGTflLemQibSpeQ==", "engines": { "node": ">=4.0" @@ -12068,6 +13091,7 @@ }, "node_modules/xtend": { "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", "dev": true, "engines": { @@ -12076,18 +13100,21 @@ }, "node_modules/y18n": { "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", "engines": { "node": ">=10" } }, "node_modules/yallist": { - "version": "3.1.1", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", "dev": true }, "node_modules/yaml": { "version": "1.10.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", "engines": { "node": ">= 6" @@ -12095,6 +13122,7 @@ }, "node_modules/yargs": { "version": "17.6.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.6.2.tgz", "integrity": "sha512-1/9UrdHjDZc0eOU0HxOHoS78C69UD3JRMvzlJ7S79S2nTaWRA/whGCTV8o9e/N/1Va9YIV7Q4sOxD8VV4pCWOw==", "dependencies": { "cliui": "^8.0.1", @@ -12111,6 +13139,7 @@ }, "node_modules/yargs-parser": { "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", "dev": true, "engines": { @@ -12119,6 +13148,7 @@ }, "node_modules/yargs-unparser": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", "dev": true, "dependencies": { @@ -12133,6 +13163,7 @@ }, "node_modules/yargs-unparser/node_modules/camelcase": { "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", "dev": true, "engines": { @@ -12144,6 +13175,7 @@ }, "node_modules/yargs-unparser/node_modules/decamelize": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", "dev": true, "engines": { @@ -12155,6 +13187,7 @@ }, "node_modules/yargs-unparser/node_modules/is-plain-obj": { "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", "dev": true, "engines": { @@ -12163,6 +13196,7 @@ }, "node_modules/yargs/node_modules/yargs-parser": { "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", "engines": { "node": ">=12" @@ -12170,6 +13204,7 @@ }, "node_modules/yn": { "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", "dev": true, "engines": { @@ -12178,6 +13213,7 @@ }, "node_modules/yocto-queue": { "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", "dev": true, "engines": { @@ -12189,6 +13225,7 @@ }, "node_modules/zip-stream": { "version": "4.1.0", + "resolved": "https://registry.npmjs.org/zip-stream/-/zip-stream-4.1.0.tgz", "integrity": "sha512-zshzwQW7gG7hjpBlgeQP9RuyPGNxvJdzR8SUM3QhxCnLjWN2E7j3dOvpeDcQoETfHx0urRS7EtmVToql7YpU4A==", "dependencies": { "archiver-utils": "^2.1.0", From 7c2ddb3cc6b5869bc1384d74f489829b7f09dac7 Mon Sep 17 00:00:00 2001 From: Mario Doiron <4956+doiron@users.noreply.github.com> Date: Thu, 30 Mar 2023 17:44:06 -0700 Subject: [PATCH 04/10] fix: not runing lint as npm script anymore --- .github/workflows/unit-test.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/unit-test.yml b/.github/workflows/unit-test.yml index c5032688..ae0f1cdb 100644 --- a/.github/workflows/unit-test.yml +++ b/.github/workflows/unit-test.yml @@ -27,5 +27,4 @@ jobs: with: node-version: ${{ matrix.node }} - run: npm install - - run: npm run lint - run: npm run test:report From 9981ac4baf40de6e4df198be0b8d8303d0ca0784 Mon Sep 17 00:00:00 2001 From: Mario Doiron <4956+doiron@users.noreply.github.com> Date: Thu, 30 Mar 2023 17:47:09 -0700 Subject: [PATCH 05/10] fix: functional tests after v2.29.0 new flow changes --- package.json | 2 +- .../commands/high-level-commands-test.js | 43 ++++++++++--------- test/test-utils.js | 1 + 3 files changed, 25 insertions(+), 21 deletions(-) diff --git a/package.json b/package.json index 7c693c82..656e1100 100644 --- a/package.json +++ b/package.json @@ -34,7 +34,7 @@ "test:report": "nyc npm run test", "test:browser": "npm run test:report && open coverage/index.html", "integration-test": "mocha -t 180000 test/integration/run-test.js", - "functional-test": "mocha -t 600000 -u bdd --require ts-node/register test/functional/run-test.js -R spec 'test/functional/{,**/}!(*.d).{ts,js}'", + "functional-test": "npm run build && chmod +x ./dist/bin/ask.js && mocha -t 600000 -u bdd --require ts-node/register test/functional/run-test.js -R spec 'test/functional/{,**/}!(*.d).{ts,js}'", "functional-test:clean-up": "node scripts/aws-clean-up.js; node scripts/ask-clean-up.js", "format": "prettier --write .", "pre-release": "standard-version", diff --git a/test/functional/commands/high-level-commands-test.js b/test/functional/commands/high-level-commands-test.js index 3c876beb..7b2af498 100644 --- a/test/functional/commands/high-level-commands-test.js +++ b/test/functional/commands/high-level-commands-test.js @@ -1,5 +1,6 @@ const {expect} = require("chai"); const parallel = require("mocha.parallel"); +const path = require("path"); const { run, KeySymbol, @@ -10,14 +11,14 @@ const { } = require("../../test-utils"); parallel("high level commands test", () => { - let cmd; + let askCmd; before(() => { resetTempDirectory(); }); beforeEach(() => { - cmd = "ask"; + askCmd = path.join(process.cwd(), "/dist/bin/ask.js"); }); it("| should init new skill", async () => { @@ -39,7 +40,7 @@ parallel("high level commands test", () => { {match: "? Does this look correct?"}, ]; - const result = await run(cmd, args, {inputs, cwd}); + const result = await run(askCmd, args, {inputs, cwd}); expect(result).include("succeeded"); }); @@ -51,29 +52,29 @@ parallel("high level commands test", () => { // new let args = ["new"]; let inputs = [ - {match: "? Choose the programming language"}, + {match: "? Choose a modeling stack for your skill"}, + {match: "? Choose the programming language you will use to code your skill"}, {match: "? Choose a method to host your skill"}, - {match: "? Choose the default locale for your skill"}, {match: "? Choose the default region for your skill"}, {match: "? Please type in your skill name"}, {match: "? Please type in your folder name", input: folderName}, ]; - let result = await run(cmd, args, {inputs}); + let result = await run(askCmd, args, {inputs}); expect(result).include("Hosted skill provisioning finished"); // deploy let cwd = getPathInTempDirectory(folderName); - cmd = "git"; + const gitCmd = "git"; args = ["add", "."]; - await run(cmd, args, {cwd}); + await run(gitCmd, args, {cwd}); args = ["commit", "-m", '"test"']; - await run(cmd, args, {cwd}); + await run(gitCmd, args, {cwd}); args = ["push"]; - result = await run(cmd, args, {cwd}); + result = await run(gitCmd, args, {cwd}); expect(result).include("After the code pushed, please check the deployment status"); @@ -81,11 +82,10 @@ parallel("high level commands test", () => { folderName = "cloned-hosted-skill"; cwd = getPathInTempDirectory(folderName); - cmd = "ask"; args = ["init", "--hosted-skill-id", skillId]; inputs = [{match: "? Please type in your folder name", input: folderName}]; - result = await run(cmd, args, {inputs, cwd}); + result = await run(askCmd, args, {inputs, cwd}); expect(result).include("successfully initialized"); }); @@ -96,14 +96,15 @@ parallel("high level commands test", () => { // new let args = ["new"]; const inputs = [ - {match: "? Choose the programming language"}, + {match: "? Choose a modeling stack for your skill"}, + {match: "? Choose the programming language you will use to code your skill"}, {match: "? Choose a method to host your skill", input: KeySymbol.DOWN}, {match: "? Choose a template to start with"}, {match: "? Please type in your skill name"}, {match: "? Please type in your folder name", input: folderName}, ]; - let result = await run(cmd, args, {inputs}); + let result = await run(askCmd, args, {inputs}); expect(result).include('Project initialized with deploy delegate "@ask-cli/cfn-deployer" successfully'); @@ -111,7 +112,7 @@ parallel("high level commands test", () => { const cwd = getPathInTempDirectory(folderName); args = ["deploy"]; - result = await run(cmd, args, {cwd}); + result = await run(askCmd, args, {cwd}); expect(result).include("Skill infrastructures deployed successfully through @ask-cli/cfn-deployer"); }); @@ -122,14 +123,15 @@ parallel("high level commands test", () => { // new let args = ["new"]; const inputs = [ - {match: "? Choose the programming language"}, + {match: "? Choose a modeling stack for your skill"}, + {match: "? Choose the programming language you will use to code your skill"}, {match: "? Choose a method to host your skill", input: `${KeySymbol.DOWN}${KeySymbol.DOWN}`}, {match: "? Choose a template to start with"}, {match: "? Please type in your skill name", input: folderName}, {match: "? Please type in your folder name", input: folderName}, ]; - let result = await run(cmd, args, {inputs}); + let result = await run(askCmd, args, {inputs}); expect(result).include('Project initialized with deploy delegate "@ask-cli/lambda-deployer" successfully'); @@ -137,7 +139,7 @@ parallel("high level commands test", () => { const cwd = getPathInTempDirectory(folderName); args = ["deploy"]; - result = await run(cmd, args, {cwd}); + result = await run(askCmd, args, {cwd}); expect(result).include("Skill infrastructures deployed successfully through @ask-cli/lambda-deployer"); }); @@ -148,13 +150,14 @@ parallel("high level commands test", () => { // new let args = ["new"]; const inputs = [ - {match: "? Choose the programming language"}, + {match: "? Choose a modeling stack for your skill"}, + {match: "? Choose the programming language you will use to code your skill"}, {match: "? Choose a method to host your skill", input: `${KeySymbol.DOWN}${KeySymbol.DOWN}`}, {match: "? Choose a template to start with", input: `${KeySymbol.DOWN}${KeySymbol.DOWN}${KeySymbol.DOWN}`}, {match: "? Please type in your skill name", input: folderName}, {match: "? Please type in your folder name", input: folderName}, ]; - let result = await run(cmd, args, {inputs}); + let result = await run(askCmd, args, {inputs}); expect(result).include('Project initialized with deploy delegate "@ask-cli/lambda-deployer" successfully'); }); }); diff --git a/test/test-utils.js b/test/test-utils.js index 127f267d..8f0c7881 100644 --- a/test/test-utils.js +++ b/test/test-utils.js @@ -42,6 +42,7 @@ const run = (cmd, args, options = {}) => { const env = {...process.env, ...options.env}; fs.ensureDirSync(cwd); + fs.ensureFileSync(cmd); const childProcess = spawn(cmd, args, {cwd, env, stdio: [null, null, null, null]}); From 25806fe517d4e84ab07e00dce1bf0bcf548e84e6 Mon Sep 17 00:00:00 2001 From: Mario Doiron <4956+doiron@users.noreply.github.com> Date: Thu, 30 Mar 2023 21:01:55 -0700 Subject: [PATCH 06/10] fix: removing node 14 for integration test to see if 16 works --- .github/workflows/functional-test.yml | 3 +-- .github/workflows/integration-test.yml | 4 ++-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/.github/workflows/functional-test.yml b/.github/workflows/functional-test.yml index 59a3f1c1..fdb61185 100644 --- a/.github/workflows/functional-test.yml +++ b/.github/workflows/functional-test.yml @@ -8,9 +8,8 @@ on: jobs: build: if: "!contains(github.event.head_commit.message, 'chore(release):')" - - runs-on: ubuntu-latest + runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - name: Use Node.js diff --git a/.github/workflows/integration-test.yml b/.github/workflows/integration-test.yml index de61b601..a596350a 100644 --- a/.github/workflows/integration-test.yml +++ b/.github/workflows/integration-test.yml @@ -2,7 +2,7 @@ name: Integration Test on: push: - branches: + branches: - master - develop paths-ignore: @@ -18,7 +18,7 @@ jobs: strategy: matrix: os: [ubuntu-latest, windows-latest, macos-latest] - node: [14, 16] + node: [16] steps: - uses: actions/checkout@v3 From 94be29862036436e60947c921b772fc2100f5bcf Mon Sep 17 00:00:00 2001 From: Mario Doiron <4956+doiron@users.noreply.github.com> Date: Thu, 30 Mar 2023 21:15:21 -0700 Subject: [PATCH 07/10] fix: fixing some integ test failures --- .github/workflows/integration-test.yml | 3 +- package.json | 5 +- .../commands/smapi-commands-test.js | 359 +++++++++--------- 3 files changed, 184 insertions(+), 183 deletions(-) diff --git a/.github/workflows/integration-test.yml b/.github/workflows/integration-test.yml index a596350a..c1f541c1 100644 --- a/.github/workflows/integration-test.yml +++ b/.github/workflows/integration-test.yml @@ -18,8 +18,7 @@ jobs: strategy: matrix: os: [ubuntu-latest, windows-latest, macos-latest] - node: [16] - + node: [14, 16] steps: - uses: actions/checkout@v3 - name: Use Node.js ${{ matrix.node }} diff --git a/package.json b/package.json index 656e1100..c30ada4b 100644 --- a/package.json +++ b/package.json @@ -33,8 +33,9 @@ "test:watch": "mocha --require ts-node/register test/unit/run-test.js -w", "test:report": "nyc npm run test", "test:browser": "npm run test:report && open coverage/index.html", - "integration-test": "mocha -t 180000 test/integration/run-test.js", - "functional-test": "npm run build && chmod +x ./dist/bin/ask.js && mocha -t 600000 -u bdd --require ts-node/register test/functional/run-test.js -R spec 'test/functional/{,**/}!(*.d).{ts,js}'", + "pre-test": "npm run build && chmod +x ./dist/bin/ask.js", + "integration-test": "npm run pre-test && mocha -t 180000 test/integration/run-test.js", + "functional-test": "npm run pre-test && mocha -t 600000 -u bdd --require ts-node/register test/functional/run-test.js -R spec 'test/functional/{,**/}!(*.d).{ts,js}'", "functional-test:clean-up": "node scripts/aws-clean-up.js; node scripts/ask-clean-up.js", "format": "prettier --write .", "pre-release": "standard-version", diff --git a/test/integration/commands/smapi-commands-test.js b/test/integration/commands/smapi-commands-test.js index dacd7966..296d7c1b 100644 --- a/test/integration/commands/smapi-commands-test.js +++ b/test/integration/commands/smapi-commands-test.js @@ -1,9 +1,10 @@ -const {expect} = require("chai"); -const {ModelIntrospector} = require("ask-smapi-sdk"); +const { expect } = require("chai"); +const { ModelIntrospector } = require("ask-smapi-sdk"); const parallel = require("mocha.parallel"); +const path = require("path"); -const {CliCustomizationProcessor} = require("../../../lib/commands/smapi/cli-customization-processor"); -const {run, startMockSmapiServer, startMockLwaServer, MockServerPort} = require("../../test-utils"); +const { CliCustomizationProcessor } = require("../../../lib/commands/smapi/cli-customization-processor"); +const { run, startMockSmapiServer, startMockLwaServer, MockServerPort } = require("../../test-utils"); const skillManifest = require("../../integration/fixtures/skill-manifest.json"); const catalogUploadBody = require("../../integration/fixtures/catalog-upload.json"); const inSkillProductRequestBody = require("../../integration/fixtures/create-in-skill-product-request.json"); @@ -21,16 +22,16 @@ const untestedCommands = new Set([...modelIntrospector.getOperations().keys()].m const testedCommands = new Set(); const addCoveredCommand = (args) => { - const cmd = args[1]; - if (testedCommands.has(cmd)) { - console.warn(`${cmd} already has been covered!`); + const smapiCmd = args[1]; + if (testedCommands.has(smapiCmd)) { + console.warn(`${smapiCmd} already has been covered!`); } - testedCommands.add(cmd); - untestedCommands.delete(cmd); + testedCommands.add(smapiCmd); + untestedCommands.delete(smapiCmd); }; parallel('smapi command test', () => { - const cmd = 'ask'; + const askCmd = path.join(process.cwd(), "/dist/bin/ask.js"); const subCmd = 'smapi'; let mockSmapiServer; let mockLwaServer; @@ -143,35 +144,35 @@ parallel('smapi command test', () => { it("| should display vendor list", async () => { const args = [subCmd, "get-vendor-list"]; addCoveredCommand(args); - const result = await run(cmd, args, options); + const result = await run(askCmd, args, options); expect(result).be.an("object"); }); it("| should list skills for vendor", async () => { const args = [subCmd, "list-skills-for-vendor", "--max-results", 1]; addCoveredCommand(args); - const result = await run(cmd, args, options); + const result = await run(askCmd, args, options); expect(result).be.an("object"); }); it("| should create skill for vendor", async () => { const args = [subCmd, "create-skill-for-vendor", "--manifest", JSON.stringify(skillManifest)]; addCoveredCommand(args); - const result = await run(cmd, args, options); + const result = await run(askCmd, args, options); expect(result).be.an("object"); }); it("| should get skill status", async () => { const args = [subCmd, "get-skill-status", "-s", skillId]; addCoveredCommand(args); - const result = await run(cmd, args, options); + const result = await run(askCmd, args, options); expect(result).be.an("object"); }); it("| should display catalog list", async () => { const args = [subCmd, "list-catalogs-for-vendor"]; addCoveredCommand(args); - const result = await run(cmd, args, options); + const result = await run(askCmd, args, options); expect(result).be.an("object"); }); @@ -187,140 +188,140 @@ parallel('smapi command test', () => { "AlexaMusic.Catalog.BroadcastChannel", ]; addCoveredCommand(args); - const result = await run(cmd, args, options); + const result = await run(askCmd, args, options); expect(result).be.an("object"); }); it("| should get catalog information", async () => { const args = [subCmd, "get-catalog", "-c", "someCatalogId"]; addCoveredCommand(args); - const result = await run(cmd, args, options); + const result = await run(askCmd, args, options); expect(result).be.an("object"); }); it("| should associate skill with catalog", async () => { const args = [subCmd, "associate-catalog-with-skill", "-c", catalogId, "-s", skillId]; addCoveredCommand(args); - const result = await run(cmd, args, {...options, parse: false}); + const result = await run(askCmd, args, {...options, parse: false}); expect(result).include("Command executed successfully!"); }); it("| should create catalog upload", async () => { const args = [subCmd, "create-catalog-upload", "-c", catalogId, "--catalog-upload-request-body", JSON.stringify(catalogUploadBody)]; addCoveredCommand(args); - const result = await run(cmd, args, {...options, parse: false}); + const result = await run(askCmd, args, {...options, parse: false}); expect(result).include("Command executed successfully!"); }); it("| should display catalog list for skill", async () => { const args = [subCmd, "list-catalogs-for-skill", "-s", skillId, "--max-results", 1]; addCoveredCommand(args); - const result = await run(cmd, args, options); + const result = await run(askCmd, args, options); expect(result).be.an("object"); }); it("| should display alexa hosted skill metadata", async () => { const args = [subCmd, "get-alexa-hosted-skill-metadata", "-s", skillId]; addCoveredCommand(args); - const result = await run(cmd, args, options); + const result = await run(askCmd, args, options); expect(result).be.an("object"); }); it("| should display utterance data", async () => { const args = [subCmd, "get-utterance-data", "-s", skillId, "--locale", locale, "--sort-direction", "asc"]; addCoveredCommand(args); - const result = await run(cmd, args, options); + const result = await run(askCmd, args, options); expect(result).be.an("object"); }); it("| should add testers to beta test", async () => { const args = [subCmd, "add-testers-to-beta-test", "-s", skillId, "--testers-emails", testersEmails]; addCoveredCommand(args); - const result = await run(cmd, args, {...options, parse: false}); + const result = await run(askCmd, args, {...options, parse: false}); expect(result).include("Command executed successfully!"); }); it("| should get list of testers", async () => { const args = [subCmd, "get-list-of-testers", "-s", skillId, "--max-results", 1]; addCoveredCommand(args); - const result = await run(cmd, args, options); + const result = await run(askCmd, args, options); expect(result).be.an("object"); }); it("| should request feedback from testers", async () => { const args = [subCmd, "request-feedback-from-testers", "-s", skillId, "--testers-emails", testersEmails]; addCoveredCommand(args); - const result = await run(cmd, args, {...options, parse: false}); + const result = await run(askCmd, args, {...options, parse: false}); expect(result).include("Command executed successfully!"); }); it("| should send reminder to testers", async () => { const args = [subCmd, "send-reminder-to-testers", "-s", skillId, "--testers-emails", testersEmails]; addCoveredCommand(args); - const result = await run(cmd, args, {...options, parse: false}); + const result = await run(askCmd, args, {...options, parse: false}); expect(result).include("Command executed successfully!"); }); it("| should remove testers from beta test", async () => { const args = [subCmd, "remove-testers-from-beta-test", "-s", skillId, "--testers-emails", testersEmails]; addCoveredCommand(args); - const result = await run(cmd, args, {...options, parse: false}); + const result = await run(askCmd, args, {...options, parse: false}); expect(result).include("Command executed successfully!"); }); it("| should update interaction model catalog version and return version number", async () => { const args = [subCmd, "update-interaction-model-catalog-version", "-c", catalogId, "--vers", 1, "--description", "test"]; addCoveredCommand(args); - const result = await run(cmd, args, {...options, parse: false}); + const result = await run(askCmd, args, {...options, parse: false}); expect(result).include("Command executed successfully!"); }); it("| should simulate skill", async () => { const args = [subCmd, "simulate-skill", "-s", skillId, "--device-locale", locale, "-g", stage, "--input-content", "hello"]; addCoveredCommand(args); - const result = await run(cmd, args, options); + const result = await run(askCmd, args, options); expect(result).be.an("object"); }); it("| should create beta test", async () => { const args = [subCmd, "create-beta-test", "-s", skillId, "--feedback-email", "someemail@email.com"]; addCoveredCommand(args); - const result = await run(cmd, args, {...options, parse: false}); + const result = await run(askCmd, args, {...options, parse: false}); expect(result).include("Command executed successfully!"); }); it("| should update beta test", async () => { const args = [subCmd, "update-beta-test", "-s", skillId, "--feedback-email", "test2@gmail.com"]; addCoveredCommand(args); - const result = await run(cmd, args, {...options, parse: false}); + const result = await run(askCmd, args, {...options, parse: false}); expect(result).include("Command executed successfully!"); }); it("| should retrieve beta test", async () => { const args = [subCmd, "get-beta-test", "-s", skillId]; addCoveredCommand(args); - const result = await run(cmd, args, options); + const result = await run(askCmd, args, options); expect(result).be.an("object"); }); it("| should list uploads for catalog", async () => { const args = [subCmd, "list-uploads-for-catalog", "-c", catalogId, "--max-results", 1]; addCoveredCommand(args); - const result = await run(cmd, args, options); + const result = await run(askCmd, args, options); expect(result).be.an("object"); }); it("| should list isp for vendor", async () => { const args = [subCmd, "get-isp-list-for-vendor", "--max-results", 1]; addCoveredCommand(args); - const result = await run(cmd, args, options); + const result = await run(askCmd, args, options); expect(result).be.an("object"); }); it("| should list isp for skill id ", async () => { const args = [subCmd, "get-isp-list-for-skill-id", "-s", skillId, "-g", stage, "--max-results", 1]; addCoveredCommand(args); - const result = await run(cmd, args, options); + const result = await run(askCmd, args, options); expect(result).be.an("object"); }); @@ -336,63 +337,63 @@ parallel('smapi command test', () => { JSON.stringify(accountLinkingRequest), ]; addCoveredCommand(args); - const result = await run(cmd, args, {...options, parse: false}); + const result = await run(askCmd, args, {...options, parse: false}); expect(result).include("Command executed successfully!"); }); it("| should retrieve account linking", async () => { const args = [subCmd, "get-account-linking-info", "-s", skillId, "-g", stage]; addCoveredCommand(args); - const result = await run(cmd, args, options); + const result = await run(askCmd, args, options); expect(result).be.an("object"); }); it("| should delete account linking", async () => { const args = [subCmd, "delete-account-linking-info", "-s", skillId, "-g", stage]; addCoveredCommand(args); - const result = await run(cmd, args, {...options, parse: false}); + const result = await run(askCmd, args, {...options, parse: false}); expect(result).include("Command executed successfully!"); }); it("| should create isp", async () => { const args = [subCmd, "create-isp-for-vendor", "--create-in-skill-product-request", JSON.stringify(inSkillProductRequestBody)]; addCoveredCommand(args); - const result = await run(cmd, args, options); + const result = await run(askCmd, args, options); expect(result).be.an("object"); }); it("| should get isp definition", async () => { const args = [subCmd, "get-isp-definition", "--product-id", productId, "-g", stage]; addCoveredCommand(args); - const result = await run(cmd, args, options); + const result = await run(askCmd, args, options); expect(result).be.an("object"); }); it("| should reset entitlement for product", async () => { const args = [subCmd, "reset-entitlement-for-product", "--product-id", productId, "-g", stage]; addCoveredCommand(args); - const result = await run(cmd, args, {...options, parse: false}); + const result = await run(askCmd, args, {...options, parse: false}); expect(result).include("Command executed successfully!"); }); it("| should get isp associated skills", async () => { const args = [subCmd, "get-isp-associated-skills", "--product-id", productId, "-g", stage]; addCoveredCommand(args); - const result = await run(cmd, args, options); + const result = await run(askCmd, args, options); expect(result).be.an("object"); }); it("| should disassociate isp with skill", async () => { const args = [subCmd, "disassociate-isp-with-skill", "--product-id", productId, "-s", skillId]; addCoveredCommand(args); - const result = await run(cmd, args, {...options, parse: false}); + const result = await run(askCmd, args, {...options, parse: false}); expect(result).include("Command executed successfully!"); }); it("| should retrieve isp summary", async () => { const args = [subCmd, "get-isp-summary", "--product-id", productId, "-g", stage]; addCoveredCommand(args); - const result = await run(cmd, args, options); + const result = await run(askCmd, args, options); expect(result).be.an("object"); }); @@ -408,21 +409,21 @@ parallel('smapi command test', () => { JSON.stringify(inSkillProductRequestBody), ]; addCoveredCommand(args); - const result = await run(cmd, args, {...options, parse: false}); + const result = await run(askCmd, args, {...options, parse: false}); expect(result).include("Command executed successfully!"); }); it("| should delete isp for product", async () => { const args = [subCmd, "delete-isp-for-product", "--product-id", productId, "-g", stage]; addCoveredCommand(args); - const result = await run(cmd, args, {...options, parse: false}); + const result = await run(askCmd, args, {...options, parse: false}); expect(result).include("Command executed successfully!"); }); it("| should create content upload", async () => { const args = [subCmd, "create-content-upload", "-c", catalogId, "--number-of-upload-parts", 1]; addCoveredCommand(args); - const result = await run(cmd, args, options); + const result = await run(askCmd, args, options); expect(result).be.an("object"); }); @@ -438,42 +439,42 @@ parallel('smapi command test', () => { "GIT", ]; addCoveredCommand(args); - const result = await run(cmd, args, options); + const result = await run(askCmd, args, options); expect(result).be.an("object"); }); it("| should get content upload by id", async () => { const args = [subCmd, "get-content-upload-by-id", "-c", catalogId, "--upload-id", uploadId]; addCoveredCommand(args); - const result = await run(cmd, args, options); + const result = await run(askCmd, args, options); expect(result).be.an("object"); }); it("| should complete catalog upload", async () => { const args = [subCmd, "complete-catalog-upload", "-c", catalogId, "--upload-id", uploadId, "--part-e-tags", partETags]; addCoveredCommand(args); - const result = await run(cmd, args, {...options, parse: false}); + const result = await run(askCmd, args, {...options, parse: false}); expect(result).include("Command executed successfully!"); }); it("| should list subscribers for development events", async () => { const args = [subCmd, "list-subscribers-for-development-events"]; addCoveredCommand(args); - const result = await run(cmd, args, options); + const result = await run(askCmd, args, options); expect(result).be.an("object"); }); it("| should create subscriber for development events", async () => { const args = [subCmd, "create-subscriber-for-development-events", "--create-subscriber-request", createSubscriptionRequest]; addCoveredCommand(args); - const result = await run(cmd, args, {...options, parse: false}); + const result = await run(askCmd, args, {...options, parse: false}); expect(result).include("Command executed successfully!"); }); it("| should get subscriber for development events", async () => { const args = [subCmd, "get-subscriber-for-development-events", "--subscriber-id", subscriberId]; addCoveredCommand(args); - const result = await run(cmd, args, options); + const result = await run(askCmd, args, options); expect(result).be.an("object"); }); @@ -487,21 +488,21 @@ parallel('smapi command test', () => { updateSubscriptionRequest, ]; addCoveredCommand(args); - const result = await run(cmd, args, {...options, parse: false}); + const result = await run(askCmd, args, {...options, parse: false}); expect(result).include("Command executed successfully!"); }); it("| should delete subscriber for development events", async () => { const args = [subCmd, "delete-subscriber-for-development-events", "--subscriber-id", subscriberId]; addCoveredCommand(args); - const result = await run(cmd, args, {...options, parse: false}); + const result = await run(askCmd, args, {...options, parse: false}); expect(result).include("Command executed successfully!"); }); it("| should list subscriptions for development events", async () => { const args = [subCmd, "list-subscriptions-for-development-events"]; addCoveredCommand(args); - const result = await run(cmd, args, options); + const result = await run(askCmd, args, options); expect(result).be.an("object"); }); @@ -517,14 +518,14 @@ parallel('smapi command test', () => { subscriberId, ]; addCoveredCommand(args); - const result = await run(cmd, args, {...options, parse: false}); + const result = await run(askCmd, args, {...options, parse: false}); expect(result).include("Command executed successfully!"); }); it("| should get subscription for development events", async () => { const args = [subCmd, "get-subscription-for-development-events", "--subscription-id", subscriptionId]; addCoveredCommand(args); - const result = await run(cmd, args, options); + const result = await run(askCmd, args, options); expect(result).be.an("object"); }); @@ -540,105 +541,105 @@ parallel('smapi command test', () => { "AlexaDevelopmentEvent.ManifestUpdated,AlexaDevelopmentEvent.ManifestCreated", ]; addCoveredCommand(args); - const result = await run(cmd, args, {...options, parse: false}); + const result = await run(askCmd, args, {...options, parse: false}); expect(result).include("Command executed successfully!"); }); it("| should delete subscription for development events", async () => { const args = [subCmd, "delete-subscription-for-development-events", "--subscription-id", subscriptionId]; addCoveredCommand(args); - const result = await run(cmd, args, {...options, parse: false}); + const result = await run(askCmd, args, {...options, parse: false}); expect(result).include("Command executed successfully!"); }); it("| should generate catalog upload url", async () => { const args = [subCmd, "generate-catalog-upload-url", "-c", catalogId, "--number-of-upload-parts", 1]; addCoveredCommand(args); - const result = await run(cmd, args, options); + const result = await run(askCmd, args, options); expect(result).be.an("object"); }); it("| should associate isp with skill", async () => { const args = [subCmd, "associate-isp-with-skill", "--product-id", productId, "-s", skillId]; addCoveredCommand(args); - const result = await run(cmd, args, {...options, parse: false}); + const result = await run(askCmd, args, {...options, parse: false}); expect(result).include("Command executed successfully!"); }); it('| should get alexa hosted skill user permissions', async () => { const args = [subCmd, 'get-alexa-hosted-skill-user-permissions', '--hosted-skill-permission-type', 'somePermission']; addCoveredCommand(args); - const result = await run(cmd, args, options); + const result = await run(askCmd, args, options); expect(result).be.an('object'); }); it("| should start beta test", async () => { const args = [subCmd, "start-beta-test", "-s", skillId]; addCoveredCommand(args); - const result = await run(cmd, args, {...options, parse: false}); + const result = await run(askCmd, args, {...options, parse: false}); expect(result).include("Command executed successfully!"); }); it("| should end beta test", async () => { const args = [subCmd, "end-beta-test", "-s", skillId]; addCoveredCommand(args); - const result = await run(cmd, args, {...options, parse: false}); + const result = await run(askCmd, args, {...options, parse: false}); expect(result).include("Command executed successfully!"); }); it("| should get certifications list", async () => { const args = [subCmd, "get-certifications-list", "-s", skillId]; addCoveredCommand(args); - const result = await run(cmd, args, options); + const result = await run(askCmd, args, options); expect(result).be.an("object"); }); it("| should get certification review", async () => { const args = [subCmd, "get-certification-review", "-s", skillId, "-c", catalogId]; addCoveredCommand(args); - const result = await run(cmd, args, options); + const result = await run(askCmd, args, options); expect(result).be.an("object"); }); it("| should get skill enablement status", async () => { const args = [subCmd, "get-skill-enablement-status", "-s", skillId, "-g", stage]; addCoveredCommand(args); - const result = await run(cmd, args, {...options, parse: false}); + const result = await run(askCmd, args, {...options, parse: false}); expect(result).include("Command executed successfully!"); }); it("| should set skill enablement", async () => { const args = [subCmd, "set-skill-enablement", "-s", skillId, "-g", stage]; addCoveredCommand(args); - const result = await run(cmd, args, {...options, parse: false}); + const result = await run(askCmd, args, {...options, parse: false}); expect(result).include("Command executed successfully!"); }); it("| should delete skill enablement", async () => { const args = [subCmd, "delete-skill-enablement", "-s", skillId, "-g", stage]; addCoveredCommand(args); - const result = await run(cmd, args, {...options, parse: false}); + const result = await run(askCmd, args, {...options, parse: false}); expect(result).include("Command executed successfully!"); }); it("| should profile nlu", async () => { const args = [subCmd, "profile-nlu", "-u", "test", "--multi-turn-token", "someToken", "-s", skillId, "-g", stage, "-l", locale]; addCoveredCommand(args); - const result = await run(cmd, args, options); + const result = await run(askCmd, args, options); expect(result).be.an("object"); }); it("| should get interaction model", async () => { const args = [subCmd, "get-interaction-model", "-s", skillId, "-g", stage, "-l", locale]; addCoveredCommand(args); - const result = await run(cmd, args, options); + const result = await run(askCmd, args, options); expect(result).be.an("object"); }); it("| should get interaction model metadata", async () => { const args = [subCmd, "get-interaction-model-metadata", "-s", skillId, "-g", stage, "-l", locale]; addCoveredCommand(args); - const result = await run(cmd, args, {...options, parse: false}); + const result = await run(askCmd, args, {...options, parse: false}); expect(result).include("Command executed successfully!"); }); @@ -656,119 +657,119 @@ parallel('smapi command test', () => { JSON.stringify(interactionModel), ]; addCoveredCommand(args); - const result = await run(cmd, args, {...options, parse: false}); + const result = await run(askCmd, args, {...options, parse: false}); expect(result).include("Command executed successfully!"); }); it("| should list interaction model catalogs", async () => { const args = [subCmd, "list-interaction-model-catalogs"]; addCoveredCommand(args); - const result = await run(cmd, args, options); + const result = await run(askCmd, args, options); expect(result).be.an("object"); }); it("| should create interaction model catalog", async () => { const args = [subCmd, "create-interaction-model-catalog", "--catalog-name", "name", "--catalog-description", "someDescription"]; addCoveredCommand(args); - const result = await run(cmd, args, options); + const result = await run(askCmd, args, options); expect(result).be.an("object"); }); it("| should get interaction model catalog definition", async () => { const args = [subCmd, "get-interaction-model-catalog-definition", "-c", catalogId]; addCoveredCommand(args); - const result = await run(cmd, args, options); + const result = await run(askCmd, args, options); expect(result).be.an("object"); }); it("| should delete interaction model catalog", async () => { const args = [subCmd, "delete-interaction-model-catalog", "-c", catalogId]; addCoveredCommand(args); - const result = await run(cmd, args, {...options, parse: false}); + const result = await run(askCmd, args, {...options, parse: false}); expect(result).include("Command executed successfully!"); }); it("| should get interaction model catalog update status", async () => { const args = [subCmd, "get-interaction-model-catalog-update-status", "-c", catalogId, "--update-request-id", updateRequestId]; addCoveredCommand(args); - const result = await run(cmd, args, options); + const result = await run(askCmd, args, options); expect(result).be.an("object"); }); it("| should update interaction model catalog", async () => { const args = [subCmd, "update-interaction-model-catalog", "-c", catalogId, "--name", "name", "--description", "someDescription"]; addCoveredCommand(args); - const result = await run(cmd, args, {...options, parse: false}); + const result = await run(askCmd, args, {...options, parse: false}); expect(result).include("Command executed successfully!"); }); it('| should create interaction model catalog version', async () => { const args = [subCmd, 'create-interaction-model-catalog-version', '-c', catalogId, '--source-type', 'catalogType', '--source-url', 'catalogUrl', '--description', 'someDescription']; addCoveredCommand(args); - const result = await run(cmd, args, { ...options, parse: false }); + const result = await run(askCmd, args, { ...options, parse: false }); expect(result).include('Command executed successfully!'); }); it("| should get interaction model catalog version", async () => { const args = [subCmd, "get-interaction-model-catalog-version", "-c", catalogId, "--vers", version]; addCoveredCommand(args); - const result = await run(cmd, args, options); + const result = await run(askCmd, args, options); expect(result).be.an("object"); }); it("| should delete interaction model catalog version", async () => { const args = [subCmd, "delete-interaction-model-catalog-version", "-c", catalogId, "--vers", version]; addCoveredCommand(args); - const result = await run(cmd, args, {...options, parse: false}); + const result = await run(askCmd, args, {...options, parse: false}); expect(result).include("Command executed successfully!"); }); it("| should get interaction model catalog values", async () => { const args = [subCmd, "get-interaction-model-catalog-values", "-c", catalogId, "--vers", version]; addCoveredCommand(args); - const result = await run(cmd, args, options); + const result = await run(askCmd, args, options); expect(result).be.an("object"); }); it("| should get interaction model version", async () => { const args = [subCmd, "get-interaction-model-version", "-s", skillId, "-g", stage, "-l", locale, "--vers", version]; addCoveredCommand(args); - const result = await run(cmd, args, options); + const result = await run(askCmd, args, options); expect(result).be.an("object"); }); it("| should list interaction model versions", async () => { const args = [subCmd, "list-interaction-model-versions", "-s", skillId, "-g", stage, "-l", locale]; addCoveredCommand(args); - const result = await run(cmd, args, options); + const result = await run(askCmd, args, options); expect(result).be.an("object"); }); it("| should list interaction model slot types", async () => { const args = [subCmd, "list-interaction-model-slot-types"]; addCoveredCommand(args); - const result = await run(cmd, args, options); + const result = await run(askCmd, args, options); expect(result).be.an("object"); }); it("| should create interaction model slot type", async () => { const args = [subCmd, "create-interaction-model-slot-type", "--slot-type", slotType]; addCoveredCommand(args); - const result = await run(cmd, args, options); + const result = await run(askCmd, args, options); expect(result).be.an("object"); }); it("| should get interaction model slot type definition", async () => { const args = [subCmd, "get-interaction-model-slot-type-definition", "--slot-type-id", slotTypeId]; addCoveredCommand(args); - const result = await run(cmd, args, options); + const result = await run(askCmd, args, options); expect(result).be.an("object"); }); it("| should delete interaction model slot type", async () => { const args = [subCmd, "delete-interaction-model-slot-type", "--slot-type-id", slotTypeId]; addCoveredCommand(args); - const result = await run(cmd, args, {...options, parse: false}); + const result = await run(askCmd, args, {...options, parse: false}); expect(result).include("Command executed successfully!"); }); @@ -782,42 +783,42 @@ parallel('smapi command test', () => { updateRequestId, ]; addCoveredCommand(args); - const result = await run(cmd, args, options); + const result = await run(askCmd, args, options); expect(result).be.an("object"); }); it("| should update interaction model slot type", async () => { const args = [subCmd, "update-interaction-model-slot-type", "--slot-type-id", slotTypeId, "--slot-type-description", "someDescription"]; addCoveredCommand(args); - const result = await run(cmd, args, {...options, parse: false}); + const result = await run(askCmd, args, {...options, parse: false}); expect(result).include("Command executed successfully!"); }); it("| should list interaction model slot type versions", async () => { const args = [subCmd, "list-interaction-model-slot-type-versions", "--slot-type-id", slotTypeId]; addCoveredCommand(args); - const result = await run(cmd, args, options); + const result = await run(askCmd, args, options); expect(result).be.an("object"); }); it("| should create interaction model slot type version", async () => { const args = [subCmd, "create-interaction-model-slot-type-version", "--slot-type-id", slotTypeId, "--slot-type", slotType]; addCoveredCommand(args); - const result = await run(cmd, args, {...options, parse: false}); + const result = await run(askCmd, args, {...options, parse: false}); expect(result).include("Command executed successfully!"); }); it("| should get interaction model slot type version", async () => { const args = [subCmd, "get-interaction-model-slot-type-version", "--slot-type-id", slotTypeId, "--vers", version]; addCoveredCommand(args); - const result = await run(cmd, args, options); + const result = await run(askCmd, args, options); expect(result).be.an("object"); }); it("| should delete interaction model slot type version", async () => { const args = [subCmd, "delete-interaction-model-slot-type-version", "--slot-type-id", slotTypeId, "--vers", version]; addCoveredCommand(args); - const result = await run(cmd, args, {...options, parse: false}); + const result = await run(askCmd, args, {...options, parse: false}); expect(result).include("Command executed successfully!"); }); @@ -833,21 +834,21 @@ parallel('smapi command test', () => { "someDescription", ]; addCoveredCommand(args); - const result = await run(cmd, args, {...options, parse: false}); + const result = await run(askCmd, args, {...options, parse: false}); expect(result).include("Command executed successfully!"); }); it("| should get skill manifest", async () => { const args = [subCmd, "get-skill-manifest", "-s", skillId, "-g", stage]; addCoveredCommand(args); - const result = await run(cmd, args, options); + const result = await run(askCmd, args, options); expect(result).be.an("object"); }); it("| should update skill manifest", async () => { const args = [subCmd, "update-skill-manifest", "-s", skillId, "-g", stage, "--manifest", JSON.stringify(skillManifest)]; addCoveredCommand(args); - const result = await run(cmd, args, {...options, parse: false}); + const result = await run(askCmd, args, {...options, parse: false}); expect(result).include("Command executed successfully!"); }); @@ -871,140 +872,140 @@ parallel('smapi command test', () => { "smartHome", ]; addCoveredCommand(args); - const result = await run(cmd, args, options); + const result = await run(askCmd, args, options); expect(result).be.an("object"); }); it("| should set private distribution account id", async () => { const args = [subCmd, "set-private-distribution-account-id", "-s", skillId, "-g", stage, "--id", "someId"]; addCoveredCommand(args); - const result = await run(cmd, args, {...options, parse: false}); + const result = await run(askCmd, args, {...options, parse: false}); expect(result).include("Command executed successfully!"); }); it("| should delete private distribution account id", async () => { const args = [subCmd, "delete-private-distribution-account-id", "-s", skillId, "-g", stage, "--id", "someId"]; addCoveredCommand(args); - const result = await run(cmd, args, {...options, parse: false}); + const result = await run(askCmd, args, {...options, parse: false}); expect(result).include("Command executed successfully!"); }); it("| should list private distribution accounts", async () => { const args = [subCmd, "list-private-distribution-accounts", "-s", skillId, "-g", stage]; addCoveredCommand(args); - const result = await run(cmd, args, options); + const result = await run(askCmd, args, options); expect(result).be.an("object"); }); it("| should get skill simulation", async () => { const args = [subCmd, "get-skill-simulation", "-s", skillId, "-g", stage, "-i", simulationId]; addCoveredCommand(args); - const result = await run(cmd, args, options); + const result = await run(askCmd, args, options); expect(result).be.an("object"); }); it("| should submit skill validation", async () => { const args = [subCmd, "submit-skill-validation", "-l", locale, "-s", skillId, "-g", stage]; addCoveredCommand(args); - const result = await run(cmd, args, options); + const result = await run(askCmd, args, options); expect(result).be.an("object"); }); it("| should get skill validations", async () => { const args = [subCmd, "get-skill-validations", "-s", skillId, "-i", simulationId, "-g", stage]; addCoveredCommand(args); - const result = await run(cmd, args, options); + const result = await run(askCmd, args, options); expect(result).be.an("object"); }); it("| should delete skill", async () => { const args = [subCmd, "delete-skill", "-s", skillId]; addCoveredCommand(args); - const result = await run(cmd, args, {...options, parse: false}); + const result = await run(askCmd, args, {...options, parse: false}); expect(result).include("Command executed successfully!"); }); it("| should get ssl certificates", async () => { const args = [subCmd, "get-ssl-certificates", "-s", skillId]; addCoveredCommand(args); - const result = await run(cmd, args, options); + const result = await run(askCmd, args, options); expect(result).be.an("object"); }); it("| should set ssl certificates", async () => { const args = [subCmd, "set-ssl-certificates", "-s", skillId, "--ssl-certificate-payload", sslCertificatePayload]; addCoveredCommand(args); - const result = await run(cmd, args, {...options, parse: false}); + const result = await run(askCmd, args, {...options, parse: false}); expect(result).include("Command executed successfully!"); }); it("| should submit skill for certification", async () => { const args = [subCmd, "submit-skill-for-certification", "-s", skillId, "--publication-method", "MANUAL_PUBLISHING"]; addCoveredCommand(args); - const result = await run(cmd, args, {...options, parse: false}); + const result = await run(askCmd, args, {...options, parse: false}); expect(result).include("Command executed successfully!"); }); it("| should withdraw skill from certification", async () => { const args = [subCmd, "withdraw-skill-from-certification", "-s", skillId, "--reason", "TEST_SKILL"]; addCoveredCommand(args); - const result = await run(cmd, args, {...options, parse: false}); + const result = await run(askCmd, args, {...options, parse: false}); expect(result).include("Command executed successfully!"); }); it("| should create export request for skill", async () => { const args = [subCmd, "create-export-request-for-skill", "-s", skillId, "-g", stage]; addCoveredCommand(args); - const result = await run(cmd, args, {...options, parse: false}); + const result = await run(askCmd, args, {...options, parse: false}); expect(result).include("Command executed successfully!"); }); it("| should get status of export request", async () => { const args = [subCmd, "get-status-of-export-request", "--export-id", "someExportId"]; addCoveredCommand(args); - const result = await run(cmd, args, options); + const result = await run(askCmd, args, options); expect(result).be.an("object"); }); it("| should create skill package", async () => { const args = [subCmd, "create-skill-package", "--location", location]; addCoveredCommand(args); - const result = await run(cmd, args, {...options, parse: false}); + const result = await run(askCmd, args, {...options, parse: false}); expect(result).include("Command executed successfully!"); }); it("| should import skill package", async () => { const args = [subCmd, "import-skill-package", "--location", location, "-s", skillId]; addCoveredCommand(args); - const result = await run(cmd, args, {...options, parse: false}); + const result = await run(askCmd, args, {...options, parse: false}); expect(result).include("Command executed successfully!"); }); it("| should get import status", async () => { const args = [subCmd, "get-import-status", "--import-id", "someImportId"]; addCoveredCommand(args); - const result = await run(cmd, args, options); + const result = await run(askCmd, args, options); expect(result).be.an("object"); }); it("| should create upload url", async () => { const args = [subCmd, "create-upload-url"]; addCoveredCommand(args); - const result = await run(cmd, args, options); + const result = await run(askCmd, args, options); expect(result).be.an("object"); }); it("| should query development audit logs", async () => { const args = [subCmd, "query-development-audit-logs"]; addCoveredCommand(args); - const result = await run(cmd, args, options); + const result = await run(askCmd, args, options); expect(result).be.an("object"); }); it("| should invoke skill end point", async () => { const args = [subCmd, "invoke-skill", "-s", skillId, "--endpoint-region", "someRegion", "--skill-request-body", JSON.stringify({})]; addCoveredCommand(args); - const result = await run(cmd, args, options); + const result = await run(askCmd, args, options); expect(result).be.an("object"); }); @@ -1022,77 +1023,77 @@ parallel('smapi command test', () => { JSON.stringify({}), ]; addCoveredCommand(args); - const result = await run(cmd, args, options); + const result = await run(askCmd, args, options); expect(result).be.an("object"); }); it("| should list nlu evaluations", async () => { const args = [subCmd, "list-nlu-evaluations", "-s", skillId]; addCoveredCommand(args); - const result = await run(cmd, args, options); + const result = await run(askCmd, args, options); expect(result).be.an("object"); }); it("| should get nlu evaluation", async () => { const args = [subCmd, "get-nlu-evaluation", "-s", skillId, "--evaluation-id", evaluationId]; addCoveredCommand(args); - const result = await run(cmd, args, options); + const result = await run(askCmd, args, options); expect(result).be.an("object"); }); it("| should get result for nlu evaluations", async () => { const args = [subCmd, "get-result-for-nlu-evaluations", "-s", skillId, "--evaluation-id", evaluationId]; addCoveredCommand(args); - const result = await run(cmd, args, options); + const result = await run(askCmd, args, options); expect(result).be.an("object"); }); it("| should list nlu annotation sets", async () => { const args = [subCmd, "list-nlu-annotation-sets", "-s", skillId]; addCoveredCommand(args); - const result = await run(cmd, args, options); + const result = await run(askCmd, args, options); expect(result).be.an("object"); }); it("| should create nlu annotation set", async () => { const args = [subCmd, "create-nlu-annotation-set", "-s", skillId, "-l", locale, "--name", name]; addCoveredCommand(args); - const result = await run(cmd, args, options); + const result = await run(askCmd, args, options); expect(result).be.an("object"); }); it("| should create nlu evaluations", async () => { const args = [subCmd, "create-nlu-evaluations", "-g", stage, "-l", locale, "--source-annotation-id", sourceAnnotationId, "-s", skillId]; addCoveredCommand(args); - const result = await run(cmd, args, options); + const result = await run(askCmd, args, options); expect(result).be.an("object"); }); it("| should get properties for nlu annotation sets", async () => { const args = [subCmd, "get-properties-for-nlu-annotation-sets", "-s", skillId, "--annotation-id", annotationId]; addCoveredCommand(args); - const result = await run(cmd, args, options); + const result = await run(askCmd, args, options); expect(result).be.an("object"); }); it("| should update properties for nlu annotation sets", async () => { const args = [subCmd, "update-properties-for-nlu-annotation-sets", "-s", skillId, "--annotation-id", annotationId, "--name", name]; addCoveredCommand(args); - const result = await run(cmd, args, {...options, parse: false}); + const result = await run(askCmd, args, {...options, parse: false}); expect(result).include("Command executed successfully!"); }); it("| should delete properties for nlu annotation sets", async () => { const args = [subCmd, "delete-properties-for-nlu-annotation-sets", "-s", skillId, "--annotation-id", annotationId]; addCoveredCommand(args); - const result = await run(cmd, args, {...options, parse: false}); + const result = await run(askCmd, args, {...options, parse: false}); expect(result).include("Command executed successfully!"); }); it("| should get annotations for nlu annotation sets", async () => { const args = [subCmd, "get-annotations-for-nlu-annotation-sets", "-s", skillId, "--annotation-id", annotationId, "--accept", accept]; addCoveredCommand(args); - const result = await run(cmd, args, options); + const result = await run(askCmd, args, options); expect(result).be.an("object"); }); @@ -1110,14 +1111,14 @@ parallel('smapi command test', () => { updateNluAnnotationSetAnnotationsRequest, ]; addCoveredCommand(args); - const result = await run(cmd, args, {...options, parse: false}); + const result = await run(askCmd, args, {...options, parse: false}); expect(result).include("Command executed successfully!"); }); it("| should get conflicts for interaction model conflict detection", async () => { const args = [subCmd, "get-conflicts-for-interaction-model", "-s", skillId, "-l", locale, "-g", stage, "--vers", "1"]; addCoveredCommand(args); - const result = await run(cmd, args, options); + const result = await run(askCmd, args, options); expect(result).be.an("object"); }); @@ -1135,49 +1136,49 @@ parallel('smapi command test', () => { "1", ]; addCoveredCommand(args); - const result = await run(cmd, args, options); + const result = await run(askCmd, args, options); expect(result).be.an("object"); }); it("| should get skill credential", async () => { const args = [subCmd, "get-skill-credentials", "-s", skillId]; addCoveredCommand(args); - const result = await run(cmd, args, options); + const result = await run(askCmd, args, options); expect(result).be.an("object"); }); it("| should list asr annotation sets", async () => { const args = [subCmd, "list-asr-annotation-sets", "-s", skillId]; addCoveredCommand(args); - const result = await run(cmd, args, options); + const result = await run(askCmd, args, options); expect(result).be.an("object"); }); it("| should create asr annotation set", async () => { const args = [subCmd, "create-asr-annotation-set", "-s", skillId, "--name", name]; addCoveredCommand(args); - const result = await run(cmd, args, options); + const result = await run(askCmd, args, options); expect(result).be.an("object"); }); it("| should get asr annotation set", async () => { const args = [subCmd, "get-asr-annotation-set", "-s", skillId, "--annotation-set-id", annotationSetId]; addCoveredCommand(args); - const result = await run(cmd, args, options); + const result = await run(askCmd, args, options); expect(result).be.an("object"); }); it("| should set asr annotation set", async () => { const args = [subCmd, "set-asr-annotation-set", "-s", skillId, "--annotation-set-id", annotationSetId, "--name", name]; addCoveredCommand(args); - const result = await run(cmd, args, {...options, parse: false}); + const result = await run(askCmd, args, {...options, parse: false}); expect(result).include("Command executed successfully!"); }); it("| should delete asr annotation set", async () => { const args = [subCmd, "delete-asr-annotation-set", "-s", skillId, "--annotation-set-id", annotationSetId]; addCoveredCommand(args); - const result = await run(cmd, args, {...options, parse: false}); + const result = await run(askCmd, args, {...options, parse: false}); expect(result).include("Command executed successfully!"); }); @@ -1193,7 +1194,7 @@ parallel('smapi command test', () => { accept, ]; addCoveredCommand(args); - const result = await run(cmd, args, options); + const result = await run(askCmd, args, options); expect(result).be.an("object"); }); @@ -1209,14 +1210,14 @@ parallel('smapi command test', () => { annotations, ]; addCoveredCommand(args); - const result = await run(cmd, args, {...options, parse: false}); + const result = await run(askCmd, args, {...options, parse: false}); expect(result).include("Command executed successfully!"); }); it("| should list asr evaluations", async () => { const args = [subCmd, "list-asr-evaluations", "-s", skillId]; addCoveredCommand(args); - const result = await run(cmd, args, options); + const result = await run(askCmd, args, options); expect(result).be.an("object"); }); @@ -1234,70 +1235,70 @@ parallel('smapi command test', () => { skillId, ]; addCoveredCommand(args); - const result = await run(cmd, args, options); + const result = await run(askCmd, args, options); expect(result).be.an("object"); }); it("| should get asr evaluation status", async () => { const args = [subCmd, "get-asr-evaluation-status", "-s", skillId, "--evaluation-id", evaluationId]; addCoveredCommand(args); - const result = await run(cmd, args, options); + const result = await run(askCmd, args, options); expect(result).be.an("object"); }); it("| should delete asr evaluation", async () => { const args = [subCmd, "delete-asr-evaluation", "-s", skillId, "--evaluation-id", evaluationId]; addCoveredCommand(args); - const result = await run(cmd, args, {...options, parse: false}); + const result = await run(askCmd, args, {...options, parse: false}); expect(result).include("Command executed successfully!"); }); it("| should list asr evaluations results", async () => { const args = [subCmd, "list-asr-evaluations-results", "-s", skillId, "--evaluation-id", evaluationId]; addCoveredCommand(args); - const result = await run(cmd, args, options); + const result = await run(askCmd, args, options); expect(result).be.an("object"); }); it("| should list interaction model catalog versions", async () => { const args = [subCmd, "list-interaction-model-catalog-versions", "-c", catalogId]; addCoveredCommand(args); - const result = await run(cmd, args, options); + const result = await run(askCmd, args, options); expect(result).be.an("object"); }); it("| should clone locale", async () => { const args = [subCmd, "clone-locale", "-s", skillId, "--source-locale", sourceLocale, "--target-locales", targetLocales]; addCoveredCommand(args); - const result = await run(cmd, args, {...options, parse: false}); + const result = await run(askCmd, args, {...options, parse: false}); expect(result).include("Command executed successfully!"); }); it("| should get clone locale status", async () => { const args = [subCmd, "get-clone-locale-status", "-s", skillId, "--clone-locale-request-id", cloneLocaleRequestId]; addCoveredCommand(args); - const result = await run(cmd, args, options); + const result = await run(askCmd, args, options); expect(result).be.an("object"); }); it("| should list versions for skill", async () => { const args = [subCmd, "list-versions-for-skill", "-s", skillId]; addCoveredCommand(args); - const result = await run(cmd, args, options); + const result = await run(askCmd, args, options); expect(result).be.an("object"); }); it("| should rollback skill", async () => { const args = [subCmd, "rollback-skill", "-s", skillId, "--target-version", targetVersion]; addCoveredCommand(args); - const result = await run(cmd, args, options); + const result = await run(askCmd, args, options); expect(result).be.an("object"); }); it("| should get rollback for skill", async () => { const args = [subCmd, "get-rollback-for-skill", "-s", skillId, "--rollback-request-id", rollbackRequestId]; addCoveredCommand(args); - const result = await run(cmd, args, options); + const result = await run(askCmd, args, options); expect(result).be.an("object"); }); @@ -1313,98 +1314,98 @@ parallel('smapi command test', () => { "2019-04-12T23:20:50.52Z", ]; addCoveredCommand(args); - const result = await run(cmd, args, options); + const result = await run(askCmd, args, options); expect(result).be.an("object"); }); it("| should get skill publications", async () => { const args = [subCmd, "get-skill-publications", "-s", skillId, "--accept-language", acceptLanguage]; addCoveredCommand(args); - const result = await run(cmd, args, options); + const result = await run(askCmd, args, options); expect(result).be.an("object"); }); it("| should list all the job defintions for IM", async () => { const args = [subCmd, "list-job-definitions-for-interaction-model"]; addCoveredCommand(args); - const result = await run(cmd, args, options); + const result = await run(askCmd, args, options); expect(result).be.an("object"); }); it("| should create job definition for IM", async () => { const args = [subCmd, "create-job-definition-for-interaction-model", "--job-definition", interactionModelJobDefinition]; addCoveredCommand(args); - const result = await run(cmd, args, options); + const result = await run(askCmd, args, options); expect(result).be.an("object"); }); it("| should get job definition for IM", async () => { const args = [subCmd, "get-job-definition-for-interaction-model", "--job-id", imJobId]; addCoveredCommand(args); - const result = await run(cmd, args, options); + const result = await run(askCmd, args, options); expect(result).be.an("object"); }); it("| should delete job definition for IM", async () => { const args = [subCmd, "delete-job-definition-for-interaction-model", "--job-id", imJobId]; addCoveredCommand(args); - const result = await run(cmd, args, {...options, parse: false}); + const result = await run(askCmd, args, {...options, parse: false}); expect(result).include("Command executed successfully!"); }); it("| should set job status for IM", async () => { const args = [subCmd, "set-job-status-for-interaction-model", "--job-id", imJobId, "--status", imJobStatus]; addCoveredCommand(args); - const result = await run(cmd, args, {...options, parse: false}); + const result = await run(askCmd, args, {...options, parse: false}); expect(result).include("Command executed successfully!"); }); it("| should list all the job executions for IM", async () => { const args = [subCmd, "list-job-executions-for-interaction-model", "--job-id", imJobId]; addCoveredCommand(args); - const result = await run(cmd, args, options); + const result = await run(askCmd, args, options); expect(result).be.an("object"); }); it("| should cancel next job execution for IMJob", async () => { const args = [subCmd, "cancel-next-job-execution-for-interaction-model", "--job-id", imJobId, "--execution-id", imExecutionId]; addCoveredCommand(args); - const result = await run(cmd, args, {...options, parse: false}); + const result = await run(askCmd, args, {...options, parse: false}); expect(result).include("Command executed successfully!"); }); it("| should get resource schema", async () => { const args = [subCmd, "get-resource-schema", "--resource", "manifest"]; addCoveredCommand(args); - const result = await run(cmd, args, options); + const result = await run(askCmd, args, options); expect(result).be.an("object"); }); it("| should list smarthome capability test plans", async () => { const args = [subCmd, "list-smarthome-capability-test-plans", "-s", skillId]; addCoveredCommand(args); - const result = await run(cmd, args, options); + const result = await run(askCmd, args, options); expect(result).be.an("object"); }); it("| should get smarthome capablity evaluation results", async () => { const args = [subCmd, "get-smarthome-capablity-evaluation-results", "-s", skillId, "--evaluation-id", evaluationId]; addCoveredCommand(args); - const result = await run(cmd, args, options); + const result = await run(askCmd, args, options); expect(result).be.an("object"); }); it("| should get smart home capability evaluation", async () => { const args = [subCmd, "get-smart-home-capability-evaluation", "-s", skillId, "--evaluation-id", evaluationId]; addCoveredCommand(args); - const result = await run(cmd, args, options); + const result = await run(askCmd, args, options); expect(result).be.an("object"); }); it("| should list smarthome capability evaluations", async () => { const args = [subCmd, "list-smarthome-capability-evaluations", "-s", skillId]; addCoveredCommand(args); - const result = await run(cmd, args, options); + const result = await run(askCmd, args, options); expect(result).be.an("object"); }); @@ -1420,91 +1421,91 @@ parallel('smapi command test', () => { 2, ]; addCoveredCommand(args); - const result = await run(cmd, args, options); + const result = await run(askCmd, args, options); expect(result).be.an("object"); }); it('| should list all experiments associated with this skill id', async () => { const args = [subCmd, 'list-experiments', '-s', skillId]; addCoveredCommand(args); - const result = await run(cmd, args, options); + const result = await run(askCmd, args, options); expect(result).be.an('object'); }); it('| should create a new experiment for a skill', async () => { const args = [subCmd, 'create-experiment', '-s', skillId, '--experiment-name', experimentName, '--experiment-description', experimentDescription, '--experiment-type', experimentType, '--experiment-planned-duration', experimentPlannedDuration, '--experiment-exposure-percentage', experimentExposurePercentage, '--experiment-metric-configurations', experimentMetricConfigurations]; addCoveredCommand(args); - const result = await run(cmd, args, { ...options, parse: false }); + const result = await run(askCmd, args, { ...options, parse: false }); expect(result).include('Command executed successfully!'); }); it('| should update an existing experiment for a skill', async () => { const args = [subCmd, 'update-experiment', '-s', skillId, '--experiment-id', experimentId, '--experiment-description', experimentDescription, '--experiment-planned-duration', experimentPlannedDuration, '--experiment-exposure-percentage', experimentExposurePercentage, '--experiment-metric-configurations', experimentMetricConfigurations]; addCoveredCommand(args); - const result = await run(cmd, args, { ...options, parse: false }); + const result = await run(askCmd, args, { ...options, parse: false }); expect(result).include('Command executed successfully!'); }); it('| should retrieve an existing experiment for a skill', async () => { const args = [subCmd, 'get-experiment', '-s', skillId, '--experiment-id', experimentId]; addCoveredCommand(args); - const result = await run(cmd, args, options); + const result = await run(askCmd, args, options); expect(result).be.an('object'); }); it('| should delete an existing experiment for a skill', async () => { const args = [subCmd, 'delete-experiment', '-s', skillId, '--experiment-id', experimentId]; addCoveredCommand(args); - const result = await run(cmd, args, { ...options, parse: false }); + const result = await run(askCmd, args, { ...options, parse: false }); expect(result).include('Command executed successfully!'); }); it('| should update the exposure of an experiment that is in CREATED or RUNNING state.', async () => { const args = [subCmd, 'update-exposure', '-s', skillId, '--experiment-id', experimentId, '--exposure-percentage', experimentExposurePercentage]; addCoveredCommand(args); - const result = await run(cmd, args, { ...options, parse: false }); + const result = await run(askCmd, args, { ...options, parse: false }); expect(result).include('Command executed successfully!'); }); it('| should retrieve the current user\'s customer treatment override for an existing A/B Test experiment', async () => { const args = [subCmd, 'get-customer-treatment-override', '-s', skillId, '--experiment-id', experimentId]; addCoveredCommand(args); - const result = await run(cmd, args, options); + const result = await run(askCmd, args, options); expect(result).be.an('object'); }); it('| should add the requesting user\'s customer treatment override to an existing experiment.', async () => { const args = [subCmd, 'set-customer-treatment-override', '-s', skillId, '--experiment-id', experimentId, '--treatment-id', treatmentId]; addCoveredCommand(args); - const result = await run(cmd, args, { ...options, parse: false }); + const result = await run(askCmd, args, { ...options, parse: false }); expect(result).include('Command executed successfully!'); }); it('| should retrieve the current state of the experiment.', async () => { const args = [subCmd, 'get-experiment-state', '-s', skillId, '--experiment-id', experimentId]; addCoveredCommand(args); - const result = await run(cmd, args, options); + const result = await run(askCmd, args, options); expect(result).be.an('object'); }); it('| should request an action on the experiment to move it to the targetState.', async () => { const args = [subCmd, 'manage-experiment-state', '-s', skillId, '--experiment-id', experimentId, '--target-state', targetState]; addCoveredCommand(args); - const result = await run(cmd, args, { ...options, parse: false }); + const result = await run(askCmd, args, { ...options, parse: false }); expect(result).include('Command executed successfully!'); }); it('| should get a list of all metric snapshots associated with this experiment id.', async () => { const args = [subCmd, 'list-experiment-metric-snapshots', '-s', skillId, '--experiment-id', experimentId]; addCoveredCommand(args); - const result = await run(cmd, args, options); + const result = await run(askCmd, args, options); expect(result).be.an('object'); }); it('| should gets a list of all metric data associated with this experiment\'s metric snapshot.', async () => { const args = [subCmd, 'get-experiment-metric-snapshot', '-s', skillId, '--experiment-id', experimentId, '--metric-snapshot-id', metricSnapShotId]; addCoveredCommand(args); - const result = await run(cmd, args, options); + const result = await run(askCmd, args, options); expect(result).be.an('object'); }); From f0f6097b0dfdd965f43abc1793b7fbe50105e271 Mon Sep 17 00:00:00 2001 From: Mario Doiron <4956+doiron@users.noreply.github.com> Date: Thu, 30 Mar 2023 21:19:40 -0700 Subject: [PATCH 08/10] fix: removing node 14 for integration test again --- .github/workflows/integration-test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/integration-test.yml b/.github/workflows/integration-test.yml index c1f541c1..77df3142 100644 --- a/.github/workflows/integration-test.yml +++ b/.github/workflows/integration-test.yml @@ -18,7 +18,7 @@ jobs: strategy: matrix: os: [ubuntu-latest, windows-latest, macos-latest] - node: [14, 16] + node: [16] steps: - uses: actions/checkout@v3 - name: Use Node.js ${{ matrix.node }} From caec99472346f2ce536fad5081a42188407d9ce4 Mon Sep 17 00:00:00 2001 From: Mario Doiron <4956+doiron@users.noreply.github.com> Date: Fri, 31 Mar 2023 10:31:13 -0700 Subject: [PATCH 09/10] fix: removing unused dialog-evaluate test projects --- .../test-project-1/.ask/ask-states.json | 8 - .../test-project-1/ask-resources.json | 10 - .../conversations/ALexaPrize.acdl | 203 ---- .../conversations/Dialog_NonDeployable.acdl | 81 -- ...ableDialogsUsage_NonDeployableDialogs.acdl | 45 - .../skill-package/conversations/Weather.acdl | 137 --- .../skill-package/conversations/apis.acdl | 15 - .../conversations/apisNamepaceLambda.acdl | 22 - .../conversations/conversation_empty.acdl | 114 -- .../conversations/fruitNameApi.acdl | 34 - .../conversations/soaDialog.acdl | 123 --- .../skill-package/conversations/types.acdl | 43 - .../conversations/utteracesets.acdl | 82 -- .../interactionModels/custom/en-US.json | 919 ----------------- .../confirm_city_apl_display/document.json | 331 ------ .../confirm_date_apl_display/document.json | 331 ------ .../document.json | 379 ------- .../request_city_apl_display/document.json | 331 ------ .../request_date_apl_display/document.json | 331 ------ .../weather_success_apl_display/document.json | 379 ------- .../AlexaConversationsBye/document.json | 19 - .../document.json | 19 - .../document.json | 19 - .../document.json | 19 - .../document.json | 19 - .../AlexaConversationsThankYou/document.json | 19 - .../AlexaConversationsWelcome/document.json | 19 - .../document.json | 19 - .../document.json | 89 -- .../document.json | 19 - .../confirm_fruitName_apla/document.json | 19 - .../document.json | 19 - .../response/prompts/no_apla/document.json | 19 - .../prompts/nothing2_apla/document.json | 19 - .../prompts/nothing_apla/document.json | 19 - .../numericfeedback_apla/document.json | 19 - .../prompts/rating_apla/document.json | 19 - .../document.json | 25 - .../prompts/request_city_apla/document.json | 19 - .../request_city_date_apla/document.json | 19 - .../document.json | 19 - .../prompts/request_date_apla/document.json | 19 - .../request_dob_getDate_apla/document.json | 19 - .../request_getEmploeeID_apla/document.json | 19 - .../prompts/request_name_apla/document.json | 19 - .../success_colorFruitAPI_apla/document.json | 19 - .../success_fruitPriceAPI_apla/document.json | 19 - .../prompts/weather_apla/document.json | 27 - .../response/prompts/yes_apla/document.json | 19 - .../prompts/yesnofeedback_apla/document.json | 19 - .../test-project-1/skill-package/skill.json | 92 -- .../test-project-2/.ask/ask-states.json | 8 - .../test-project-2/ask-resources.json | 10 - .../conversations/Samenamespace.acdl | 7 - .../skill-package/conversations/apis.acdl | 51 - .../conversations/basicOfferDialog.acdl | 65 -- .../skill-package/conversations/conditions | 71 -- .../conversations/conversation_empty | 147 --- .../conversations/delegateToSkill.acdl | 33 - .../conversations/dialogWeather.acdl | 9 - .../listDialogWithConditions.acdl | 243 ----- .../conversations/optionalDelegate.acdl | 118 --- .../skill-package/conversations/pizza.acdl | 189 ---- .../conversations/soaDialog.acdl | 50 - .../skill-package/conversations/types.acdl | 248 ----- .../conversations/utteracesets.acdl | 435 -------- .../conversations/welcomeAPI.acdl | 38 - .../interactionModels/custom/en-US.json | 527 ---------- .../confirm_city_apl_display/document.json | 331 ------ .../confirm_date_apl_display/document.json | 331 ------ .../document.json | 379 ------- .../request_city_apl_display/document.json | 331 ------ .../request_date_apl_display/document.json | 331 ------ .../weather_success_apl_display/document.json | 379 ------- .../AlexaConversationsBye/document.json | 19 - .../document.json | 19 - .../document.json | 19 - .../document.json | 19 - .../document.json | 19 - .../AlexaConversationsThankYou/document.json | 19 - .../AlexaConversationsWelcome/document.json | 19 - .../document.json | 19 - .../document.json | 20 - .../document.json | 20 - .../datasources/default.json | 1 - .../prompts/askForCrustPrompts/document.json | 26 - .../datasources/default.json | 1 - .../prompts/askForSizePrompts/document.json | 26 - .../datasources/default.json | 1 - .../askForToppingOnePrompt/document.json | 20 - .../datasources/default.json | 1 - .../askForToppingTwoPrompt/document.json | 20 - .../datasources/default.json | 1 - .../askForToppingsPrompts/document.json | 20 - .../datasources/default.json | 1 - .../askForTwoToppingsPrompts/document.json | 20 - .../datasources/default.json | 1 - .../document.json | 20 - .../document.json | 19 - .../document.json | 19 - .../datasources/default.json | 1 - .../prompts/confirmSizePrompt/document.json | 20 - .../datasources/default.json | 1 - .../document.json | 20 - .../datasources/default.json | 1 - .../document.json | 20 - .../datasources/default.json | 1 - .../confirmTwoToppingsPrompt/document.json | 20 - .../document.json | 19 - .../confirm_fruitName_apla/document.json | 19 - .../document.json | 19 - .../confirm_weather_apla/document.json | 19 - .../confirm_weather_city_apla/document.json | 19 - .../confirm_weather_date_apla/document.json | 19 - .../response/prompts/no_apla/document.json | 19 - .../prompts/nothing2_apla/document.json | 19 - .../prompts/nothing_apla/document.json | 19 - .../numericfeedback_apla/document.json | 19 - .../prompts/rating_apla/document.json | 19 - .../document.json | 25 - .../requestFromBookFlight_apla/document.json | 20 - .../document.json | 20 - .../requestToBookFlight_apla/document.json | 20 - .../prompts/request_city_apla/document.json | 19 - .../request_city_cityName_apla/document.json | 25 - .../document.json | 19 - .../document.json | 19 - .../document.json | 19 - .../prompts/request_date_apla/document.json | 19 - .../request_listAddOns_apla/document.json | 19 - .../request_mainFoodName_apla/document.json | 19 - .../prompts/request_name_apla/document.json | 19 - .../prompts/request_sign_apla/document.json | 19 - .../requestdropToBookCab_apla/document.json | 20 - .../prompts/secondEarthAPI_apla/document.json | 19 - .../prompts/seq_offer_apla/document.json | 19 - .../successBookCabAPI_apla/document.json | 20 - .../successBookFlightAPI_apla/document.json | 20 - .../success_cookingAPI_apla/document.json | 19 - .../document.json | 19 - .../success_fruitPriceAPI_apla/document.json | 19 - .../datasources/default.json | 1 - .../document.json | 20 - .../weather_success_apla/document.json | 27 - .../prompts/welcome_apla_custom/document.json | 19 - .../test-project-2/skill-package/skill.json | 93 -- .../test-project-3/.ask/ask-states.json | 8 - .../test-project-3/ask-resources.json | 10 - .../TestDataACDLi18n/deBye/document.json | 18 - .../TestDataACDLi18n/deHelp/document.json | 19 - .../deOutOfDomain/datasources/default.json | 1 - .../deOutOfDomain/document.json | 18 - .../deRequireMore/document.json | 19 - .../TestDataACDLi18n/deWelcome/document.json | 18 - .../conversations/ALexaPrize.acdl | 203 ---- .../conversations/Dialog_NonDeployable.acdl | 81 -- ...ableDialogsUsage_NonDeployableDialogs.acdl | 50 - .../skill-package/conversations/Weather.acdl | 152 --- .../skill-package/conversations/apis.acdl | 17 - .../conversations/apisNamepaceLambda.acdl | 23 - .../conversations/conversation_empty.acdl | 114 -- .../conversations/fruitNameApi.acdl | 34 - .../conversations/separateConfig.acdl | 98 -- .../conversations/soaDialog.acdl | 132 --- .../skill-package/conversations/types.acdl | 43 - .../conversations/utteracesets.acdl | 82 -- .../interactionModels/custom/de-DE.json | 919 ----------------- .../interactionModels/custom/en-US.json | 919 ----------------- .../confirm_city_apl_display/document.json | 331 ------ .../confirm_date_apl_display/document.json | 331 ------ .../document.json | 379 ------- .../display/display_de_apl/document.json | 331 ------ .../request_city_apl_display/document.json | 331 ------ .../request_date_apl_display/document.json | 331 ------ .../weather_success_apl_display/document.json | 379 ------- .../AlexaConversationsBye/document.json | 19 - .../document.json | 19 - .../document.json | 19 - .../document.json | 19 - .../document.json | 19 - .../AlexaConversationsThankYou/document.json | 19 - .../AlexaConversationsWelcome/document.json | 19 - .../document.json | 19 - .../document.json | 89 -- .../document.json | 19 - .../confirm_fruitName_apla/document.json | 19 - .../document.json | 19 - .../response/prompts/no_apla/document.json | 19 - .../prompts/nothing2_apla/document.json | 19 - .../prompts/nothing_apla/document.json | 19 - .../numericfeedback_apla/document.json | 19 - .../prompts/rating_apla/document.json | 19 - .../document.json | 25 - .../prompts/request_city_apla/document.json | 19 - .../request_city_date_apla/document.json | 19 - .../document.json | 19 - .../prompts/request_date_apla/document.json | 19 - .../request_dob_getDate_apla/document.json | 19 - .../request_getEmploeeID_apla/document.json | 19 - .../prompts/request_name_apla/document.json | 19 - .../success_colorFruitAPI_apla/document.json | 19 - .../success_fruitPriceAPI_apla/document.json | 19 - .../prompts/weather_apla/document.json | 27 - .../weather_apla_de_apla/document.json | 27 - .../response/prompts/yes_apla/document.json | 19 - .../prompts/yesnofeedback_apla/document.json | 19 - .../test-project-3/skill-package/skill.json | 105 -- .../test-project-5/.ask/ask-states.json | 8 - .../test-project-5/ask-resources.json | 10 - .../conversations/Samenamespace.acdl | 7 - .../skill-package/conversations/apisMine.acdl | 50 - .../conversations/basicOfferDialog.acdl | 134 --- .../conversations/conditions.acdl | 172 --- .../conversations/conversation_empty.acdl | 109 -- .../conversations/delegateToSkill.acdl | 29 - .../conversations/dialogWeather.acdl | 9 - .../listDialogWithConditions.acdl | 250 ----- .../conversations/optionalDelegate.acdl | 162 --- .../skill-package/conversations/pizza.acdl | 196 ---- .../conversations/soaDialog.acdl | 89 -- .../conversations/typesMine.acdl | 248 ----- .../conversations/utteracesetsMine.acdl | 455 -------- .../conversations/welcomeAPI.acdl | 34 - .../interactionModels/custom/en-US.json | 564 ---------- .../confirm_city_apl_display/document.json | 358 ------- .../confirm_date_apl_display/document.json | 358 ------- .../document.json | 412 -------- .../request_city_apl_display/document.json | 358 ------- .../request_date_apl_display/document.json | 358 ------- .../weather_success_apl_display/document.json | 412 -------- .../AlexaConversationsBye/document.json | 21 - .../document.json | 21 - .../document.json | 21 - .../document.json | 21 - .../document.json | 21 - .../AlexaConversationsThankYou/document.json | 21 - .../AlexaConversationsWelcome/document.json | 21 - .../document.json | 21 - .../document.json | 22 - .../document.json | 22 - .../datasources/default.json | 1 - .../prompts/askForCrustPrompts/document.json | 1 - .../datasources/default.json | 1 - .../prompts/askForSizePrompts/document.json | 1 - .../datasources/default.json | 1 - .../askForToppingOnePrompt/document.json | 1 - .../datasources/default.json | 1 - .../askForToppingTwoPrompt/document.json | 1 - .../datasources/default.json | 1 - .../askForToppingsPrompts/document.json | 1 - .../datasources/default.json | 1 - .../askForTwoToppingsPrompts/document.json | 1 - .../datasources/default.json | 1 - .../document.json | 1 - .../document.json | 28 - .../document.json | 21 - .../datasources/default.json | 1 - .../prompts/confirmSizePrompt/document.json | 1 - .../datasources/default.json | 1 - .../document.json | 22 - .../datasources/default.json | 1 - .../document.json | 22 - .../datasources/default.json | 1 - .../confirmTwoToppingsPrompt/document.json | 1 - .../document.json | 21 - .../confirm_fruitName_apla/document.json | 21 - .../document.json | 21 - .../confirm_weather_apla/document.json | 21 - .../confirm_weather_city_apla/document.json | 21 - .../confirm_weather_date_apla/document.json | 21 - .../response/prompts/no_apla/document.json | 21 - .../prompts/nothing2_apla/document.json | 21 - .../prompts/nothing_apla/document.json | 21 - .../numericfeedback_apla/document.json | 19 - .../prompts/rating_apla/document.json | 21 - .../document.json | 27 - .../requestFromBookFlight_apla/document.json | 22 - .../document.json | 22 - .../requestToBookFlight_apla/document.json | 22 - .../prompts/request_city_apla/document.json | 21 - .../request_city_cityName_apla/document.json | 27 - .../document.json | 21 - .../document.json | 21 - .../document.json | 21 - .../prompts/request_date_apla/document.json | 21 - .../request_listAddOns_apla/document.json | 21 - .../request_mainFoodName_apla/document.json | 21 - .../prompts/request_name_apla/document.json | 21 - .../prompts/request_sign_apla/document.json | 21 - .../requestdropToBookCab_apla/document.json | 22 - .../prompts/secondEarthAPI_apla/document.json | 21 - .../prompts/seq_offer_apla/document.json | 21 - .../successBookCabAPI_apla/document.json | 22 - .../successBookFlightAPI_apla/document.json | 22 - .../success_cookingAPI_apla/document.json | 21 - .../document.json | 22 - .../success_fruitPriceAPI_apla/document.json | 21 - .../datasources/default.json | 1 - .../document.json | 22 - .../weather_success_apla/document.json | 29 - .../prompts/welcome_apla_custom/document.json | 21 - .../test-project-5/skill-package/skill.json | 96 -- .../test-project-6/.ask/ask-states.json | 8 - .../test-project-6/ask-resources.json | 10 - .../conversations/ALexaPrize.acdl | 213 ---- .../conversations/Dialog_NonDeployable.acdl | 90 -- ...ableDialogsUsage_NonDeployableDialogs.acdl | 47 - .../skill-package/conversations/Weather.acdl | 139 --- .../conversations/apisNamepaceLambda.acdl | 22 - .../conversations/apis_mine.acdl | 15 - .../conversations/conversation_empty.acdl | 115 --- .../conversations/soaDialog.acdl | 89 -- .../conversations/types_mine.acdl | 43 - .../conversations/utteracesets_mine.acdl | 82 -- .../interactionModels/custom/en-US.json | 923 ----------------- .../confirm_city_apl_display/document.json | 358 ------- .../confirm_date_apl_display/document.json | 358 ------- .../document.json | 412 -------- .../request_city_apl_display/document.json | 358 ------- .../request_date_apl_display/document.json | 358 ------- .../weather_success_apl_display/document.json | 412 -------- .../AlexaConversationsBye/document.json | 21 - .../document.json | 21 - .../document.json | 21 - .../document.json | 21 - .../document.json | 21 - .../AlexaConversationsThankYou/document.json | 21 - .../AlexaConversationsWelcome/document.json | 21 - .../document.json | 21 - .../document.json | 91 -- .../document.json | 21 - .../confirm_fruitName_apla/document.json | 21 - .../document.json | 21 - .../response/prompts/no_apla/document.json | 21 - .../prompts/nothing2_apla/document.json | 21 - .../prompts/nothing_apla/document.json | 21 - .../numericfeedback_apla/document.json | 19 - .../prompts/rating_apla/document.json | 21 - .../document.json | 27 - .../prompts/request_city_apla/document.json | 21 - .../request_city_date_apla/document.json | 21 - .../document.json | 21 - .../prompts/request_date_apla/document.json | 21 - .../request_dob_getDate_apla/document.json | 21 - .../request_getEmploeeID_apla/document.json | 21 - .../prompts/request_name_apla/document.json | 21 - .../success_colorFruitAPI_apla/document.json | 21 - .../success_fruitPriceAPI_apla/document.json | 21 - .../prompts/weather_apla/document.json | 29 - .../response/prompts/yes_apla/document.json | 21 - .../prompts/yesnofeedback_apla/document.json | 21 - .../test-project-6/skill-package/skill.json | 97 -- .../test-project-7/.ask/ask-states.json | 8 - .../test-project-7/ask-resources.json | 10 - .../TestDataACDLi18n/deBye/document.json | 20 - .../TestDataACDLi18n/deHelp/document.json | 21 - .../deOutOfDomain/datasources/default.json | 1 - .../deOutOfDomain/document.json | 20 - .../deRequireMore/document.json | 21 - .../TestDataACDLi18n/deWelcome/document.json | 20 - .../conversations/ALexaPrize.acdl | 203 ---- .../conversations/Dialog_NonDeployable.acdl | 79 -- ...ableDialogsUsage_NonDeployableDialogs.acdl | 50 - .../conversations/MoreDialogs.acdl | 174 ---- .../skill-package/conversations/Weather.acdl | 154 --- .../skill-package/conversations/apis.acdl | 36 - .../conversations/apisNamepaceLambda | 23 - .../conversations/conversation_empty.acdl | 114 -- .../conversations/delegateToSkill.acdl | 33 - .../conversations/fruitNameApi.acdl | 34 - .../conversations/separateConfig.acdl | 83 -- .../conversations/soaDialog.acdl | 132 --- .../skill-package/conversations/test | 4 - .../skill-package/conversations/types.acdl | 43 - .../conversations/utteracesets.acdl | 82 -- .../interactionModels/custom/de-DE.json | 963 ----------------- .../interactionModels/custom/en-GB.json | 963 ----------------- .../interactionModels/custom/en-US.json | 976 ------------------ .../confirm_city_apl_display/document.json | 358 ------- .../confirm_date_apl_display/document.json | 358 ------- .../document.json | 412 -------- .../display/display_de_apl/document.json | 358 ------- .../dummyLastScreen/datasources/default.json | 1 - .../display/dummyLastScreen/document.json | 1 - .../dummyLastScreen/sources/default.json | 1 - .../request_city_apl_display/document.json | 358 ------- .../request_date_apl_display/document.json | 358 ------- .../weather_success_apl_display/document.json | 412 -------- .../AlexaConversationsBye/document.json | 21 - .../document.json | 21 - .../document.json | 21 - .../document.json | 21 - .../document.json | 21 - .../AlexaConversationsThankYou/document.json | 21 - .../AlexaConversationsWelcome/document.json | 21 - .../document.json | 21 - .../document.json | 91 -- .../document.json | 21 - .../confirm_fruitName_apla/document.json | 21 - .../document.json | 21 - .../response/prompts/no_apla/document.json | 21 - .../prompts/nothing2_apla/document.json | 21 - .../prompts/nothing_apla/document.json | 21 - .../numericfeedback_apla/document.json | 21 - .../prompts/rating_apla/document.json | 21 - .../document.json | 27 - .../prompts/request_city_apla/document.json | 21 - .../request_city_date_apla/document.json | 21 - .../document.json | 21 - .../prompts/request_date_apla/document.json | 21 - .../request_dob_getDate_apla/document.json | 21 - .../request_getEmploeeID_apla/document.json | 21 - .../prompts/request_name_apla/document.json | 21 - .../prompts/response0Prompt16/document.json | 1 - .../prompts/secondEarthAPI_apla/document.json | 21 - .../success_colorFruitAPI_apla/document.json | 21 - .../success_fruitPriceAPI_apla/document.json | 21 - .../prompts/weather_apla/document.json | 29 - .../weather_apla_de_apla/document.json | 29 - .../whoAmiSuccess/datasources/default.json | 7 - .../prompts/whoAmiSuccess/document.json | 22 - .../response/prompts/yes_apla/document.json | 21 - .../prompts/yesnofeedback_apla/document.json | 21 - .../test-project-7/skill-package/skill.json | 119 --- 424 files changed, 35094 deletions(-) delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-1/.ask/ask-states.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-1/ask-resources.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-1/skill-package/conversations/ALexaPrize.acdl delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-1/skill-package/conversations/Dialog_NonDeployable.acdl delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-1/skill-package/conversations/Dialogs_reusableDialogsUsage_NonDeployableDialogs.acdl delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-1/skill-package/conversations/Weather.acdl delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-1/skill-package/conversations/apis.acdl delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-1/skill-package/conversations/apisNamepaceLambda.acdl delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-1/skill-package/conversations/conversation_empty.acdl delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-1/skill-package/conversations/fruitNameApi.acdl delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-1/skill-package/conversations/soaDialog.acdl delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-1/skill-package/conversations/types.acdl delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-1/skill-package/conversations/utteracesets.acdl delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-1/skill-package/interactionModels/custom/en-US.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/display/confirm_city_apl_display/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/display/confirm_date_apl_display/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/display/confirm_weather_apla_display/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/display/request_city_apl_display/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/display/request_date_apl_display/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/display/weather_success_apl_display/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/AlexaConversationsBye/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/AlexaConversationsNotifyFailure/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/AlexaConversationsOutOfDomain/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/AlexaConversationsProvideHelp/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/AlexaConversationsRequestMore/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/AlexaConversationsThankYou/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/AlexaConversationsWelcome/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/AlexaConversationsYouAreWelcome/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/alexa_prize_preconditions_apla/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/confirm_color_for_fruit_apla/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/confirm_fruitName_apla/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/getEmployeePosition_success_apla/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/no_apla/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/nothing2_apla/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/nothing_apla/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/numericfeedback_apla/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/rating_apla/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/requestArgs_request_fruitName_apla/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/request_city_apla/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/request_city_date_apla/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/request_colorName_multiple_apla/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/request_date_apla/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/request_dob_getDate_apla/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/request_getEmploeeID_apla/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/request_name_apla/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/success_colorFruitAPI_apla/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/success_fruitPriceAPI_apla/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/weather_apla/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/yes_apla/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/yesnofeedback_apla/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-1/skill-package/skill.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/.ask/ask-states.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/ask-resources.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/conversations/Samenamespace.acdl delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/conversations/apis.acdl delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/conversations/basicOfferDialog.acdl delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/conversations/conditions delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/conversations/conversation_empty delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/conversations/delegateToSkill.acdl delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/conversations/dialogWeather.acdl delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/conversations/listDialogWithConditions.acdl delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/conversations/optionalDelegate.acdl delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/conversations/pizza.acdl delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/conversations/soaDialog.acdl delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/conversations/types.acdl delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/conversations/utteracesets.acdl delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/conversations/welcomeAPI.acdl delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/interactionModels/custom/en-US.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/display/confirm_city_apl_display/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/display/confirm_date_apl_display/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/display/confirm_weather_apla_display/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/display/request_city_apl_display/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/display/request_date_apl_display/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/display/weather_success_apl_display/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/AlexaConversationsBye/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/AlexaConversationsNotifyFailure/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/AlexaConversationsOutOfDomain/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/AlexaConversationsProvideHelp/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/AlexaConversationsRequestMore/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/AlexaConversationsThankYou/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/AlexaConversationsWelcome/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/AlexaConversationsYouAreWelcome/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/SuccessGiveMeTodaySpecialsEvent_apla/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/SuccessGiveMeTodaySpecialsEvent_apla_failure/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/askForCrustPrompts/datasources/default.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/askForCrustPrompts/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/askForSizePrompts/datasources/default.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/askForSizePrompts/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/askForToppingOnePrompt/datasources/default.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/askForToppingOnePrompt/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/askForToppingTwoPrompt/datasources/default.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/askForToppingTwoPrompt/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/askForToppingsPrompts/datasources/default.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/askForToppingsPrompts/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/askForTwoToppingsPrompts/datasources/default.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/askForTwoToppingsPrompts/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/askForTwoToppingsPrompts_copy/datasources/default.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/askForTwoToppingsPrompts_copy/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/confirmAction_complexNames_apla/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/confirmArgs_complexNames_apla/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/confirmSizePrompt/datasources/default.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/confirmSizePrompt/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/confirmTwoToppingOrderPrompt/datasources/default.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/confirmTwoToppingOrderPrompt/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/confirmTwoToppingOrderPromptcopy/datasources/default.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/confirmTwoToppingOrderPromptcopy/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/confirmTwoToppingsPrompt/datasources/default.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/confirmTwoToppingsPrompt/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/confirm_color_for_fruit_apla/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/confirm_fruitName_apla/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/confirm_main_addon_list_apla/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/confirm_weather_apla/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/confirm_weather_city_apla/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/confirm_weather_date_apla/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/no_apla/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/nothing2_apla/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/nothing_apla/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/numericfeedback_apla/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/rating_apla/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/requestArgs_request_fruitName_apla/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/requestFromBookFlight_apla/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/requestPickUpFromBookCab_apla/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/requestToBookFlight_apla/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/request_city_apla/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/request_city_cityName_apla/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/request_city_cityName_date_AMAZON_DATE_apla/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/request_colorName_multiple_apla/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/request_date_AMAZON_DATE_apla/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/request_date_apla/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/request_listAddOns_apla/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/request_mainFoodName_apla/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/request_name_apla/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/request_sign_apla/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/requestdropToBookCab_apla/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/secondEarthAPI_apla/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/seq_offer_apla/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/successBookCabAPI_apla/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/successBookFlightAPI_apla/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/success_cookingAPI_apla/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/success_favColorSign_Name_apla/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/success_fruitPriceAPI_apla/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/twoToppingOrderSuccessPrompt/datasources/default.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/twoToppingOrderSuccessPrompt/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/weather_success_apla/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/welcome_apla_custom/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-2/skill-package/skill.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-3/.ask/ask-states.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-3/ask-resources.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-3/skill-package/TestDataACDLi18n/deBye/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-3/skill-package/TestDataACDLi18n/deHelp/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-3/skill-package/TestDataACDLi18n/deOutOfDomain/datasources/default.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-3/skill-package/TestDataACDLi18n/deOutOfDomain/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-3/skill-package/TestDataACDLi18n/deRequireMore/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-3/skill-package/TestDataACDLi18n/deWelcome/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-3/skill-package/conversations/ALexaPrize.acdl delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-3/skill-package/conversations/Dialog_NonDeployable.acdl delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-3/skill-package/conversations/Dialogs_reusableDialogsUsage_NonDeployableDialogs.acdl delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-3/skill-package/conversations/Weather.acdl delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-3/skill-package/conversations/apis.acdl delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-3/skill-package/conversations/apisNamepaceLambda.acdl delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-3/skill-package/conversations/conversation_empty.acdl delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-3/skill-package/conversations/fruitNameApi.acdl delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-3/skill-package/conversations/separateConfig.acdl delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-3/skill-package/conversations/soaDialog.acdl delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-3/skill-package/conversations/types.acdl delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-3/skill-package/conversations/utteracesets.acdl delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-3/skill-package/interactionModels/custom/de-DE.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-3/skill-package/interactionModels/custom/en-US.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/display/confirm_city_apl_display/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/display/confirm_date_apl_display/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/display/confirm_weather_apla_display/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/display/display_de_apl/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/display/request_city_apl_display/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/display/request_date_apl_display/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/display/weather_success_apl_display/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/AlexaConversationsBye/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/AlexaConversationsNotifyFailure/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/AlexaConversationsOutOfDomain/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/AlexaConversationsProvideHelp/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/AlexaConversationsRequestMore/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/AlexaConversationsThankYou/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/AlexaConversationsWelcome/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/AlexaConversationsYouAreWelcome/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/alexa_prize_preconditions_apla/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/confirm_color_for_fruit_apla/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/confirm_fruitName_apla/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/getEmployeePosition_success_apla/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/no_apla/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/nothing2_apla/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/nothing_apla/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/numericfeedback_apla/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/rating_apla/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/requestArgs_request_fruitName_apla/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/request_city_apla/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/request_city_date_apla/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/request_colorName_multiple_apla/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/request_date_apla/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/request_dob_getDate_apla/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/request_getEmploeeID_apla/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/request_name_apla/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/success_colorFruitAPI_apla/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/success_fruitPriceAPI_apla/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/weather_apla/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/weather_apla_de_apla/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/yes_apla/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/yesnofeedback_apla/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-3/skill-package/skill.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/.ask/ask-states.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/ask-resources.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/conversations/Samenamespace.acdl delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/conversations/apisMine.acdl delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/conversations/basicOfferDialog.acdl delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/conversations/conditions.acdl delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/conversations/conversation_empty.acdl delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/conversations/delegateToSkill.acdl delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/conversations/dialogWeather.acdl delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/conversations/listDialogWithConditions.acdl delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/conversations/optionalDelegate.acdl delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/conversations/pizza.acdl delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/conversations/soaDialog.acdl delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/conversations/typesMine.acdl delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/conversations/utteracesetsMine.acdl delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/conversations/welcomeAPI.acdl delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/interactionModels/custom/en-US.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/display/confirm_city_apl_display/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/display/confirm_date_apl_display/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/display/confirm_weather_apla_display/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/display/request_city_apl_display/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/display/request_date_apl_display/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/display/weather_success_apl_display/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/AlexaConversationsBye/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/AlexaConversationsNotifyFailure/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/AlexaConversationsOutOfDomain/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/AlexaConversationsProvideHelp/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/AlexaConversationsRequestMore/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/AlexaConversationsThankYou/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/AlexaConversationsWelcome/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/AlexaConversationsYouAreWelcome/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/SuccessGiveMeTodaySpecialsEvent_apla/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/SuccessGiveMeTodaySpecialsEvent_apla_failure/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/askForCrustPrompts/datasources/default.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/askForCrustPrompts/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/askForSizePrompts/datasources/default.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/askForSizePrompts/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/askForToppingOnePrompt/datasources/default.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/askForToppingOnePrompt/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/askForToppingTwoPrompt/datasources/default.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/askForToppingTwoPrompt/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/askForToppingsPrompts/datasources/default.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/askForToppingsPrompts/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/askForTwoToppingsPrompts/datasources/default.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/askForTwoToppingsPrompts/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/askForTwoToppingsPrompts_copy/datasources/default.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/askForTwoToppingsPrompts_copy/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/confirmAction_complexNames_apla/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/confirmArgs_complexNames_apla/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/confirmSizePrompt/datasources/default.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/confirmSizePrompt/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/confirmTwoToppingOrderPrompt/datasources/default.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/confirmTwoToppingOrderPrompt/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/confirmTwoToppingOrderPromptcopy/datasources/default.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/confirmTwoToppingOrderPromptcopy/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/confirmTwoToppingsPrompt/datasources/default.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/confirmTwoToppingsPrompt/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/confirm_color_for_fruit_apla/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/confirm_fruitName_apla/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/confirm_main_addon_list_apla/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/confirm_weather_apla/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/confirm_weather_city_apla/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/confirm_weather_date_apla/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/no_apla/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/nothing2_apla/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/nothing_apla/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/numericfeedback_apla/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/rating_apla/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/requestArgs_request_fruitName_apla/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/requestFromBookFlight_apla/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/requestPickUpFromBookCab_apla/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/requestToBookFlight_apla/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/request_city_apla/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/request_city_cityName_apla/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/request_city_cityName_date_AMAZON_DATE_apla/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/request_colorName_multiple_apla/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/request_date_AMAZON_DATE_apla/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/request_date_apla/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/request_listAddOns_apla/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/request_mainFoodName_apla/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/request_name_apla/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/request_sign_apla/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/requestdropToBookCab_apla/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/secondEarthAPI_apla/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/seq_offer_apla/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/successBookCabAPI_apla/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/successBookFlightAPI_apla/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/success_cookingAPI_apla/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/success_favColorSign_Name_apla/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/success_fruitPriceAPI_apla/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/twoToppingOrderSuccessPrompt/datasources/default.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/twoToppingOrderSuccessPrompt/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/weather_success_apla/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/welcome_apla_custom/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-5/skill-package/skill.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-6/.ask/ask-states.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-6/ask-resources.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-6/skill-package/conversations/ALexaPrize.acdl delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-6/skill-package/conversations/Dialog_NonDeployable.acdl delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-6/skill-package/conversations/Dialogs_reusableDialogsUsage_NonDeployableDialogs.acdl delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-6/skill-package/conversations/Weather.acdl delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-6/skill-package/conversations/apisNamepaceLambda.acdl delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-6/skill-package/conversations/apis_mine.acdl delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-6/skill-package/conversations/conversation_empty.acdl delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-6/skill-package/conversations/soaDialog.acdl delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-6/skill-package/conversations/types_mine.acdl delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-6/skill-package/conversations/utteracesets_mine.acdl delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-6/skill-package/interactionModels/custom/en-US.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/display/confirm_city_apl_display/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/display/confirm_date_apl_display/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/display/confirm_weather_apla_display/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/display/request_city_apl_display/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/display/request_date_apl_display/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/display/weather_success_apl_display/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/AlexaConversationsBye/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/AlexaConversationsNotifyFailure/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/AlexaConversationsOutOfDomain/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/AlexaConversationsProvideHelp/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/AlexaConversationsRequestMore/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/AlexaConversationsThankYou/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/AlexaConversationsWelcome/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/AlexaConversationsYouAreWelcome/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/alexa_prize_preconditions_apla/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/confirm_color_for_fruit_apla/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/confirm_fruitName_apla/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/getEmployeePosition_success_apla/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/no_apla/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/nothing2_apla/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/nothing_apla/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/numericfeedback_apla/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/rating_apla/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/requestArgs_request_fruitName_apla/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/request_city_apla/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/request_city_date_apla/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/request_colorName_multiple_apla/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/request_date_apla/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/request_dob_getDate_apla/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/request_getEmploeeID_apla/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/request_name_apla/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/success_colorFruitAPI_apla/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/success_fruitPriceAPI_apla/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/weather_apla/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/yes_apla/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/yesnofeedback_apla/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-6/skill-package/skill.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-7/.ask/ask-states.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-7/ask-resources.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-7/skill-package/TestDataACDLi18n/deBye/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-7/skill-package/TestDataACDLi18n/deHelp/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-7/skill-package/TestDataACDLi18n/deOutOfDomain/datasources/default.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-7/skill-package/TestDataACDLi18n/deOutOfDomain/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-7/skill-package/TestDataACDLi18n/deRequireMore/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-7/skill-package/TestDataACDLi18n/deWelcome/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-7/skill-package/conversations/ALexaPrize.acdl delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-7/skill-package/conversations/Dialog_NonDeployable.acdl delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-7/skill-package/conversations/Dialogs_reusableDialogsUsage_NonDeployableDialogs.acdl delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-7/skill-package/conversations/MoreDialogs.acdl delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-7/skill-package/conversations/Weather.acdl delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-7/skill-package/conversations/apis.acdl delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-7/skill-package/conversations/apisNamepaceLambda delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-7/skill-package/conversations/conversation_empty.acdl delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-7/skill-package/conversations/delegateToSkill.acdl delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-7/skill-package/conversations/fruitNameApi.acdl delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-7/skill-package/conversations/separateConfig.acdl delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-7/skill-package/conversations/soaDialog.acdl delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-7/skill-package/conversations/test delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-7/skill-package/conversations/types.acdl delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-7/skill-package/conversations/utteracesets.acdl delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-7/skill-package/interactionModels/custom/de-DE.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-7/skill-package/interactionModels/custom/en-GB.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-7/skill-package/interactionModels/custom/en-US.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/display/confirm_city_apl_display/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/display/confirm_date_apl_display/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/display/confirm_weather_apla_display/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/display/display_de_apl/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/display/dummyLastScreen/datasources/default.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/display/dummyLastScreen/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/display/dummyLastScreen/sources/default.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/display/request_city_apl_display/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/display/request_date_apl_display/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/display/weather_success_apl_display/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/AlexaConversationsBye/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/AlexaConversationsNotifyFailure/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/AlexaConversationsOutOfDomain/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/AlexaConversationsProvideHelp/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/AlexaConversationsRequestMore/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/AlexaConversationsThankYou/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/AlexaConversationsWelcome/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/AlexaConversationsYouAreWelcome/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/alexa_prize_preconditions_apla/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/confirm_color_for_fruit_apla/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/confirm_fruitName_apla/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/getEmployeePosition_success_apla/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/no_apla/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/nothing2_apla/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/nothing_apla/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/numericfeedback_apla/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/rating_apla/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/requestArgs_request_fruitName_apla/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/request_city_apla/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/request_city_date_apla/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/request_colorName_multiple_apla/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/request_date_apla/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/request_dob_getDate_apla/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/request_getEmploeeID_apla/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/request_name_apla/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/response0Prompt16/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/secondEarthAPI_apla/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/success_colorFruitAPI_apla/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/success_fruitPriceAPI_apla/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/weather_apla/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/weather_apla_de_apla/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/whoAmiSuccess/datasources/default.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/whoAmiSuccess/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/yes_apla/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/yesnofeedback_apla/document.json delete mode 100644 test/unit/fixture/dialog-evaluate/test-project-7/skill-package/skill.json diff --git a/test/unit/fixture/dialog-evaluate/test-project-1/.ask/ask-states.json b/test/unit/fixture/dialog-evaluate/test-project-1/.ask/ask-states.json deleted file mode 100644 index 18048d0e..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-1/.ask/ask-states.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "askcliStatesVersion": "2020-03-31", - "profiles": { - "TEST_PROFILE": { - "skillId": "TEST_SKILL_ID" - } - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-1/ask-resources.json b/test/unit/fixture/dialog-evaluate/test-project-1/ask-resources.json deleted file mode 100644 index 649c901b..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-1/ask-resources.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "askcliResourcesVersion": "2020-03-31", - "profiles": { - "TEST_PROFILE": { - "skillMetadata": { - "src": "./skill-package" - } - } - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/conversations/ALexaPrize.acdl b/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/conversations/ALexaPrize.acdl deleted file mode 100644 index 086efb02..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/conversations/ALexaPrize.acdl +++ /dev/null @@ -1,203 +0,0 @@ -namespace com.alexaprize - -import com.amazon.alexa.ask.conversations.Affirm -import com.amazon.alexa.ask.conversations.Deny -import com.amazon.alexa.ask.conversations.Invoke -import com.amazon.alexa.ask.conversations.Notify -import com.amazon.alexa.ask.conversations.Offer -import com.amazon.alexa.ask.conversations.expect -import com.amazon.alexa.ask.conversations.response -import com.amazon.alexa.ask.conversations.utterances -import com.amazon.alexa.schema.Boolean -import com.amazon.alexa.schema.Nothing -import com.amazon.alexa.schema.String -import com.amazon.ask.types.builtins.AMAZON.NUMBER -import prompts.alexa_prize_preconditions_apla -import slotTypes.TopicType - -type ConversationDetails { - optional TopicType Topic -} - -letsChatEvent = utterances( - samples = [ - "let's chat", - "i want to chat", - "chat", - "talk", - "let's chat about {Topic}", - "i want to talk about {Topic}", - "can we talk about {Topic}" - ] -) - -affirmEvent = utterances( - samples = [ - "yes", - "yup", - "yeah", - "sure", - "alright" - ] -) - -denyEvent = utterances( - samples = [ - "no", - "nope", - "not really", - "not", - "naah" - ] -) - -type AlexaPrizePreconditions { - NUMBER isLocaleSupported - NUMBER isDeviceSupported - NUMBER isFalseWake - NUMBER isSocialBotAvailable - NUMBER isAlexaPrizeEnabled - NUMBER isTopicBanned - String handoffPromptOverride -} - -type AlexaPrizePreconditionsPayload { - AlexaPrizePreconditions result -} - -type HandoffResults { - String handoffPromptOverride -} - -type HandoffResultsPayload { - HandoffResults result -} - -action AlexaPrizePreconditions checkPreconditionsAndHandoff(TopicType Topic = nothing) - -action HandoffResults intentConfirmedHandoff() - -action HandoffResults intentDeniedHandoff() - -dialog Nothing AlexaPrizeDialog() { - sample { - preconditionsResult = checkPrecondition() - isHandoffPossible = (((preconditionsResult.isDeviceSupported == 1 && preconditionsResult.isLocaleSupported == 1) && preconditionsResult.isSocialBotAvailable == 1) && preconditionsResult.isAlexaPrizeEnabled == 1) - if (isHandoffPossible) { - isConfirmationNeeded = (preconditionsResult.isFalseWake == 1 || preconditionsResult.isTopicBanned == 1) - responses( - isConfirmationNeeded = isConfirmationNeeded, - preconditionsResult = preconditionsResult - ) - } else { - response( - response = alexa_prize_preconditions_apla, - act = Notify { - actionName = checkPreconditionsAndHandoff, - success = false - }, - payload = AlexaPrizePreconditionsPayload { - result = preconditionsResult - } - ) - } - } -} - -dialog AlexaPrizePreconditions checkPrecondition() { - sample { - chatRequest = expect( - act = Invoke, - event = letsChatEvent - ) - checkPreconditionsAndHandoff( - Topic = chatRequest.Topic - ) - } - sample { - expect( - act = Invoke, - event = letsChatEvent - ) - preconditionsResult = checkPreconditionsAndHandoff() - } -} - -dialog Nothing responses(Boolean isConfirmationNeeded, AlexaPrizePreconditions preconditionsResult) { - sample { - if (isConfirmationNeeded) { - handoffResult( - preconditionsResult = preconditionsResult - ) - } else { - response( - response = alexa_prize_preconditions_apla, - act = Notify { - actionName = checkPreconditionsAndHandoff - }, - payload = AlexaPrizePreconditionsPayload { - result = preconditionsResult - } - ) - } - } -} - -dialog Nothing handoffResult(AlexaPrizePreconditions preconditionsResult) { - sample { - response( - response = alexa_prize_preconditions_apla, - act = Notify { - actionName = checkPreconditionsAndHandoff - }, - nextAct = Offer { - actionName = intentConfirmedHandoff - }, - payload = AlexaPrizePreconditionsPayload { - result = preconditionsResult - } - ) - expect( - act = Affirm, - event = affirmEvent - ) - handoffResults = intentConfirmedHandoff() - response( - response = alexa_prize_preconditions_apla, - act = Notify { - actionName = intentConfirmedHandoff - }, - payload = HandoffResultsPayload { - result = handoffResults - } - ) - } - sample { - response( - response = alexa_prize_preconditions_apla, - act = Notify { - actionName = checkPreconditionsAndHandoff - }, - nextAct = Offer { - actionName = intentDeniedHandoff - }, - payload = AlexaPrizePreconditionsPayload { - result = preconditionsResult - } - ) - expect( - act = Deny, - event = denyEvent - ) - handoffResults = intentDeniedHandoff() - response( - response = alexa_prize_preconditions_apla, - act = Notify { - actionName = intentDeniedHandoff - }, - payload = HandoffResultsPayload { - result = handoffResults - } - ) - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/conversations/Dialog_NonDeployable.acdl b/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/conversations/Dialog_NonDeployable.acdl deleted file mode 100644 index 275632d7..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/conversations/Dialog_NonDeployable.acdl +++ /dev/null @@ -1,81 +0,0 @@ -namespace dialogs_non_deployable - -import apis.getEmployeeDetails -import com.amazon.alexa.ask.conversations.Inform -import com.amazon.alexa.ask.conversations.Request -import com.amazon.alexa.ask.conversations.expect -import com.amazon.alexa.ask.conversations.response -import com.amazon.ask.types.builtins.AMAZON.DATE -import com.amazon.ask.types.builtins.AMAZON.NUMBER -import prompts.request_dob_getDate_apla -import prompts.request_getEmploeeID_apla -import prompts.request_name_apla -import slotTypes.complexNames -import types.complexResult -import utteracesets.informComplexNameEvent -import utteracesets.informDOBEvent -import utteracesets.informEmployeeIDEvent - -dialog complexNames getName() { - sample { - response( - response = request_name_apla, - act = Request { - arguments = [ - getEmployeeDetails.arguments.name1 - ] - } - ) - complexNamesReturn = expect( - act = Inform, - event = informComplexNameEvent - ) - complexNamesReturn.name - } -} - -dialog NUMBER getEmploeeID() { - sample { - response( - response = request_getEmploeeID_apla, - act = Request { - arguments = [ - getEmployeeDetails.arguments.emplyee1id - ] - } - ) - empID = expect( - act = Inform, - event = informEmployeeIDEvent - ) - empID.emplyee1id - } -} - -dialog DATE getDate() { - sample { - response( - response = request_dob_getDate_apla, - act = Request { - arguments = [ - getEmployeeDetails.arguments.a_dateOfBirth - ] - } - ) - dobEvent = expect( - act = Inform, - event = informDOBEvent - ) - dobEvent.a_dateOfBirth - } -} - -dialog complexResult a_getEmployeeDetails(complexNames name1, NUMBER emplyee1id, DATE a_dateOfBirth) { - sample { - complexResultEvent = getEmployeeDetails( - name1 = name1, - emplyee1id = emplyee1id, - a_dateOfBirth = a_dateOfBirth - ) - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/conversations/Dialogs_reusableDialogsUsage_NonDeployableDialogs.acdl b/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/conversations/Dialogs_reusableDialogsUsage_NonDeployableDialogs.acdl deleted file mode 100644 index b810c926..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/conversations/Dialogs_reusableDialogsUsage_NonDeployableDialogs.acdl +++ /dev/null @@ -1,45 +0,0 @@ -namespace reusableDialogs.NonDeployableDialogs - -import apis.getEmployeeDetails -import com.amazon.alexa.ask.conversations.Invoke -import com.amazon.alexa.ask.conversations.Notify -import com.amazon.alexa.ask.conversations.expect -import com.amazon.alexa.ask.conversations.response -import com.amazon.alexa.schema.Nothing -import dialogs_non_deployable.a_getEmployeeDetails -import dialogs_non_deployable.getDate -import dialogs_non_deployable.getEmploeeID -import dialogs_non_deployable.getName -import prompts.getEmployeePosition_success_apla -import types.complexResult -import utteracesets.who_are_you - -type PayLoadresult { - complexResult result -} - -dialog Nothing dilaog_getEmployeePosition() { - sample { - expect( - act = Invoke, - event = who_are_you - ) - complexNamesEvent = getName() - NUMBEREvent = getEmploeeID() - DATEEvent = getDate() - resultOne = a_getEmployeeDetails( - name1 = complexNamesEvent, - emplyee1id = NUMBEREvent, - a_dateOfBirth = DATEEvent - ) - response( - response = getEmployeePosition_success_apla, - act = Notify { - actionName = getEmployeeDetails - }, - payload = PayLoadresult { - result = resultOne - } - ) - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/conversations/Weather.acdl b/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/conversations/Weather.acdl deleted file mode 100644 index c4c30976..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/conversations/Weather.acdl +++ /dev/null @@ -1,137 +0,0 @@ -namespace com.weatherbot - -import com.amazon.alexa.ask.conversations.Invoke -import com.amazon.alexa.ask.conversations.Notify -import com.amazon.alexa.ask.conversations.RequestArguments -import com.amazon.alexa.ask.conversations.ensure -import com.amazon.alexa.ask.conversations.expect -import com.amazon.alexa.ask.conversations.response -import com.amazon.alexa.ask.conversations.utterances -import com.amazon.alexa.schema.Nothing -import com.amazon.alexa.schema.Thing -import com.amazon.ask.types.builtins.AMAZON.DATE -import com.amazon.ask.types.builtins.AMAZON.NUMBER -import com.amazon.ask.types.builtins.AMAZON.US_CITY -import prompts.request_city_apla -import prompts.request_date_apla -import prompts.weather_apla -import slotTypes.myCustomCities - -type CityAndDate { - optional myCustomCities cityNameChanged - optional US_CITY cityName - optional DATE date -} - -getWeatherEvent = utterances( - samples = [ - "What's the weather {date} in {cityNameChanged}", - "What's the weather {date} in {cityName}", - "what is the weather {date}", - "how is weather" - ] -) - -type WeatherResult { - optional myCustomCities cityNameChanged - optional US_CITY cityName - NUMBER highTemp - NUMBER lowTemp -} - -type ResponsePayload { - WeatherResult weatherResult -} - -action WeatherResult getWeather(DATE date, US_CITY cityName = nothing, myCustomCities cityNameChanged = nothing) - -dialog Nothing Weather() { - sample { - weatherRequest = expect( - act = Invoke, - event = getWeatherEvent - ) - ensure( - requestArgs = [ - RequestArguments { - arguments = [ - getWeather.arguments.cityNameChanged - ], - response = request_city_apla - }, - RequestArguments { - arguments = [ - getWeather.arguments.cityName - ], - response = request_city_apla - }, - RequestArguments { - arguments = [ - getWeather.arguments.date - ], - response = request_date_apla - } - ] - ) - weatherResult = getWeather( - date = weatherRequest.date, - cityName = weatherRequest.cityName - ) - response( - response = weather_apla, - act = Notify { - actionName = getWeather - }, - payload = ResponsePayload { - weatherResult = weatherResult - } - ) - } - sample { - weatherRequest = expect( - act = Invoke, - event = getWeatherEvent - ) - ensure( - requestArgs = [ - RequestArguments { - arguments = [ - getWeather.arguments.cityNameChanged - ], - response = request_city_apla - }, - RequestArguments { - arguments = [ - getWeather.arguments.cityName - ], - response = request_city_apla - }, - RequestArguments { - arguments = [ - getWeather.arguments.date - ], - response = request_date_apla - } - ] - ) - weatherResult = getWeather( - date = weatherRequest.date, - cityNameChanged = weatherRequest.cityNameChanged - ) - response( - response = weather_apla, - act = Notify { - actionName = getWeather - }, - payload = ResponsePayload { - weatherResult = weatherResult - } - ) - } -} - -dialog Nothing ComplexTest() { - sample { - Weather() - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/conversations/apis.acdl b/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/conversations/apis.acdl deleted file mode 100644 index 072d682e..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/conversations/apis.acdl +++ /dev/null @@ -1,15 +0,0 @@ -namespace apis - -import com.amazon.alexa.schema.Nothing -import com.amazon.ask.types.builtins.AMAZON.DATE -import com.amazon.ask.types.builtins.AMAZON.NUMBER -import slotTypes.complexNames -import slotTypes.signs -import types.complexResult -import types.result_one - -action Nothing secondEarthAPI() - -action result_one favColorSign_Name(complexNames name, signs sign = nothing) - -action complexResult getEmployeeDetails(complexNames name1, NUMBER emplyee1id, DATE a_dateOfBirth = nothing) diff --git a/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/conversations/apisNamepaceLambda.acdl b/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/conversations/apisNamepaceLambda.acdl deleted file mode 100644 index 553a40c5..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/conversations/apisNamepaceLambda.acdl +++ /dev/null @@ -1,22 +0,0 @@ -namespace com.weatherbot.apis - -import com.amazon.ask.types.builtins.AMAZON.Food -import com.amazon.ask.types.builtins.AMAZON.NUMBER -import slotTypes.myColors - -type result { - Food fruitName - NUMBER price -} - -type payloadgetFruitPriceEvent { - result result -} - -action result fruitNameAPI(Food fruitName) - -action resultthree colorFruitName(myColors colorName) - -type resultthree { - Food fruitName -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/conversations/conversation_empty.acdl b/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/conversations/conversation_empty.acdl deleted file mode 100644 index 4189bdda..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/conversations/conversation_empty.acdl +++ /dev/null @@ -1,114 +0,0 @@ -namespace com.numberbot - -import com.amazon.alexa.ask.conversations.APLA -import com.amazon.alexa.ask.conversations.Action -import com.amazon.alexa.ask.conversations.Bye -import com.amazon.alexa.ask.conversations.Invoke -import com.amazon.alexa.ask.conversations.Notify -import com.amazon.alexa.ask.conversations.Offer -import com.amazon.alexa.ask.conversations.RequestArguments -import com.amazon.alexa.ask.conversations.ensure -import com.amazon.alexa.ask.conversations.expect -import com.amazon.alexa.ask.conversations.response -import com.amazon.alexa.ask.conversations.utterances -import com.amazon.alexa.schema.Nothing -import com.amazon.alexa.schema.Number -import com.amazon.alexa.schema.Thing -import com.amazon.ask.types.builtins.AMAZON.NUMBER -import prompts.AlexaConversationsBye -import prompts.numericfeedback_apla -import prompts.rating_apla - -type NumPayload { - Number num -} - -type RatingRequest { - NUMBER rating -} - -InformRatingEvent = utterances( - samples = [ - "my score is {rating}", - "that was a {rating} conversation", - "i rate you a {rating}", - "{rating}" - ] -) - -getStart = utterances( - samples = [ - "give me a number please" - ] -) - -action Nothing saveRating(Number rating) - -action Number getNumber() - -dialog Nothing GetFeedback(APLA feedback_prompt, Number num, Action notifyAction) { - sample { - response( - response = feedback_prompt, - act = Notify { - actionName = notifyAction, - success = true - }, - nextAct = Offer { - actionName = saveRating, - arguments = [ - saveRating.arguments.rating - ] - }, - payload = NumPayload { - num = num - } - ) - myRating = expect( - act = Invoke, - event = InformRatingEvent - ) - ensure( - requestArgs = [ - RequestArguments { - arguments = [ - saveRating.arguments.rating - ], - response = rating_apla - } - ] - ) - saveRating( - rating = myRating.rating - ) - } -} - -dialog Number levelOne() { - sample { - expect( - act = Invoke, - event = getStart - ) - num = getNumber() - } -} - -dialog Nothing MainDialog() { - sample { - num = levelOne() - GetFeedback( - feedback_prompt = numericfeedback_apla, - num = num, - notifyAction = getNumber - ) - response( - response = AlexaConversationsBye, - act = Notify { - actionName = saveRating, - success = true - }, - nextAct = Bye {} - ) - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/conversations/fruitNameApi.acdl b/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/conversations/fruitNameApi.acdl deleted file mode 100644 index 4664f2f2..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/conversations/fruitNameApi.acdl +++ /dev/null @@ -1,34 +0,0 @@ -namespace test - -import com.amazon.alexa.ask.conversations.utterances -import com.amazon.ask.types.builtins.AMAZON.Food - -type fruitNameShell { - Food fruitName -} - -type paylaodCompleFruit { - Food fruitName -} - -getFruitPriceEvent = utterances( - samples = [ - "what is the price of the fruit", - "what is the price of fruit" - ] -) - -informfruitNameEvent = utterances( - samples = [ - "{fruitName}", - "fruit name is {fruitName}", - "fruit is {fruitName}" - ] -) - -affirmFruitAPIEvent = utterances( - samples = [ - "uh huh", - "yup" - ] -) diff --git a/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/conversations/soaDialog.acdl b/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/conversations/soaDialog.acdl deleted file mode 100644 index 30a83432..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/conversations/soaDialog.acdl +++ /dev/null @@ -1,123 +0,0 @@ -namespace soaACDl - -import com.amazon.alexa.ask.conversations.Inform -import com.amazon.alexa.ask.conversations.Invoke -import com.amazon.alexa.ask.conversations.Notify -import com.amazon.alexa.ask.conversations.Request -import com.amazon.alexa.ask.conversations.expect -import com.amazon.alexa.ask.conversations.received -import com.amazon.alexa.ask.conversations.response -import com.amazon.alexa.ask.conversations.utterances -import com.amazon.alexa.schema.Nothing -import com.weatherbot.apis.colorFruitName -import com.weatherbot.apis.resultthree -import prompts.request_colorName_multiple_apla -import prompts.success_colorFruitAPI_apla -import slotTypes.myColors - -type payloadMultipleDialogEvent { - resultthree result -} - -MultipleDialogEvent = utterances( - samples = [ - "i want to buy a fruit" - ] -) - -informColorMultipleEvent = utterances( - samples = [ - "{colorName}", - "color is {colorName}", - "color {colorName}" - ] -) - -affirmMultipleColorEvent = utterances( - samples = [ - "do it" - ] -) - -type colorNameShell { - myColors colorName -} - -type payloadsOAConfirmArgs { - myColors colorName -} - -type colorEvent0 { - myColors colorName -} - -interaction { - actual { - result1 = received( - act = Inform, - utterance = "{armadillo|colorName}" - ) - resultEvent11 = colorFruitName( - colorName = result1.colorName - ) - response( - response = success_colorFruitAPI_apla, - act = Notify { - actionName = colorFruitName - }, - payload = payloadMultipleDialogEvent { - result = resultEvent11 - } - ) - } expected { - result1 = received( - act = Inform, - utterance = "{armadillo|colorName}" - ) - resultEvent11 = colorFruitName( - colorName = result1.colorName - ) - response( - response = success_colorFruitAPI_apla, - act = Notify { - actionName = colorFruitName - }, - payload = payloadMultipleDialogEvent { - result = resultEvent11 - } - ) - } -} - -dialog Nothing sOA() { - sample { - expect( - act = Invoke, - event = MultipleDialogEvent - ) - response( - response = request_colorName_multiple_apla, - act = Request { - arguments = [ - colorFruitName.arguments.colorName - ] - } - ) - colorEvent = expect( - act = Inform, - event = informColorMultipleEvent - ) - resultEvent = colorFruitName( - colorName = colorEvent.colorName - ) - response( - response = success_colorFruitAPI_apla, - act = Notify { - actionName = colorFruitName - }, - payload = payloadMultipleDialogEvent { - result = resultEvent - } - ) - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/conversations/types.acdl b/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/conversations/types.acdl deleted file mode 100644 index 3cc656d2..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/conversations/types.acdl +++ /dev/null @@ -1,43 +0,0 @@ -namespace types - -import com.amazon.ask.types.builtins.AMAZON.Color -import com.amazon.ask.types.builtins.AMAZON.DATE -import com.amazon.ask.types.builtins.AMAZON.Food -import com.amazon.ask.types.builtins.AMAZON.NUMBER -import slotTypes.complexNames -import slotTypes.myColors -import slotTypes.position -import slotTypes.signs - -type result_one { - Color colorName - complexNames name - signs sign -} - -type complexResult { - complexNames name1 - DATE a_dateOfBirth - NUMBER emplyee1id - position position -} - -type nameShell { - complexNames name -} - -type dobshell { - DATE a_dateOfBirth -} - -type employeeIDshell { - NUMBER emplyee1id -} - -type fruitNameShell { - Food fruitName -} - -type colorEvent0 { - myColors colorName -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/conversations/utteracesets.acdl b/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/conversations/utteracesets.acdl deleted file mode 100644 index 5f8fe09b..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/conversations/utteracesets.acdl +++ /dev/null @@ -1,82 +0,0 @@ -namespace utteracesets - -import com.amazon.alexa.ask.conversations.utterances -import types.dobshell -import types.employeeIDshell -import types.fruitNameShell -import types.nameShell - -getFruitPriceEvent = utterances( - samples = [ - "what is the price of the fruit", - "what is the price of fruit" - ] -) - -affirmFruitAPIEvent = utterances( - samples = [ - "yeah" - ] -) - -informfruitNameEvent = utterances( - samples = [ - "{fruitName}", - "fruit name is {fruitName}", - "fruit is {fruitName}" - ] -) - -delegateToSkill = utterances( - samples = [ - "get me to paradise", - "take me to paradise" - ] -) - -getFavColorEvent = utterances( - samples = [ - "what is my favourite color", - "tell my favourite color" - ] -) - -affirmFavColorEvent = utterances( - samples = [ - "correct" - ] -) - -who_are_you = utterances( - samples = [ - "who are you", - "who is that", - "find his designation" - ] -) - -informComplexNameEvent = utterances( - samples = [ - "{name}", - "name is {name}", - "i am {name}" - ] -) - -informDOBEvent = utterances( - samples = [ - "date of birth is {a_dateOfBirth}", - "birth date is {a_dateOfBirth}" - ] -) - -informEmployeeIDEvent = utterances( - samples = [ - "employee i.d. is {emplyee1id}", - "employee identification is {emplyee1id}", - "identification is {emplyee1id}", - "employee id is {emplyee1id}", - "i.d. is {emplyee1id}", - "id is {emplyee1id}" - ] -) diff --git a/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/interactionModels/custom/en-US.json b/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/interactionModels/custom/en-US.json deleted file mode 100644 index 7df58746..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/interactionModels/custom/en-US.json +++ /dev/null @@ -1,919 +0,0 @@ -{ - "interactionModel": { - "languageModel": { - "invocationName": "serious working test skill", - "intents": [ - { - "name": "AMAZON.CancelIntent", - "samples": [] - }, - { - "name": "AMAZON.HelpIntent", - "samples": [] - }, - { - "name": "AMAZON.StopIntent", - "samples": [] - }, - { - "name": "GetWeatherIntent", - "samples": ["what is the weather", "how is the weather", "tell me the weather"] - }, - { - "name": "AMAZON.NavigateHomeIntent", - "samples": [] - }, - { - "name": "AMAZON.FallbackIntent", - "samples": [] - } - ], - "types": [ - { - "values": [ - { - "id": "movies", - "name": { - "value": "movies", - "synonyms": [] - } - }, - { - "id": "politics", - "name": { - "value": "politics", - "synonyms": [] - } - }, - { - "id": "sports", - "name": { - "value": "sports", - "synonyms": [] - } - }, - { - "id": "hobbies", - "name": { - "value": "hobbies", - "synonyms": [] - } - }, - { - "id": "astronomy", - "name": { - "value": "astronomy", - "synonyms": [] - } - }, - { - "id": "physics", - "name": { - "value": "physics", - "synonyms": [] - } - }, - { - "id": "los_angeles_dodgers", - "name": { - "value": "los angeles dodgers" - } - }, - { - "id": "president_emmanuel_macron", - "name": { - "value": "president emmanuel macron" - } - }, - { - "id": "emmanuel_macron", - "name": { - "value": "emmanuel macron" - } - }, - { - "id": "tax_cuts", - "name": { - "value": "tax cuts" - } - }, - { - "id": "middle_class", - "name": { - "value": "middle class" - } - }, - { - "id": "inequality_divide", - "name": { - "value": "inequality divide" - } - }, - { - "id": "wealth_inequality", - "name": { - "value": "wealth inequality" - } - }, - { - "id": "n._p._r.", - "name": { - "value": "n. p. r." - } - }, - { - "id": "president_trump", - "name": { - "value": "president trump" - } - }, - { - "id": "fox", - "name": { - "value": "fox" - } - }, - { - "id": "police_officers", - "name": { - "value": "police officers" - } - }, - { - "id": "jerome_hall", - "name": { - "value": "jerome hall" - } - }, - { - "id": "diversity_training_program", - "name": { - "value": "diversity training program" - } - }, - { - "id": "read_preble", - "name": { - "value": "read preble" - } - }, - { - "id": "christopher_preble", - "name": { - "value": "christopher preble" - } - }, - { - "id": "pacific_rim", - "name": { - "value": "pacific rim" - } - }, - { - "id": "washington_nationals", - "name": { - "value": "washington nationals" - } - }, - { - "id": "michael_cohen", - "name": { - "value": "michael cohen" - } - }, - { - "id": "john_wall", - "name": { - "value": "john wall" - } - }, - { - "id": "united_states", - "name": { - "value": "united states" - } - }, - { - "id": "washington_wizards", - "name": { - "value": "washington wizards" - } - }, - { - "id": "bryce_harper", - "name": { - "value": "bryce harper" - } - }, - { - "id": "capitals_playoff_hockey_capitals", - "name": { - "value": "capitals playoff hockey capitals" - } - }, - { - "id": "james_b._comey", - "name": { - "value": "james b. comey" - } - }, - { - "id": "mike_pompeo", - "name": { - "value": "mike pompeo" - } - }, - { - "id": "tom_toles", - "name": { - "value": "tom toles" - } - }, - { - "id": "white_house", - "name": { - "value": "white house" - } - }, - { - "id": "manny_machado", - "name": { - "value": "manny machado" - } - }, - { - "id": "national_league_east", - "name": { - "value": "national league east" - } - }, - { - "id": "otto_porter_jr._now", - "name": { - "value": "otto porter jr. now" - } - }, - { - "id": "hillary_clinton", - "name": { - "value": "hillary clinton" - } - }, - { - "id": "trea_turner", - "name": { - "value": "trea turner" - } - }, - { - "id": "max_scherzer", - "name": { - "value": "max scherzer" - } - }, - { - "id": "donald_trump", - "name": { - "value": "donald trump" - } - }, - { - "id": "bryce_harper_nationals", - "name": { - "value": "bryce harper nationals" - } - }, - { - "id": "michael_a._taylor", - "name": { - "value": "michael a. taylor" - } - }, - { - "id": "news_media", - "name": { - "value": "news media" - } - }, - { - "id": "conservative_political_action_conference", - "name": { - "value": "conservative political action conference" - } - }, - { - "id": "mainstream_media", - "name": { - "value": "mainstream media" - } - }, - { - "id": "baltimore_orioles", - "name": { - "value": "baltimore orioles" - } - }, - { - "id": "sean_hannity", - "name": { - "value": "sean hannity" - } - }, - { - "id": "privilege", - "name": { - "value": "privilege" - } - }, - { - "id": "sarah_hart", - "name": { - "value": "sarah hart" - } - }, - { - "id": "matt_kemp", - "name": { - "value": "matt kemp" - } - }, - { - "id": "stephen_strasburg", - "name": { - "value": "stephen strasburg" - } - }, - { - "id": "police_misconduct", - "name": { - "value": "police misconduct" - } - }, - { - "id": "sarah_huckabee_sanders", - "name": { - "value": "sarah huckabee sanders" - } - }, - { - "id": "washington_wizards_april", - "name": { - "value": "washington wizards april" - } - }, - { - "id": "environmental_protection_agency_administrator_scott_pruitt", - "name": { - "value": "environmental protection agency administrator scott pruitt" - } - }, - { - "id": "dodger_stadium", - "name": { - "value": "dodger stadium" - } - }, - { - "id": "environmental_protection_agency", - "name": { - "value": "environmental protection agency" - } - }, - { - "id": "barbara_bush", - "name": { - "value": "barbara bush" - } - }, - { - "id": "lewis_\"scooter\"_libby", - "name": { - "value": "lewis \"scooter\" libby" - } - }, - { - "id": "lewis_scooter_libby", - "name": { - "value": "lewis scooter libby" - } - }, - { - "id": "game_3._lowry", - "name": { - "value": "game 3. lowry" - } - }, - { - "id": "columbus_blue_jackets", - "name": { - "value": "columbus blue jackets" - } - }, - { - "id": "john_tortorella", - "name": { - "value": "john tortorella" - } - }, - { - "id": "george_w._bush", - "name": { - "value": "george w. bush" - } - }, - { - "id": "george_h.w._bush", - "name": { - "value": "george h.w. bush" - } - }, - { - "id": "jarrett_hurd", - "name": { - "value": "jarrett hurd" - } - }, - { - "id": "said_fred_hurd_sr.", - "name": { - "value": "said fred hurd sr." - } - }, - { - "id": "fred_hurd_sr.", - "name": { - "value": "fred hurd sr." - } - }, - { - "id": "san_antonio", - "name": { - "value": "san antonio" - } - }, - { - "id": "san_antonio_spurs", - "name": { - "value": "san antonio spurs" - } - }, - { - "id": "gregg_popovich", - "name": { - "value": "gregg popovich" - } - }, - { - "id": "kawhi_leonard", - "name": { - "value": "kawhi leonard" - } - }, - { - "id": "tim_bontemps_seth_jones", - "name": { - "value": "tim bontemps seth jones" - } - }, - { - "id": "consumer_sentiment_index", - "name": { - "value": "consumer sentiment index" - } - }, - { - "id": "pew_research_center", - "name": { - "value": "pew research center" - } - }, - { - "id": "conference_board_consumer_confidence_survey", - "name": { - "value": "conference board consumer confidence survey" - } - }, - { - "id": "speech_rights", - "name": { - "value": "speech rights" - } - }, - { - "id": "first_amendment", - "name": { - "value": "first amendment" - } - }, - { - "id": "golden_state", - "name": { - "value": "golden state" - } - }, - { - "id": "north_korea", - "name": { - "value": "north korea" - } - }, - { - "id": "woman_pilot", - "name": { - "value": "woman pilot" - } - }, - { - "id": "airline_pilot_population", - "name": { - "value": "airline pilot population" - } - }, - { - "id": "air_transport_pilot", - "name": { - "value": "air transport pilot" - } - }, - { - "id": "southwest_airlines", - "name": { - "value": "southwest airlines" - } - }, - { - "id": "democratic_national_committee", - "name": { - "value": "democratic national committee" - } - }, - { - "id": "senate_foreign_relations_committee", - "name": { - "value": "senate foreign relations committee" - } - }, - { - "id": "cia_director_mike_pompeo", - "name": { - "value": "cia director mike pompeo" - } - }, - { - "id": "playoff_overtime_games", - "name": { - "value": "playoff overtime games" - } - }, - { - "id": "lord_jesus", - "name": { - "value": "lord jesus" - } - }, - { - "id": "lgbtq_community", - "name": { - "value": "lgbtq community" - } - }, - { - "id": "health_and_human_services_department", - "name": { - "value": "health and human services department" - } - }, - { - "id": "group_prayer", - "name": { - "value": "group prayer" - } - }, - { - "id": "princess_charlotte_elizabeth_diana", - "name": { - "value": "princess charlotte elizabeth diana" - } - }, - { - "id": "term_war_economy", - "name": { - "value": "term war economy" - } - }, - { - "id": "melissa_kirk", - "name": { - "value": "melissa kirk" - } - }, - { - "id": "captain_america", - "name": { - "value": "captain america" - } - }, - { - "id": "draft_position", - "name": { - "value": "draft position" - } - }, - { - "id": "elysee_mbem-bosse", - "name": { - "value": "elysee mbem-bosse" - } - }, - { - "id": "water_crisis", - "name": { - "value": "water crisis" - } - }, - { - "id": "nationals_pitchers", - "name": { - "value": "nationals pitchers" - } - }, - { - "id": "sen._jennifer_t._wexton", - "name": { - "value": "sen. jennifer t. wexton" - } - }, - { - "id": "interest_rates", - "name": { - "value": "interest rates" - } - }, - { - "id": "town_crier", - "name": { - "value": "town crier" - } - }, - { - "id": "nancy_goes_millennial", - "name": { - "value": "nancy goes millennial" - } - }, - { - "id": "steve_rogers", - "name": { - "value": "steve rogers" - } - }, - { - "id": "game_3._lebron_james", - "name": { - "value": "game 3. lebron james" - } - }, - { - "id": "anthony_rendon", - "name": { - "value": "anthony rendon" - } - }, - { - "id": "buckingham_palace", - "name": { - "value": "buckingham palace" - } - }, - { - "id": "travis_reinking_suspected", - "name": { - "value": "travis reinking suspected" - } - }, - { - "id": "detroit_free_press", - "name": { - "value": "detroit free press" - } - }, - { - "id": "national_rifle_association", - "name": { - "value": "national rifle association" - } - }, - { - "id": "ed_harris", - "name": { - "value": "ed harris" - } - }, - { - "id": "overtime_playoff_games", - "name": { - "value": "overtime playoff games" - } - }, - { - "id": "republican_sen._bob_corker", - "name": { - "value": "republican sen. bob corker" - } - }, - { - "id": "electricity_sector_reforms", - "name": { - "value": "electricity sector reforms" - } - }, - { - "id": "baltimore_manager_buck_showalter", - "name": { - "value": "baltimore manager buck showalter" - } - }, - { - "id": "sen._joe_manchin_iii", - "name": { - "value": "sen. joe manchin iii" - } - }, - { - "id": "car_seat_belts", - "name": { - "value": "car seat belts" - } - }, - { - "id": "andrews_mcmeel.", - "name": { - "value": "andrews mcmeel." - } - }, - { - "id": "north_africa_program", - "name": { - "value": "north africa program" - } - }, - { - "id": "state_prosecutor_lobby", - "name": { - "value": "state prosecutor lobby" - } - }, - { - "id": "cape_town", - "name": { - "value": "cape town" - } - }, - { - "id": "data_privacy_law", - "name": { - "value": "data privacy law" - } - }, - { - "id": "president_trump_down", - "name": { - "value": "president trump down" - } - }, - { - "id": "christian_kirk", - "name": { - "value": "christian kirk" - } - }, - { - "id": "mitch_mcconnell", - "name": { - "value": "mitch mcconnell" - } - }, - { - "id": "federal_reserve", - "name": { - "value": "federal reserve" - } - } - ], - "name": "TopicType" - }, - { - "values": [ - { - "name": { - "value": "cancer" - } - }, - { - "name": { - "value": "scorpio" - } - }, - { - "name": { - "value": "scorpion" - } - } - ], - "name": "signs" - }, - { - "values": [ - { - "name": { - "value": "satheesh" - } - }, - { - "name": { - "value": "raman" - } - }, - { - "name": { - "value": "yadhu" - } - } - ], - "name": "complexNames" - }, - { - "values": [ - { - "name": { - "value": "tester" - } - }, - { - "name": { - "value": "engineer" - } - }, - { - "name": { - "value": "manager" - } - } - ], - "name": "position" - }, - { - "values": [ - { - "name": { - "value": "blue" - } - }, - { - "name": { - "value": "red" - } - }, - { - "name": { - "value": "rocket" - } - } - ], - "name": "myColors" - }, - { - "values": [ - { - "name": { - "value": "flower city" - } - }, - { - "name": { - "value": "temple city" - } - }, - { - "name": { - "value": "ramapuram" - } - }, - { - "name": { - "value": "guindy" - } - }, - { - "name": { - "value": "porur" - } - } - ], - "name": "myCustomCities" - } - ] - } - }, - "version": "34" -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/display/confirm_city_apl_display/document.json b/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/display/confirm_city_apl_display/document.json deleted file mode 100644 index 6fea1ff7..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/display/confirm_city_apl_display/document.json +++ /dev/null @@ -1,331 +0,0 @@ -{ - "type": "APL", - "version": "1.1", - "settings": {}, - "theme": "dark", - "import": [ - { - "name": "alexa-layouts", - "version": "1.0.0" - } - ], - "resources": [ - { - "description": "Stock color for the light theme", - "colors": { - "colorTextPrimary": "#151920" - } - }, - { - "description": "Stock color for the dark theme", - "when": "${viewport.theme == 'dark'}", - "colors": { - "colorTextPrimary": "#f0f1ef" - } - }, - { - "description": "Standard font sizes", - "dimensions": { - "textSizeBody": 48, - "textSizePrimary": 27, - "textSizeSecondary": 23, - "textSizeDetails": 20, - "textSizeSecondaryHint": 25 - } - }, - { - "description": "Common spacing values", - "dimensions": { - "spacingThin": 6, - "spacingSmall": 12, - "spacingMedium": 24, - "spacingLarge": 48, - "spacingExtraLarge": 72 - } - }, - { - "description": "Common margins and padding", - "dimensions": { - "marginTop": 40, - "marginLeft": 60, - "marginRight": 60, - "marginBottom": 40 - } - } - ], - "styles": { - "textStyleBase": { - "description": "Base font description; set color", - "values": [ - { - "color": "@colorTextPrimary" - } - ] - }, - "textStyleBase0": { - "description": "Thin version of basic font", - "extend": "textStyleBase", - "values": { - "fontWeight": "100" - } - }, - "textStyleBase1": { - "description": "Light version of basic font", - "extend": "textStyleBase", - "values": { - "fontWeight": "300" - } - }, - "textStyleBase2": { - "description": "Regular version of basic font", - "extend": "textStyleBase", - "values": { - "fontWeight": "500" - } - }, - "mixinBody": { - "values": { - "fontSize": "@textSizeBody" - } - }, - "mixinPrimary": { - "values": { - "fontSize": "@textSizePrimary" - } - }, - "mixinDetails": { - "values": { - "fontSize": "@textSizeDetails" - } - }, - "mixinSecondary": { - "values": { - "fontSize": "@textSizeSecondary" - } - }, - "textStylePrimary": { - "extend": ["textStyleBase1", "mixinPrimary"] - }, - "textStyleSecondary": { - "extend": ["textStyleBase0", "mixinSecondary"] - }, - "textStyleBody": { - "extend": ["textStyleBase1", "mixinBody"] - }, - "textStyleSecondaryHint": { - "values": { - "fontFamily": "Bookerly", - "fontStyle": "italic", - "fontSize": "@textSizeSecondaryHint", - "color": "@colorTextPrimary" - } - }, - "textStyleDetails": { - "extend": ["textStyleBase2", "mixinDetails"] - } - }, - "onMount": [], - "graphics": {}, - "commands": {}, - "layouts": { - "ListTemplate1": { - "parameters": ["backgroundImage", "title", "logo", "hintText", "listData"], - "item": [ - { - "type": "Container", - "width": "100vw", - "height": "100vh", - "direction": "column", - "items": [ - { - "type": "Image", - "source": "${backgroundImage}", - "scale": "best-fill", - "width": "100vw", - "height": "100vh", - "position": "absolute" - }, - { - "type": "AlexaHeader", - "headerTitle": "${title}", - "headerAttributionImage": "${logo}" - }, - { - "type": "Sequence", - "grow": 1, - "height": "80vh", - "scrollDirection": "vertical", - "paddingLeft": "@marginLeft", - "paddingRight": "@marginRight", - "data": "${listData}", - "numbered": true, - "items": [ - { - "type": "VerticalListItem", - "image": "${data.image.sources[0].url}", - "primaryText": "${data.textContent.primaryText.text}", - "secondaryText": "${data.textContent.secondaryText.text}", - "tertiaryText": "${data.textContent.tertiaryText.text}" - } - ] - } - ] - } - ] - }, - "VerticalListItem": { - "parameters": ["primaryText", "secondaryText", "tertiaryText", "image"], - "item": [ - { - "when": "${viewport.shape == 'round'}", - "type": "Container", - "direction": "row", - "height": 200, - "width": 500, - "alignItems": "center", - "items": [ - { - "type": "Text", - "text": "${ordinal}", - "paddingBottom": "20dp", - "color": "white", - "spacing": "5dp" - }, - { - "type": "Image", - "when": "${image}", - "source": "${image}", - "height": 150, - "width": 150, - "spacing": 15, - "scale": "best-fit", - "align": "top" - }, - { - "type": "Container", - "direction": "column", - "spacing": 25, - "items": [ - { - "type": "Text", - "text": "${primaryText}", - "style": "textStyleDetail", - "grow": 1, - "shrink": 1, - "fontWeight": "300", - "maxLines": 1 - }, - { - "type": "Text", - "text": "${secondaryText}", - "style": "textStyleCaption", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - }, - { - "type": "Text", - "text": "${tertiaryText}", - "style": "textStyleDetails", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - } - ] - } - ] - }, - { - "type": "Container", - "direction": "row", - "height": 125, - "width": 800, - "alignItems": "center", - "items": [ - { - "type": "Text", - "text": "${ordinal}", - "paddingBottom": "20dp", - "color": "white", - "spacing": "5dp" - }, - { - "type": "Image", - "when": "${image}", - "source": "${image}", - "height": 100, - "width": 100, - "align": "top", - "spacing": 50, - "scale": "best-fit" - }, - { - "type": "Container", - "spacing": 30, - "direction": "column", - "items": [ - { - "type": "Text", - "text": "${primaryText}", - "style": "textStyleBody", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - }, - { - "type": "Text", - "text": "${secondaryText}", - "style": "textStyleDetails", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - } - ] - }, - { - "type": "Text", - "text": "${tertiaryText}", - "style": "textStyleBody", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "textAlign": "right", - "maxLines": 1 - } - ] - } - ] - } - }, - "mainTemplate": { - "parameters": ["payload"], - "item": [ - { - "type": "Container", - "id": "BookCabSimpleDialogAPL", - "items": [ - { - "type": "TouchWrapper", - "onPress": { - "type": "SendEvent", - "arguments": ["delegateToColtraneOld"] - }, - "item": { - "type": "Text", - "id": "BookCabSimpleDialogAPL", - "paddingTop": "100", - "paddingLeft": "100", - "color": "green", - "size": 50, - "text": "which city ?" - } - } - ] - } - ] - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/display/confirm_date_apl_display/document.json b/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/display/confirm_date_apl_display/document.json deleted file mode 100644 index d41ea236..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/display/confirm_date_apl_display/document.json +++ /dev/null @@ -1,331 +0,0 @@ -{ - "type": "APL", - "version": "1.1", - "settings": {}, - "theme": "dark", - "import": [ - { - "name": "alexa-layouts", - "version": "1.0.0" - } - ], - "resources": [ - { - "description": "Stock color for the light theme", - "colors": { - "colorTextPrimary": "#151920" - } - }, - { - "description": "Stock color for the dark theme", - "when": "${viewport.theme == 'dark'}", - "colors": { - "colorTextPrimary": "#f0f1ef" - } - }, - { - "description": "Standard font sizes", - "dimensions": { - "textSizeBody": 48, - "textSizePrimary": 27, - "textSizeSecondary": 23, - "textSizeDetails": 20, - "textSizeSecondaryHint": 25 - } - }, - { - "description": "Common spacing values", - "dimensions": { - "spacingThin": 6, - "spacingSmall": 12, - "spacingMedium": 24, - "spacingLarge": 48, - "spacingExtraLarge": 72 - } - }, - { - "description": "Common margins and padding", - "dimensions": { - "marginTop": 40, - "marginLeft": 60, - "marginRight": 60, - "marginBottom": 40 - } - } - ], - "styles": { - "textStyleBase": { - "description": "Base font description; set color", - "values": [ - { - "color": "@colorTextPrimary" - } - ] - }, - "textStyleBase0": { - "description": "Thin version of basic font", - "extend": "textStyleBase", - "values": { - "fontWeight": "100" - } - }, - "textStyleBase1": { - "description": "Light version of basic font", - "extend": "textStyleBase", - "values": { - "fontWeight": "300" - } - }, - "textStyleBase2": { - "description": "Regular version of basic font", - "extend": "textStyleBase", - "values": { - "fontWeight": "500" - } - }, - "mixinBody": { - "values": { - "fontSize": "@textSizeBody" - } - }, - "mixinPrimary": { - "values": { - "fontSize": "@textSizePrimary" - } - }, - "mixinDetails": { - "values": { - "fontSize": "@textSizeDetails" - } - }, - "mixinSecondary": { - "values": { - "fontSize": "@textSizeSecondary" - } - }, - "textStylePrimary": { - "extend": ["textStyleBase1", "mixinPrimary"] - }, - "textStyleSecondary": { - "extend": ["textStyleBase0", "mixinSecondary"] - }, - "textStyleBody": { - "extend": ["textStyleBase1", "mixinBody"] - }, - "textStyleSecondaryHint": { - "values": { - "fontFamily": "Bookerly", - "fontStyle": "italic", - "fontSize": "@textSizeSecondaryHint", - "color": "@colorTextPrimary" - } - }, - "textStyleDetails": { - "extend": ["textStyleBase2", "mixinDetails"] - } - }, - "onMount": [], - "graphics": {}, - "commands": {}, - "layouts": { - "ListTemplate1": { - "parameters": ["backgroundImage", "title", "logo", "hintText", "listData"], - "item": [ - { - "type": "Container", - "width": "100vw", - "height": "100vh", - "direction": "column", - "items": [ - { - "type": "Image", - "source": "${backgroundImage}", - "scale": "best-fill", - "width": "100vw", - "height": "100vh", - "position": "absolute" - }, - { - "type": "AlexaHeader", - "headerTitle": "${title}", - "headerAttributionImage": "${logo}" - }, - { - "type": "Sequence", - "grow": 1, - "height": "80vh", - "scrollDirection": "vertical", - "paddingLeft": "@marginLeft", - "paddingRight": "@marginRight", - "data": "${listData}", - "numbered": true, - "items": [ - { - "type": "VerticalListItem", - "image": "${data.image.sources[0].url}", - "primaryText": "${data.textContent.primaryText.text}", - "secondaryText": "${data.textContent.secondaryText.text}", - "tertiaryText": "${data.textContent.tertiaryText.text}" - } - ] - } - ] - } - ] - }, - "VerticalListItem": { - "parameters": ["primaryText", "secondaryText", "tertiaryText", "image"], - "item": [ - { - "when": "${viewport.shape == 'round'}", - "type": "Container", - "direction": "row", - "height": 200, - "width": 500, - "alignItems": "center", - "items": [ - { - "type": "Text", - "text": "${ordinal}", - "paddingBottom": "20dp", - "color": "white", - "spacing": "5dp" - }, - { - "type": "Image", - "when": "${image}", - "source": "${image}", - "height": 150, - "width": 150, - "spacing": 15, - "scale": "best-fit", - "align": "top" - }, - { - "type": "Container", - "direction": "column", - "spacing": 25, - "items": [ - { - "type": "Text", - "text": "${primaryText}", - "style": "textStyleDetail", - "grow": 1, - "shrink": 1, - "fontWeight": "300", - "maxLines": 1 - }, - { - "type": "Text", - "text": "${secondaryText}", - "style": "textStyleCaption", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - }, - { - "type": "Text", - "text": "${tertiaryText}", - "style": "textStyleDetails", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - } - ] - } - ] - }, - { - "type": "Container", - "direction": "row", - "height": 125, - "width": 800, - "alignItems": "center", - "items": [ - { - "type": "Text", - "text": "${ordinal}", - "paddingBottom": "20dp", - "color": "white", - "spacing": "5dp" - }, - { - "type": "Image", - "when": "${image}", - "source": "${image}", - "height": 100, - "width": 100, - "align": "top", - "spacing": 50, - "scale": "best-fit" - }, - { - "type": "Container", - "spacing": 30, - "direction": "column", - "items": [ - { - "type": "Text", - "text": "${primaryText}", - "style": "textStyleBody", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - }, - { - "type": "Text", - "text": "${secondaryText}", - "style": "textStyleDetails", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - } - ] - }, - { - "type": "Text", - "text": "${tertiaryText}", - "style": "textStyleBody", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "textAlign": "right", - "maxLines": 1 - } - ] - } - ] - } - }, - "mainTemplate": { - "parameters": ["payload"], - "item": [ - { - "type": "Container", - "id": "BookCabSimpleDialogAPL", - "items": [ - { - "type": "TouchWrapper", - "onPress": { - "type": "SendEvent", - "arguments": ["delegateToColtraneOld"] - }, - "item": { - "type": "Text", - "id": "BookCabSimpleDialogAPL", - "paddingTop": "100", - "paddingLeft": "100", - "color": "green", - "size": 50, - "text": "which date ?" - } - } - ] - } - ] - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/display/confirm_weather_apla_display/document.json b/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/display/confirm_weather_apla_display/document.json deleted file mode 100644 index 3bcc0e4a..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/display/confirm_weather_apla_display/document.json +++ /dev/null @@ -1,379 +0,0 @@ -{ - "type": "APL", - "version": "1.1", - "settings": {}, - "theme": "dark", - "import": [ - { - "name": "alexa-layouts", - "version": "1.0.0" - } - ], - "resources": [ - { - "description": "Stock color for the light theme", - "colors": { - "colorTextPrimary": "#151920" - } - }, - { - "description": "Stock color for the dark theme", - "when": "${viewport.theme == 'dark'}", - "colors": { - "colorTextPrimary": "#f0f1ef" - } - }, - { - "description": "Standard font sizes", - "dimensions": { - "textSizeBody": 48, - "textSizePrimary": 27, - "textSizeSecondary": 23, - "textSizeDetails": 20, - "textSizeSecondaryHint": 25 - } - }, - { - "description": "Common spacing values", - "dimensions": { - "spacingThin": 6, - "spacingSmall": 12, - "spacingMedium": 24, - "spacingLarge": 48, - "spacingExtraLarge": 72 - } - }, - { - "description": "Common margins and padding", - "dimensions": { - "marginTop": 40, - "marginLeft": 60, - "marginRight": 60, - "marginBottom": 40 - } - } - ], - "styles": { - "textStyleBase": { - "description": "Base font description; set color", - "values": [ - { - "color": "@colorTextPrimary" - } - ] - }, - "textStyleBase0": { - "description": "Thin version of basic font", - "extend": "textStyleBase", - "values": { - "fontWeight": "100" - } - }, - "textStyleBase1": { - "description": "Light version of basic font", - "extend": "textStyleBase", - "values": { - "fontWeight": "300" - } - }, - "textStyleBase2": { - "description": "Regular version of basic font", - "extend": "textStyleBase", - "values": { - "fontWeight": "500" - } - }, - "mixinBody": { - "values": { - "fontSize": "@textSizeBody" - } - }, - "mixinPrimary": { - "values": { - "fontSize": "@textSizePrimary" - } - }, - "mixinDetails": { - "values": { - "fontSize": "@textSizeDetails" - } - }, - "mixinSecondary": { - "values": { - "fontSize": "@textSizeSecondary" - } - }, - "textStylePrimary": { - "extend": ["textStyleBase1", "mixinPrimary"] - }, - "textStyleSecondary": { - "extend": ["textStyleBase0", "mixinSecondary"] - }, - "textStyleBody": { - "extend": ["textStyleBase1", "mixinBody"] - }, - "textStyleSecondaryHint": { - "values": { - "fontFamily": "Bookerly", - "fontStyle": "italic", - "fontSize": "@textSizeSecondaryHint", - "color": "@colorTextPrimary" - } - }, - "textStyleDetails": { - "extend": ["textStyleBase2", "mixinDetails"] - } - }, - "onMount": [], - "graphics": {}, - "commands": {}, - "layouts": { - "ListTemplate1": { - "parameters": ["backgroundImage", "title", "logo", "hintText", "listData"], - "item": [ - { - "type": "Container", - "width": "100vw", - "height": "100vh", - "direction": "column", - "items": [ - { - "type": "Image", - "source": "${backgroundImage}", - "scale": "best-fill", - "width": "100vw", - "height": "100vh", - "position": "absolute" - }, - { - "type": "AlexaHeader", - "headerTitle": "${title}", - "headerAttributionImage": "${logo}" - }, - { - "type": "Sequence", - "grow": 1, - "height": "80vh", - "scrollDirection": "vertical", - "paddingLeft": "@marginLeft", - "paddingRight": "@marginRight", - "data": "${listData}", - "numbered": true, - "items": [ - { - "type": "VerticalListItem", - "image": "${data.image.sources[0].url}", - "primaryText": "${data.textContent.primaryText.text}", - "secondaryText": "${data.textContent.secondaryText.text}", - "tertiaryText": "${data.textContent.tertiaryText.text}" - } - ] - } - ] - } - ] - }, - "VerticalListItem": { - "parameters": ["primaryText", "secondaryText", "tertiaryText", "image"], - "item": [ - { - "when": "${viewport.shape == 'round'}", - "type": "Container", - "direction": "row", - "height": 200, - "width": 500, - "alignItems": "center", - "items": [ - { - "type": "Text", - "text": "${ordinal}", - "paddingBottom": "20dp", - "color": "white", - "spacing": "5dp" - }, - { - "type": "Image", - "when": "${image}", - "source": "${image}", - "height": 150, - "width": 150, - "spacing": 15, - "scale": "best-fit", - "align": "top" - }, - { - "type": "Container", - "direction": "column", - "spacing": 25, - "items": [ - { - "type": "Text", - "text": "${primaryText}", - "style": "textStyleDetail", - "grow": 1, - "shrink": 1, - "fontWeight": "300", - "maxLines": 1 - }, - { - "type": "Text", - "text": "${secondaryText}", - "style": "textStyleCaption", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - }, - { - "type": "Text", - "text": "${tertiaryText}", - "style": "textStyleDetails", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - } - ] - } - ] - }, - { - "type": "Container", - "direction": "row", - "height": 125, - "width": 800, - "alignItems": "center", - "items": [ - { - "type": "Text", - "text": "${ordinal}", - "paddingBottom": "20dp", - "color": "white", - "spacing": "5dp" - }, - { - "type": "Image", - "when": "${image}", - "source": "${image}", - "height": 100, - "width": 100, - "align": "top", - "spacing": 50, - "scale": "best-fit" - }, - { - "type": "Container", - "spacing": 30, - "direction": "column", - "items": [ - { - "type": "Text", - "text": "${primaryText}", - "style": "textStyleBody", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - }, - { - "type": "Text", - "text": "${secondaryText}", - "style": "textStyleDetails", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - } - ] - }, - { - "type": "Text", - "text": "${tertiaryText}", - "style": "textStyleBody", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "textAlign": "right", - "maxLines": 1 - } - ] - } - ] - } - }, - "mainTemplate": { - "parameters": ["payload"], - "item": [ - { - "type": "Container", - "id": "BookCabSimpleDialogAPL", - "items": [ - { - "type": "TouchWrapper", - "onPress": { - "type": "SendEvent", - "arguments": ["delegateToSkillNew"] - }, - "item": { - "type": "Text", - "id": "BookCabSimpleDialogAPL", - "paddingTop": "100", - "paddingLeft": "100", - "color": "green", - "size": 50, - "text": "delegateToSkillNew" - } - }, - { - "type": "TouchWrapper", - "onPress": { - "type": "SendEvent", - "arguments": ["delegateToSkillOld"] - }, - "item": { - "type": "Text", - "id": "BookCabSimpleDialogAPL", - "paddingTop": "100", - "paddingLeft": "100", - "color": "green", - "size": 50, - "text": "delegateToSkillOld" - } - }, - { - "type": "TouchWrapper", - "onPress": { - "type": "SendEvent", - "arguments": ["delegateToColtraneNew"] - }, - "item": { - "type": "Text", - "id": "BookCabSimpleDialogAPL", - "paddingTop": "100", - "paddingLeft": "100", - "color": "green", - "size": 50, - "text": "delegateToColtraneNew" - } - }, - { - "type": "TouchWrapper", - "onPress": { - "type": "SendEvent", - "arguments": ["delegateToColtraneOld"] - }, - "item": { - "type": "Text", - "id": "BookCabSimpleDialogAPL", - "paddingTop": "100", - "paddingLeft": "100", - "color": "green", - "size": 50, - "text": "delegateToColtraneOld" - } - } - ] - } - ] - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/display/request_city_apl_display/document.json b/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/display/request_city_apl_display/document.json deleted file mode 100644 index 6fea1ff7..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/display/request_city_apl_display/document.json +++ /dev/null @@ -1,331 +0,0 @@ -{ - "type": "APL", - "version": "1.1", - "settings": {}, - "theme": "dark", - "import": [ - { - "name": "alexa-layouts", - "version": "1.0.0" - } - ], - "resources": [ - { - "description": "Stock color for the light theme", - "colors": { - "colorTextPrimary": "#151920" - } - }, - { - "description": "Stock color for the dark theme", - "when": "${viewport.theme == 'dark'}", - "colors": { - "colorTextPrimary": "#f0f1ef" - } - }, - { - "description": "Standard font sizes", - "dimensions": { - "textSizeBody": 48, - "textSizePrimary": 27, - "textSizeSecondary": 23, - "textSizeDetails": 20, - "textSizeSecondaryHint": 25 - } - }, - { - "description": "Common spacing values", - "dimensions": { - "spacingThin": 6, - "spacingSmall": 12, - "spacingMedium": 24, - "spacingLarge": 48, - "spacingExtraLarge": 72 - } - }, - { - "description": "Common margins and padding", - "dimensions": { - "marginTop": 40, - "marginLeft": 60, - "marginRight": 60, - "marginBottom": 40 - } - } - ], - "styles": { - "textStyleBase": { - "description": "Base font description; set color", - "values": [ - { - "color": "@colorTextPrimary" - } - ] - }, - "textStyleBase0": { - "description": "Thin version of basic font", - "extend": "textStyleBase", - "values": { - "fontWeight": "100" - } - }, - "textStyleBase1": { - "description": "Light version of basic font", - "extend": "textStyleBase", - "values": { - "fontWeight": "300" - } - }, - "textStyleBase2": { - "description": "Regular version of basic font", - "extend": "textStyleBase", - "values": { - "fontWeight": "500" - } - }, - "mixinBody": { - "values": { - "fontSize": "@textSizeBody" - } - }, - "mixinPrimary": { - "values": { - "fontSize": "@textSizePrimary" - } - }, - "mixinDetails": { - "values": { - "fontSize": "@textSizeDetails" - } - }, - "mixinSecondary": { - "values": { - "fontSize": "@textSizeSecondary" - } - }, - "textStylePrimary": { - "extend": ["textStyleBase1", "mixinPrimary"] - }, - "textStyleSecondary": { - "extend": ["textStyleBase0", "mixinSecondary"] - }, - "textStyleBody": { - "extend": ["textStyleBase1", "mixinBody"] - }, - "textStyleSecondaryHint": { - "values": { - "fontFamily": "Bookerly", - "fontStyle": "italic", - "fontSize": "@textSizeSecondaryHint", - "color": "@colorTextPrimary" - } - }, - "textStyleDetails": { - "extend": ["textStyleBase2", "mixinDetails"] - } - }, - "onMount": [], - "graphics": {}, - "commands": {}, - "layouts": { - "ListTemplate1": { - "parameters": ["backgroundImage", "title", "logo", "hintText", "listData"], - "item": [ - { - "type": "Container", - "width": "100vw", - "height": "100vh", - "direction": "column", - "items": [ - { - "type": "Image", - "source": "${backgroundImage}", - "scale": "best-fill", - "width": "100vw", - "height": "100vh", - "position": "absolute" - }, - { - "type": "AlexaHeader", - "headerTitle": "${title}", - "headerAttributionImage": "${logo}" - }, - { - "type": "Sequence", - "grow": 1, - "height": "80vh", - "scrollDirection": "vertical", - "paddingLeft": "@marginLeft", - "paddingRight": "@marginRight", - "data": "${listData}", - "numbered": true, - "items": [ - { - "type": "VerticalListItem", - "image": "${data.image.sources[0].url}", - "primaryText": "${data.textContent.primaryText.text}", - "secondaryText": "${data.textContent.secondaryText.text}", - "tertiaryText": "${data.textContent.tertiaryText.text}" - } - ] - } - ] - } - ] - }, - "VerticalListItem": { - "parameters": ["primaryText", "secondaryText", "tertiaryText", "image"], - "item": [ - { - "when": "${viewport.shape == 'round'}", - "type": "Container", - "direction": "row", - "height": 200, - "width": 500, - "alignItems": "center", - "items": [ - { - "type": "Text", - "text": "${ordinal}", - "paddingBottom": "20dp", - "color": "white", - "spacing": "5dp" - }, - { - "type": "Image", - "when": "${image}", - "source": "${image}", - "height": 150, - "width": 150, - "spacing": 15, - "scale": "best-fit", - "align": "top" - }, - { - "type": "Container", - "direction": "column", - "spacing": 25, - "items": [ - { - "type": "Text", - "text": "${primaryText}", - "style": "textStyleDetail", - "grow": 1, - "shrink": 1, - "fontWeight": "300", - "maxLines": 1 - }, - { - "type": "Text", - "text": "${secondaryText}", - "style": "textStyleCaption", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - }, - { - "type": "Text", - "text": "${tertiaryText}", - "style": "textStyleDetails", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - } - ] - } - ] - }, - { - "type": "Container", - "direction": "row", - "height": 125, - "width": 800, - "alignItems": "center", - "items": [ - { - "type": "Text", - "text": "${ordinal}", - "paddingBottom": "20dp", - "color": "white", - "spacing": "5dp" - }, - { - "type": "Image", - "when": "${image}", - "source": "${image}", - "height": 100, - "width": 100, - "align": "top", - "spacing": 50, - "scale": "best-fit" - }, - { - "type": "Container", - "spacing": 30, - "direction": "column", - "items": [ - { - "type": "Text", - "text": "${primaryText}", - "style": "textStyleBody", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - }, - { - "type": "Text", - "text": "${secondaryText}", - "style": "textStyleDetails", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - } - ] - }, - { - "type": "Text", - "text": "${tertiaryText}", - "style": "textStyleBody", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "textAlign": "right", - "maxLines": 1 - } - ] - } - ] - } - }, - "mainTemplate": { - "parameters": ["payload"], - "item": [ - { - "type": "Container", - "id": "BookCabSimpleDialogAPL", - "items": [ - { - "type": "TouchWrapper", - "onPress": { - "type": "SendEvent", - "arguments": ["delegateToColtraneOld"] - }, - "item": { - "type": "Text", - "id": "BookCabSimpleDialogAPL", - "paddingTop": "100", - "paddingLeft": "100", - "color": "green", - "size": 50, - "text": "which city ?" - } - } - ] - } - ] - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/display/request_date_apl_display/document.json b/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/display/request_date_apl_display/document.json deleted file mode 100644 index d41ea236..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/display/request_date_apl_display/document.json +++ /dev/null @@ -1,331 +0,0 @@ -{ - "type": "APL", - "version": "1.1", - "settings": {}, - "theme": "dark", - "import": [ - { - "name": "alexa-layouts", - "version": "1.0.0" - } - ], - "resources": [ - { - "description": "Stock color for the light theme", - "colors": { - "colorTextPrimary": "#151920" - } - }, - { - "description": "Stock color for the dark theme", - "when": "${viewport.theme == 'dark'}", - "colors": { - "colorTextPrimary": "#f0f1ef" - } - }, - { - "description": "Standard font sizes", - "dimensions": { - "textSizeBody": 48, - "textSizePrimary": 27, - "textSizeSecondary": 23, - "textSizeDetails": 20, - "textSizeSecondaryHint": 25 - } - }, - { - "description": "Common spacing values", - "dimensions": { - "spacingThin": 6, - "spacingSmall": 12, - "spacingMedium": 24, - "spacingLarge": 48, - "spacingExtraLarge": 72 - } - }, - { - "description": "Common margins and padding", - "dimensions": { - "marginTop": 40, - "marginLeft": 60, - "marginRight": 60, - "marginBottom": 40 - } - } - ], - "styles": { - "textStyleBase": { - "description": "Base font description; set color", - "values": [ - { - "color": "@colorTextPrimary" - } - ] - }, - "textStyleBase0": { - "description": "Thin version of basic font", - "extend": "textStyleBase", - "values": { - "fontWeight": "100" - } - }, - "textStyleBase1": { - "description": "Light version of basic font", - "extend": "textStyleBase", - "values": { - "fontWeight": "300" - } - }, - "textStyleBase2": { - "description": "Regular version of basic font", - "extend": "textStyleBase", - "values": { - "fontWeight": "500" - } - }, - "mixinBody": { - "values": { - "fontSize": "@textSizeBody" - } - }, - "mixinPrimary": { - "values": { - "fontSize": "@textSizePrimary" - } - }, - "mixinDetails": { - "values": { - "fontSize": "@textSizeDetails" - } - }, - "mixinSecondary": { - "values": { - "fontSize": "@textSizeSecondary" - } - }, - "textStylePrimary": { - "extend": ["textStyleBase1", "mixinPrimary"] - }, - "textStyleSecondary": { - "extend": ["textStyleBase0", "mixinSecondary"] - }, - "textStyleBody": { - "extend": ["textStyleBase1", "mixinBody"] - }, - "textStyleSecondaryHint": { - "values": { - "fontFamily": "Bookerly", - "fontStyle": "italic", - "fontSize": "@textSizeSecondaryHint", - "color": "@colorTextPrimary" - } - }, - "textStyleDetails": { - "extend": ["textStyleBase2", "mixinDetails"] - } - }, - "onMount": [], - "graphics": {}, - "commands": {}, - "layouts": { - "ListTemplate1": { - "parameters": ["backgroundImage", "title", "logo", "hintText", "listData"], - "item": [ - { - "type": "Container", - "width": "100vw", - "height": "100vh", - "direction": "column", - "items": [ - { - "type": "Image", - "source": "${backgroundImage}", - "scale": "best-fill", - "width": "100vw", - "height": "100vh", - "position": "absolute" - }, - { - "type": "AlexaHeader", - "headerTitle": "${title}", - "headerAttributionImage": "${logo}" - }, - { - "type": "Sequence", - "grow": 1, - "height": "80vh", - "scrollDirection": "vertical", - "paddingLeft": "@marginLeft", - "paddingRight": "@marginRight", - "data": "${listData}", - "numbered": true, - "items": [ - { - "type": "VerticalListItem", - "image": "${data.image.sources[0].url}", - "primaryText": "${data.textContent.primaryText.text}", - "secondaryText": "${data.textContent.secondaryText.text}", - "tertiaryText": "${data.textContent.tertiaryText.text}" - } - ] - } - ] - } - ] - }, - "VerticalListItem": { - "parameters": ["primaryText", "secondaryText", "tertiaryText", "image"], - "item": [ - { - "when": "${viewport.shape == 'round'}", - "type": "Container", - "direction": "row", - "height": 200, - "width": 500, - "alignItems": "center", - "items": [ - { - "type": "Text", - "text": "${ordinal}", - "paddingBottom": "20dp", - "color": "white", - "spacing": "5dp" - }, - { - "type": "Image", - "when": "${image}", - "source": "${image}", - "height": 150, - "width": 150, - "spacing": 15, - "scale": "best-fit", - "align": "top" - }, - { - "type": "Container", - "direction": "column", - "spacing": 25, - "items": [ - { - "type": "Text", - "text": "${primaryText}", - "style": "textStyleDetail", - "grow": 1, - "shrink": 1, - "fontWeight": "300", - "maxLines": 1 - }, - { - "type": "Text", - "text": "${secondaryText}", - "style": "textStyleCaption", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - }, - { - "type": "Text", - "text": "${tertiaryText}", - "style": "textStyleDetails", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - } - ] - } - ] - }, - { - "type": "Container", - "direction": "row", - "height": 125, - "width": 800, - "alignItems": "center", - "items": [ - { - "type": "Text", - "text": "${ordinal}", - "paddingBottom": "20dp", - "color": "white", - "spacing": "5dp" - }, - { - "type": "Image", - "when": "${image}", - "source": "${image}", - "height": 100, - "width": 100, - "align": "top", - "spacing": 50, - "scale": "best-fit" - }, - { - "type": "Container", - "spacing": 30, - "direction": "column", - "items": [ - { - "type": "Text", - "text": "${primaryText}", - "style": "textStyleBody", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - }, - { - "type": "Text", - "text": "${secondaryText}", - "style": "textStyleDetails", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - } - ] - }, - { - "type": "Text", - "text": "${tertiaryText}", - "style": "textStyleBody", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "textAlign": "right", - "maxLines": 1 - } - ] - } - ] - } - }, - "mainTemplate": { - "parameters": ["payload"], - "item": [ - { - "type": "Container", - "id": "BookCabSimpleDialogAPL", - "items": [ - { - "type": "TouchWrapper", - "onPress": { - "type": "SendEvent", - "arguments": ["delegateToColtraneOld"] - }, - "item": { - "type": "Text", - "id": "BookCabSimpleDialogAPL", - "paddingTop": "100", - "paddingLeft": "100", - "color": "green", - "size": 50, - "text": "which date ?" - } - } - ] - } - ] - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/display/weather_success_apl_display/document.json b/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/display/weather_success_apl_display/document.json deleted file mode 100644 index 3bcc0e4a..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/display/weather_success_apl_display/document.json +++ /dev/null @@ -1,379 +0,0 @@ -{ - "type": "APL", - "version": "1.1", - "settings": {}, - "theme": "dark", - "import": [ - { - "name": "alexa-layouts", - "version": "1.0.0" - } - ], - "resources": [ - { - "description": "Stock color for the light theme", - "colors": { - "colorTextPrimary": "#151920" - } - }, - { - "description": "Stock color for the dark theme", - "when": "${viewport.theme == 'dark'}", - "colors": { - "colorTextPrimary": "#f0f1ef" - } - }, - { - "description": "Standard font sizes", - "dimensions": { - "textSizeBody": 48, - "textSizePrimary": 27, - "textSizeSecondary": 23, - "textSizeDetails": 20, - "textSizeSecondaryHint": 25 - } - }, - { - "description": "Common spacing values", - "dimensions": { - "spacingThin": 6, - "spacingSmall": 12, - "spacingMedium": 24, - "spacingLarge": 48, - "spacingExtraLarge": 72 - } - }, - { - "description": "Common margins and padding", - "dimensions": { - "marginTop": 40, - "marginLeft": 60, - "marginRight": 60, - "marginBottom": 40 - } - } - ], - "styles": { - "textStyleBase": { - "description": "Base font description; set color", - "values": [ - { - "color": "@colorTextPrimary" - } - ] - }, - "textStyleBase0": { - "description": "Thin version of basic font", - "extend": "textStyleBase", - "values": { - "fontWeight": "100" - } - }, - "textStyleBase1": { - "description": "Light version of basic font", - "extend": "textStyleBase", - "values": { - "fontWeight": "300" - } - }, - "textStyleBase2": { - "description": "Regular version of basic font", - "extend": "textStyleBase", - "values": { - "fontWeight": "500" - } - }, - "mixinBody": { - "values": { - "fontSize": "@textSizeBody" - } - }, - "mixinPrimary": { - "values": { - "fontSize": "@textSizePrimary" - } - }, - "mixinDetails": { - "values": { - "fontSize": "@textSizeDetails" - } - }, - "mixinSecondary": { - "values": { - "fontSize": "@textSizeSecondary" - } - }, - "textStylePrimary": { - "extend": ["textStyleBase1", "mixinPrimary"] - }, - "textStyleSecondary": { - "extend": ["textStyleBase0", "mixinSecondary"] - }, - "textStyleBody": { - "extend": ["textStyleBase1", "mixinBody"] - }, - "textStyleSecondaryHint": { - "values": { - "fontFamily": "Bookerly", - "fontStyle": "italic", - "fontSize": "@textSizeSecondaryHint", - "color": "@colorTextPrimary" - } - }, - "textStyleDetails": { - "extend": ["textStyleBase2", "mixinDetails"] - } - }, - "onMount": [], - "graphics": {}, - "commands": {}, - "layouts": { - "ListTemplate1": { - "parameters": ["backgroundImage", "title", "logo", "hintText", "listData"], - "item": [ - { - "type": "Container", - "width": "100vw", - "height": "100vh", - "direction": "column", - "items": [ - { - "type": "Image", - "source": "${backgroundImage}", - "scale": "best-fill", - "width": "100vw", - "height": "100vh", - "position": "absolute" - }, - { - "type": "AlexaHeader", - "headerTitle": "${title}", - "headerAttributionImage": "${logo}" - }, - { - "type": "Sequence", - "grow": 1, - "height": "80vh", - "scrollDirection": "vertical", - "paddingLeft": "@marginLeft", - "paddingRight": "@marginRight", - "data": "${listData}", - "numbered": true, - "items": [ - { - "type": "VerticalListItem", - "image": "${data.image.sources[0].url}", - "primaryText": "${data.textContent.primaryText.text}", - "secondaryText": "${data.textContent.secondaryText.text}", - "tertiaryText": "${data.textContent.tertiaryText.text}" - } - ] - } - ] - } - ] - }, - "VerticalListItem": { - "parameters": ["primaryText", "secondaryText", "tertiaryText", "image"], - "item": [ - { - "when": "${viewport.shape == 'round'}", - "type": "Container", - "direction": "row", - "height": 200, - "width": 500, - "alignItems": "center", - "items": [ - { - "type": "Text", - "text": "${ordinal}", - "paddingBottom": "20dp", - "color": "white", - "spacing": "5dp" - }, - { - "type": "Image", - "when": "${image}", - "source": "${image}", - "height": 150, - "width": 150, - "spacing": 15, - "scale": "best-fit", - "align": "top" - }, - { - "type": "Container", - "direction": "column", - "spacing": 25, - "items": [ - { - "type": "Text", - "text": "${primaryText}", - "style": "textStyleDetail", - "grow": 1, - "shrink": 1, - "fontWeight": "300", - "maxLines": 1 - }, - { - "type": "Text", - "text": "${secondaryText}", - "style": "textStyleCaption", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - }, - { - "type": "Text", - "text": "${tertiaryText}", - "style": "textStyleDetails", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - } - ] - } - ] - }, - { - "type": "Container", - "direction": "row", - "height": 125, - "width": 800, - "alignItems": "center", - "items": [ - { - "type": "Text", - "text": "${ordinal}", - "paddingBottom": "20dp", - "color": "white", - "spacing": "5dp" - }, - { - "type": "Image", - "when": "${image}", - "source": "${image}", - "height": 100, - "width": 100, - "align": "top", - "spacing": 50, - "scale": "best-fit" - }, - { - "type": "Container", - "spacing": 30, - "direction": "column", - "items": [ - { - "type": "Text", - "text": "${primaryText}", - "style": "textStyleBody", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - }, - { - "type": "Text", - "text": "${secondaryText}", - "style": "textStyleDetails", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - } - ] - }, - { - "type": "Text", - "text": "${tertiaryText}", - "style": "textStyleBody", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "textAlign": "right", - "maxLines": 1 - } - ] - } - ] - } - }, - "mainTemplate": { - "parameters": ["payload"], - "item": [ - { - "type": "Container", - "id": "BookCabSimpleDialogAPL", - "items": [ - { - "type": "TouchWrapper", - "onPress": { - "type": "SendEvent", - "arguments": ["delegateToSkillNew"] - }, - "item": { - "type": "Text", - "id": "BookCabSimpleDialogAPL", - "paddingTop": "100", - "paddingLeft": "100", - "color": "green", - "size": 50, - "text": "delegateToSkillNew" - } - }, - { - "type": "TouchWrapper", - "onPress": { - "type": "SendEvent", - "arguments": ["delegateToSkillOld"] - }, - "item": { - "type": "Text", - "id": "BookCabSimpleDialogAPL", - "paddingTop": "100", - "paddingLeft": "100", - "color": "green", - "size": 50, - "text": "delegateToSkillOld" - } - }, - { - "type": "TouchWrapper", - "onPress": { - "type": "SendEvent", - "arguments": ["delegateToColtraneNew"] - }, - "item": { - "type": "Text", - "id": "BookCabSimpleDialogAPL", - "paddingTop": "100", - "paddingLeft": "100", - "color": "green", - "size": 50, - "text": "delegateToColtraneNew" - } - }, - { - "type": "TouchWrapper", - "onPress": { - "type": "SendEvent", - "arguments": ["delegateToColtraneOld"] - }, - "item": { - "type": "Text", - "id": "BookCabSimpleDialogAPL", - "paddingTop": "100", - "paddingLeft": "100", - "color": "green", - "size": 50, - "text": "delegateToColtraneOld" - } - } - ] - } - ] - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/AlexaConversationsBye/document.json b/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/AlexaConversationsBye/document.json deleted file mode 100644 index a0e2b3a8..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/AlexaConversationsBye/document.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": ["payload"], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "Bye.", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/AlexaConversationsNotifyFailure/document.json b/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/AlexaConversationsNotifyFailure/document.json deleted file mode 100644 index 61d75e08..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/AlexaConversationsNotifyFailure/document.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": ["payload"], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "Sorry, there was an error in the request.", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/AlexaConversationsOutOfDomain/document.json b/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/AlexaConversationsOutOfDomain/document.json deleted file mode 100644 index e23d5986..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/AlexaConversationsOutOfDomain/document.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": ["payload"], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "Sorry, I don't understand.", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/AlexaConversationsProvideHelp/document.json b/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/AlexaConversationsProvideHelp/document.json deleted file mode 100644 index 612a6f6e..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/AlexaConversationsProvideHelp/document.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": ["payload"], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "I can give you the weather report. Just say \"what's the weather\" to start.", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/AlexaConversationsRequestMore/document.json b/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/AlexaConversationsRequestMore/document.json deleted file mode 100644 index 32a98507..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/AlexaConversationsRequestMore/document.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": ["payload"], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "What do you want to do.", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/AlexaConversationsThankYou/document.json b/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/AlexaConversationsThankYou/document.json deleted file mode 100644 index 4aeb6f4b..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/AlexaConversationsThankYou/document.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": ["payload"], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "Thank you.", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/AlexaConversationsWelcome/document.json b/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/AlexaConversationsWelcome/document.json deleted file mode 100644 index b4ce85fe..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/AlexaConversationsWelcome/document.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": ["payload"], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "Welcome to the weather bot, I can give you the weather report. Just say \"what's the weather\" to start.", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/AlexaConversationsYouAreWelcome/document.json b/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/AlexaConversationsYouAreWelcome/document.json deleted file mode 100644 index 2cd1b9a8..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/AlexaConversationsYouAreWelcome/document.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": ["payload"], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "You are welcome.", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/alexa_prize_preconditions_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/alexa_prize_preconditions_apla/document.json deleted file mode 100644 index 60503182..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/alexa_prize_preconditions_apla/document.json +++ /dev/null @@ -1,89 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": ["payload"], - "item": { - "type": "Selector", - "description": "Selects the speech response to render when device/locale is not supported", - "items": [ - { - "when": "${payload.result.isDeviceSupported == 0}", - "type": "Speech", - "contentType": "text", - "content": "Sorry, Alexa Prize is not available on this device.", - "description": "" - }, - { - "when": "${payload.result.isLocaleSupported == 0}", - "type": "Speech", - "contentType": "text", - "content": "Sorry, Alexa Prize is not available in your locale.", - "description": "" - }, - { - "when": "${payload.result.isSocialBotAvailable == 0}", - "type": "Speech", - "contentType": "text", - "content": "Right now the Alexa Prize socialbots are busy. Please try again soon and help the university students in their competition to advance conversational A I.", - "description": "" - }, - { - "when": "${payload.result.isAlexaPrizeEnabled == 0}", - "type": "Speech", - "contentType": "text", - "content": "Alexa Prize is currently disabled for this account. Please visit the skill store in the Alexa App to re-enable it.", - "description": "" - }, - { - "when": "${payload.result.isTopicBanned == 1}", - "type": "Speech", - "contentType": "text", - "content": "I’d rather not talk about that, but there’s lots of other things to chat about. Do you still wanna chat?", - "description": "The topic that user wants to talk about is banned, ask if they still want to chat about something else" - }, - { - "when": "${payload.result.isFalseWake == 1}", - "type": "Speech", - "contentType": "text", - "content": "Would you like to chat with an Alexa Prize socialbot?", - "description": "" - }, - { - "when": "${payload.result.handoffPromptOverride == 'HandOffConversationForFilming'}", - "type": "Speech", - "contentType": "text", - "content": "Welcome to the Finals of the Alexa Prize Socialbot Grand Challenge 3, a university competition to advance AI. I’ll get you a socialbot now.", - "description": "" - }, - { - "when": "${payload.result.handoffPromptOverride == 'HandOffConversationForFinals'}", - "type": "Speech", - "contentType": "text", - "content": "Welcome to the Alexa Prize Socialbot Grand Challenge 3: Grand Finale. Here’s one of the finalists.", - "description": "" - }, - { - "when": "${payload.result.handoffPromptOverride == 'HandOffConversationForRepeatUser'}", - "type": "Speech", - "contentType": "text", - "content": "Welcome to the Alexa Prize, a university competition to advance AI. It’s quarterfinals for these socialbots and your ratings help determine who makes it to the semifinals. I’ll get you a socialbot now. When you’re done, say stop, and I’ll ask you for your rating. Your conversation and feedback will be shared with the university to help the socialbots improve.", - "description": "" - }, - { - "when": "${payload.result.handoffPromptOverride == 'CancelHandoff'}", - "type": "Speech", - "contentType": "text", - "content": "Okay", - "description": "" - }, - { - "type": "Speech", - "contentType": "text", - "content": "Welcome to the Alexa Prize, a university competition to advance AI. It’s quarterfinals for these socialbots and your ratings help determine who makes it to the semifinals. I’ll get you a socialbot now. When you’re done, say stop, and I’ll ask you for your rating. Your conversation and feedback will be shared with the university to help the socialbots improve.", - "description": "This is the current default handoff prompt" - } - ] - } - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/confirm_color_for_fruit_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/confirm_color_for_fruit_apla/document.json deleted file mode 100644 index 62c9758b..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/confirm_color_for_fruit_apla/document.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": ["payload"], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "confirm color is ${payload.colorName} ? ", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/confirm_fruitName_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/confirm_fruitName_apla/document.json deleted file mode 100644 index 47433a49..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/confirm_fruitName_apla/document.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": ["payload"], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "confirm fruit ${payload.fruitName} ? ", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/getEmployeePosition_success_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/getEmployeePosition_success_apla/document.json deleted file mode 100644 index d0a91481..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/getEmployeePosition_success_apla/document.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": ["payload"], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "${payload.result.name1} born on ${payload.result.a_dateOfBirth} with employee id ${payload.result.emplyee1id} , is an ${payload.result.position} ", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/no_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/no_apla/document.json deleted file mode 100644 index 96a3af82..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/no_apla/document.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": ["payload"], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "I'm sorry you didn't like it", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/nothing2_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/nothing2_apla/document.json deleted file mode 100644 index af75a7a5..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/nothing2_apla/document.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": ["payload"], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "The number you gave us was not 3.", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/nothing_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/nothing_apla/document.json deleted file mode 100644 index bca77c74..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/nothing_apla/document.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": ["payload"], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "The number you gave us was 3.", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/numericfeedback_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/numericfeedback_apla/document.json deleted file mode 100644 index 2219120c..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/numericfeedback_apla/document.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": ["payload"], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "Your random number was ${payload.num}. How did we do? Please give this interaction a rating between 1-5, where 5 is the highest rating", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/rating_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/rating_apla/document.json deleted file mode 100644 index 06b50d68..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/rating_apla/document.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": ["payload"], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "rating please?", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/requestArgs_request_fruitName_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/requestArgs_request_fruitName_apla/document.json deleted file mode 100644 index 5e5d608a..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/requestArgs_request_fruitName_apla/document.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": ["payload"], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "tell me the fruit name ?", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - }, - { - "type": "Speech", - "contentType": "text", - "content": "random slection tell me the fruit name ?", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/request_city_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/request_city_apla/document.json deleted file mode 100644 index 64297b5e..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/request_city_apla/document.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": ["payload"], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "Which city?", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/request_city_date_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/request_city_date_apla/document.json deleted file mode 100644 index a55ea5e1..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/request_city_date_apla/document.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": ["payload"], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "Which city and for which date?", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/request_colorName_multiple_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/request_colorName_multiple_apla/document.json deleted file mode 100644 index 5e5891e1..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/request_colorName_multiple_apla/document.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": ["payload"], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "which color?", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/request_date_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/request_date_apla/document.json deleted file mode 100644 index af3a3f7d..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/request_date_apla/document.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": ["payload"], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "Which date?", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/request_dob_getDate_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/request_dob_getDate_apla/document.json deleted file mode 100644 index b70a2ac6..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/request_dob_getDate_apla/document.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": ["payload"], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "SSML", - "content": "provide date?", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/request_getEmploeeID_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/request_getEmploeeID_apla/document.json deleted file mode 100644 index 32c39133..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/request_getEmploeeID_apla/document.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": ["payload"], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "SSML", - "content": "provide employee id?", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/request_name_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/request_name_apla/document.json deleted file mode 100644 index db05dfee..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/request_name_apla/document.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": ["payload"], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "SSML", - "content": "what is your cool name?", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/success_colorFruitAPI_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/success_colorFruitAPI_apla/document.json deleted file mode 100644 index b566e3fb..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/success_colorFruitAPI_apla/document.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": ["payload"], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "price of an ${payload.result.fruitName} is free bucks ", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/success_fruitPriceAPI_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/success_fruitPriceAPI_apla/document.json deleted file mode 100644 index 0db81389..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/success_fruitPriceAPI_apla/document.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": ["payload"], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "price of an ${payload.result.fruitName} is ${payload.result.price} bucks ", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/weather_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/weather_apla/document.json deleted file mode 100644 index b2f5f3d9..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/weather_apla/document.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": ["payload"], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "when": "${payload.weatherResult != null && payload.weatherResult.cityName != null && payload.weatherResult.highTemp != null && payload.weatherResult.lowTemp != null}", - "type": "Speech", - "contentType": "text", - "content": "In ${payload.weatherResult.cityName}, it's a high of ${payload.weatherResult.highTemp} degrees and a low of ${payload.weatherResult.lowTemp} degrees.", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - }, - { - "when": "${payload.weatherResult != null && payload.weatherResult.cityNameChanged != null && payload.weatherResult.highTemp != null && payload.weatherResult.lowTemp != null}", - "type": "Speech", - "contentType": "text", - "content": "In ${payload.weatherResult.cityName}, it's a high of ${payload.weatherResult.highTemp} degrees and a low of ${payload.weatherResult.lowTemp} degrees.", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/yes_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/yes_apla/document.json deleted file mode 100644 index a443c91e..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/yes_apla/document.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": ["payload"], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "Nice! Glad you like it", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/yesnofeedback_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/yesnofeedback_apla/document.json deleted file mode 100644 index fd08347e..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/yesnofeedback_apla/document.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": ["payload"], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "Your number was ${payload.num}. Is this a good number, yes or no?", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/skill.json b/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/skill.json deleted file mode 100644 index 5e99d129..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-1/skill-package/skill.json +++ /dev/null @@ -1,92 +0,0 @@ -{ - "manifest": { - "apis": { - "custom": { - "dialogManagement": { - "dialogManagers": [ - { - "type": "AMAZON.Conversations" - } - ], - "sessionStartDelegationStrategy": { - "target": "AMAZON.Conversations" - } - }, - "endpoint": { - "uri": "arn:aws:lambda:us-east-1:658396899051:function:47172cde-7bb8-4e42-8fdb-dc5138bdf323:Release_0" - }, - "interfaces": [ - { - "supportedViewports": [ - { - "maxHeight": 480, - "maxWidth": 480, - "minHeight": 480, - "minWidth": 480, - "mode": "HUB", - "shape": "ROUND" - }, - { - "maxHeight": 600, - "maxWidth": 1024, - "minHeight": 600, - "minWidth": 1024, - "mode": "HUB", - "shape": "RECTANGLE" - }, - { - "maxHeight": 800, - "maxWidth": 1280, - "minHeight": 800, - "minWidth": 1280, - "mode": "HUB", - "shape": "RECTANGLE" - }, - { - "maxHeight": 540, - "maxWidth": 960, - "minHeight": 540, - "minWidth": 960, - "mode": "TV", - "shape": "RECTANGLE" - } - ], - "type": "ALEXA_PRESENTATION_APL" - } - ], - "regions": { - "EU": { - "endpoint": { - "uri": "arn:aws:lambda:eu-west-1:658396899051:function:47172cde-7bb8-4e42-8fdb-dc5138bdf323:Release_0" - } - }, - "NA": { - "endpoint": { - "uri": "arn:aws:lambda:us-east-1:658396899051:function:47172cde-7bb8-4e42-8fdb-dc5138bdf323:Release_0" - } - }, - "FE": { - "endpoint": { - "uri": "arn:aws:lambda:us-west-2:658396899051:function:47172cde-7bb8-4e42-8fdb-dc5138bdf323:Release_0" - } - } - } - } - }, - "manifestVersion": "1.0", - "publishingInformation": { - "category": "KNOWLEDGE_AND_TRIVIA", - "distributionCountries": [], - "isAvailableWorldwide": true, - "locales": { - "en-US": { - "description": "Sample Full Description", - "examplePhrases": ["Alexa open hello world", "hello", "help"], - "name": "engineering test skill one", - "summary": "Sample Short Description" - } - }, - "testingInstructions": "Sample Testing Instructions." - } - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/.ask/ask-states.json b/test/unit/fixture/dialog-evaluate/test-project-2/.ask/ask-states.json deleted file mode 100644 index 25e2965b..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-2/.ask/ask-states.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "askcliStatesVersion": "2020-03-31", - "profiles": { - "mft-test": { - "skillId": "amzn1.ask.skill.a3588a9b-d645-4a23-9e1a-90c984de0b83" - } - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/ask-resources.json b/test/unit/fixture/dialog-evaluate/test-project-2/ask-resources.json deleted file mode 100644 index 67851f3d..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-2/ask-resources.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "askcliResourcesVersion": "2020-03-31", - "profiles": { - "mft-test": { - "skillMetadata": { - "src": "./skill-package" - } - } - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/conversations/Samenamespace.acdl b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/conversations/Samenamespace.acdl deleted file mode 100644 index b173cdf7..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/conversations/Samenamespace.acdl +++ /dev/null @@ -1,7 +0,0 @@ -namespace com.weatherbot.apis - -import com.amazon.ask.types.builtins.AMAZON.DATE -import com.weatherbot.types.WeatherResult -import slotTypes.customCity - -action WeatherResult getWeather(customCity cityName, DATE date) diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/conversations/apis.acdl b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/conversations/apis.acdl deleted file mode 100644 index ca21531f..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/conversations/apis.acdl +++ /dev/null @@ -1,51 +0,0 @@ -namespace com.weatherbot.apis - -import com.amazon.alexa.schema.Nothing -import com.amazon.ask.types.builtins.AMAZON.Color -import com.amazon.ask.types.builtins.AMAZON.Food -import com.amazon.ask.types.builtins.AMAZON.NUMBER -import com.amazon.ask.types.builtins.AMAZON.US_CITY -import com.weatherbot.types.bookCabResult -import com.weatherbot.types.bookedFlightResult -import com.weatherbot.types.result -import com.weatherbot.types.result_one -import com.weatherbot.types.resultthree -import slotTypes.StringLiteral -import slotTypes.city_name_one -import slotTypes.city_name_two -import slotTypes.complexNames -import slotTypes.crust -import slotTypes.pickUpFrom -import slotTypes.signs -import slotTypes.size -import slotTypes.toppings - -action resultthree colorFruitNameAAA(Food fruitName = nothing) - -action resultthree colorFruitName(Color colorName, Food fruitName = nothing) - -action result fruitNameAPI(Food fruitName) - -action NUMBER numberOfVisits() - -action NUMBER getCooler() - -action NUMBER welcomeApi() - -action Nothing getHeater() - -action result_one favColorSign_Name(complexNames name) - -//action result_one favColorSign_Name(complexNames name, signs sign = nothing) - -action bookedFlightResult bookFlightAPI(city_name_one source, city_name_two destination) - -action bookCabResult bookCabAPI(pickUpFrom pickUpFrom, city_name_one dropTo = nothing) - -action Nothing secondEarthAPI() - -action StringLiteral OrderTwoToppingPizza(toppings second_topping, toppings first_topping, crust crust, size size = nothing) - -action Nothing satheesh(US_CITY citsy) - -action Nothing Satheesh(US_CITY citsy) diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/conversations/basicOfferDialog.acdl b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/conversations/basicOfferDialog.acdl deleted file mode 100644 index 0be5d696..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/conversations/basicOfferDialog.acdl +++ /dev/null @@ -1,65 +0,0 @@ -namespace offerDialogFile - -import com.amazon.alexa.ask.conversations.Affirm -import com.amazon.alexa.ask.conversations.CarryOverArgument -import com.amazon.alexa.ask.conversations.Inform -import com.amazon.alexa.ask.conversations.Invoke -import com.amazon.alexa.ask.conversations.Notify -import com.amazon.alexa.ask.conversations.Offer -import com.amazon.alexa.ask.conversations.Request -import com.amazon.alexa.ask.conversations.RequestArguments -import com.amazon.alexa.ask.conversations.ensure -import com.amazon.alexa.ask.conversations.expect -import com.amazon.alexa.ask.conversations.response -import com.amazon.alexa.schema.Nothing -import com.amazon.alexa.schema.Thing -import com.weatherbot.apis.bookCabAPI -import com.weatherbot.apis.bookFlightAPI -import com.weatherbot.types.bookCabResult -import com.weatherbot.types.bookedFlightResult -import com.weatherbot.utteracesets.affirmCabAPIEvent -import com.weatherbot.utteracesets.bookFlightEvent -import com.weatherbot.utteracesets.informFromBookFlight -import com.weatherbot.utteracesets.informPickUpFromBookCab -import com.weatherbot.utteracesets.informToBookFlight -import prompts.requestFromBookFlight_apla -import prompts.requestPickUpFromBookCab_apla -import prompts.requestToBookFlight_apla -import prompts.successBookCabAPI_apla -import prompts.successBookFlightAPI_apla -import slotTypes.* -import prompts.* -import displays.* -import com.weatherbot.utteracesets.* -import com.amazon.alexa.ask.conversations.* -import com.amazon.alexa.schema.* -import com.weatherbot.types.* - -type payloadBookFlightAPI { - bookedFlightResult resultTwo -} - -type payloadOfferResult { - bookCabResult result -} - -dialog Nothing complex_two() { - sample { - expect(act = Invoke,event = bookFlightEvent) - response(act = Request { arguments = [ bookFlightAPI.arguments.source ]},response = requestFromBookFlight_apla) - //response(act = Request { arguments = [ bookFlightAPI.arguments.source ]},response = requestFromBookFlight_apla) - // source is seattle - sourceFlightEvent = expect(act = Inform,event = informFromBookFlight) - response(act = Request { arguments = [ bookFlightAPI.arguments.destination ]},response = requestToBookFlight_apla) - // destination to portland - destinationFlightEvent = expect(act = Inform,event = informToBookFlight) - resultFlightApi = bookFlightAPI(source = sourceFlightEvent.source,destination = destinationFlightEvent.destination) - response(response = successBookFlightAPI_apla,act = Notify { actionName = bookFlightAPI, success = true},payload = payloadBookFlightAPI { resultTwo = resultFlightApi},nextAct = Offer { actionName = bookCabAPI, arguments = [ bookCabAPI.arguments.pickUpFrom ], carryOverArguments = [ CarryOverArgument { argument = bookCabAPI.arguments.dropTo, source = resultFlightApi.source } ]}) - ensure(requestArgs = [ RequestArguments { arguments = [ bookCabAPI.arguments.pickUpFrom ], response = requestPickUpFromBookCab_apla }]) - expect(act = Affirm,event = affirmCabAPIEvent) - response(response = requestPickUpFromBookCab_apla,act = Request { arguments = [ bookCabAPI.arguments.pickUpFrom ]}) - PickUpCabEvent = expect(act = Inform,event = informPickUpFromBookCab) - resultOne = bookCabAPI(pickUpFrom = PickUpCabEvent.pickUpFrom,dropTo = resultFlightApi.source) - response(response = successBookCabAPI_apla,act = Notify { actionName = bookCabAPI},payload = payloadOfferResult { result = resultOne}) - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/conversations/conditions b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/conversations/conditions deleted file mode 100644 index 5de831a6..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/conversations/conditions +++ /dev/null @@ -1,71 +0,0 @@ -namespace conditionsACDlFile - -import com.amazon.alexa.ask.conversations.Inform -import com.amazon.alexa.ask.conversations.Invoke -import com.amazon.alexa.ask.conversations.MultiModalResponse -import com.amazon.alexa.ask.conversations.Notify -import com.amazon.alexa.ask.conversations.Offer -import com.amazon.alexa.ask.conversations.ReqAlt -import com.amazon.alexa.ask.conversations.Request -import com.amazon.alexa.ask.conversations.RequestArguments -import com.amazon.alexa.ask.conversations.ensure -import com.amazon.alexa.ask.conversations.expect -import com.amazon.alexa.ask.conversations.response -import com.amazon.alexa.ask.conversations.size -import com.amazon.alexa.schema.Nothing -import com.amazon.alexa.schema.Thing -import com.weatherbot.apis.favColorSign_Name -import com.weatherbot.apis.getWeather -import com.weatherbot.types.WeatherResult -import com.weatherbot.types.result_one -import com.weatherbot.utteracesets.getWeatherEventNoArgs -import com.weatherbot.utteracesets.informCityEvent -import com.weatherbot.utteracesets.informComplexNameEvent -import com.weatherbot.utteracesets.informDateEvent -import displays.request_city_apl_display -import prompts.request_city_apla -import prompts.request_date_apla -import prompts.request_name_apla -import prompts.success_favColorSign_Name_apla -import prompts.weather_success_apla -import slotTypes.* -import prompts.* -import displays.* -import com.weatherbot.utteracesets.* -import com.amazon.alexa.ask.conversations.* -import com.amazon.alexa.schema.* -import com.weatherbot.types.* - -type payload_one { - result_one result -} - -type payload_one_two { - WeatherResult weatherResult -} - -dialog Nothing conditionComplex() { - sample { - expect(act = Invoke,event = getWeatherEventNoArgs) - request_city_multimodal = MultiModalResponse {apla = request_city_apla,apl = request_city_apl_display - } - request_date_multimodal = MultiModalResponse {apla = request_date_apla,apl = request_city_apl_display - } - response(response = request_city_multimodal,act = Request { arguments = [ getWeather.arguments.cityName ]}) - cityEvent = expect(act = Inform,event = informCityEvent) - response(response = request_date_multimodal,act = Request { arguments = [ getWeather.arguments.date ]}) - dateEvent = expect(act = Inform,event = informDateEvent) - weatherResult = getWeather(cityName = cityEvent.cityName,date = dateEvent.date) - if (((weatherResult.highTemp < 3 && weatherResult.lowTemp > 0) && com.amazon.alexa.ask.conversations.size(list = weatherResult.itemsToUse) > 1)) - {response( response = weather_success_apla, act = Notify {actionName = getWeather }, - nextAct = Offer { actionName = favColorSign_Name, arguments = [ favColorSign_Name.arguments.name ] }) - ensure( requestArgs = [ RequestArguments { arguments = [ favColorSign_Name.arguments.name ], response = request_name_apla } ]) - ComplexNameEvent = expect( act = Inform, event = informComplexNameEvent) - resultOne_one = favColorSign_Name( name = ComplexNameEvent.name) - response( response = success_favColorSign_Name_apla, act = Notify { actionName = favColorSign_Name }, - payload = payload_one { result = resultOne_one }) - } else { - response( response = weather_success_apla, act = Notify { actionName = getWeather,success = false }, nextAct = ReqAlt { arguments = [ getWeather.arguments.cityName ] }, payload = payload_one_two { weatherResult = weatherResult })cityEvent_new = expect( act = Inform, event = informCityEvent)weatherResult_two = getWeather( cityName = cityEvent_new.cityName, date = dateEvent.date)successAPLWithAPLsa_nw = MultiModalResponse { apla = weather_success_apla}response( response = successAPLWithAPLsa_nw, act = Notify { actionName = getWeather }, payload = payload_one_two { weatherResult = weatherResult_two }) - } - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/conversations/conversation_empty b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/conversations/conversation_empty deleted file mode 100644 index 2fa96708..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/conversations/conversation_empty +++ /dev/null @@ -1,147 +0,0 @@ -namespace com.numberbot - -import com.amazon.alexa.ask.conversations.APLA -import com.amazon.alexa.ask.conversations.Action -import com.amazon.alexa.ask.conversations.Bye -import com.amazon.alexa.ask.conversations.InvocationName -import com.amazon.alexa.ask.conversations.Invoke -import com.amazon.alexa.ask.conversations.Locale -import com.amazon.alexa.ask.conversations.Notify -import com.amazon.alexa.ask.conversations.Offer -import com.amazon.alexa.ask.conversations.RequestArguments -import com.amazon.alexa.ask.conversations.SkillLevelResponses -import com.amazon.alexa.ask.conversations.ensure -import com.amazon.alexa.ask.conversations.expect -import com.amazon.alexa.ask.conversations.response -import com.amazon.alexa.ask.conversations.skill -import com.amazon.alexa.ask.conversations.utterances -import com.amazon.alexa.schema.Nothing -import com.amazon.alexa.schema.Number -import com.amazon.alexa.schema.Thing -import com.amazon.ask.types.builtins.AMAZON.NUMBER -import prompts.AlexaConversationsBye -import prompts.AlexaConversationsOutOfDomain -import prompts.AlexaConversationsProvideHelp -import prompts.AlexaConversationsRequestMore -import prompts.AlexaConversationsWelcome -import prompts.numericfeedback_apla -import prompts.rating_apla -import slotTypes.* -import prompts.* -import displays.* -import com.weatherbot.utteracesets.* -import com.amazon.alexa.ask.conversations.* -import com.amazon.alexa.schema.* -import com.weatherbot.types.* -/* -mySkill = skill( - locales = [ - Locale.en_US - ], - dialogs = [ - MainDialog - ], - skillLevelResponses = SkillLevelResponses { - welcome = AlexaConversationsWelcome, - out_of_domain = AlexaConversationsOutOfDomain, - bye = AlexaConversationsBye, - reqmore = AlexaConversationsRequestMore, - provide_help = AlexaConversationsProvideHelp - }, - invocationNames = [ - InvocationName { - locale = Locale.en_US, - invocationName = "acdl number feedback bot" - } - ] -) - -*/ - -type NumPayload { - Number num -} - -type RatingRequest { - NUMBER rating -} - -InformRatingEvent = utterances( - samples = [ - "my score is {rating}", - "that was a {rating} conversation", - "i rate you a {rating}", - "{rating}" - ] -) - -getStart = utterances( - samples = [ - "give me a number please" - ] -) - -action Nothing saveRating(Number rating) - -action Number getNumber() - -dialog Nothing GetFeedback(APLA feedback_prompt, Thing payload, Action notifyAction) { - sample { - response( - response = feedback_prompt, - act = Notify { - actionName = notifyAction, - success = true - }, - nextAct = Offer { - actionName = saveRating, - arguments = [ - saveRating.arguments.rating - ] - }, - payload = payload - ) - myRating = expect( - act = Invoke, - event = InformRatingEvent - ) - ensure( - requestArgs = [ - RequestArguments { - arguments = [ - saveRating.arguments.rating - ], - response = rating_apla - } - ] - ) - saveRating( - rating = myRating.rating - ) - } -} - -dialog Nothing MainDialog() { - sample { - expect( - act = Invoke, - event = getStart - ) - num = getNumber() - GetFeedback( - feedback_prompt = numericfeedback_apla, - payload = NumPayload { - num = num - }, - notifyAction = getNumber - ) - response( - response = AlexaConversationsBye, - act = Notify { - actionName = saveRating, - success = true - }, - nextAct = Bye {} - ) - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/conversations/delegateToSkill.acdl b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/conversations/delegateToSkill.acdl deleted file mode 100644 index b9c572d6..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/conversations/delegateToSkill.acdl +++ /dev/null @@ -1,33 +0,0 @@ -namespace delegateToSkill - -import com.amazon.alexa.ask.conversations.Invoke -import com.amazon.alexa.ask.conversations.Notify -import com.amazon.alexa.ask.conversations.expect -import com.amazon.alexa.ask.conversations.response -import com.amazon.alexa.schema.Nothing -import com.weatherbot.apis.secondEarthAPI -import com.weatherbot.utteracesets.delegateToSkill -import prompts.secondEarthAPI_apla -import slotTypes.* -import prompts.* -import displays.* -import com.weatherbot.utteracesets.* -import com.amazon.alexa.ask.conversations.* -import com.amazon.alexa.schema.* -import com.weatherbot.types.* -dialog Nothing testTwo() { - sample { - expect( - act = Invoke, - event = delegateToSkill - ) - secondEarthAPI() - response( - response = secondEarthAPI_apla, - act = Notify { - actionName = secondEarthAPI - }, - nextAct = nothing - ) - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/conversations/dialogWeather.acdl b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/conversations/dialogWeather.acdl deleted file mode 100644 index 60962dc9..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/conversations/dialogWeather.acdl +++ /dev/null @@ -1,9 +0,0 @@ -namespace dialogWeather - -import com.amazon.ask.types.builtins.AMAZON.DATE -import slotTypes.customCity - -type payloadConfirmArgsDialogWeather { - optional customCity cityName - optional DATE date -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/conversations/listDialogWithConditions.acdl b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/conversations/listDialogWithConditions.acdl deleted file mode 100644 index a421edfa..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/conversations/listDialogWithConditions.acdl +++ /dev/null @@ -1,243 +0,0 @@ -namespace listDialog - -import com.amazon.alexa.ask.conversations.Affirm -import com.amazon.alexa.ask.conversations.ConfirmAction -import com.amazon.alexa.ask.conversations.ConfirmArgs -import com.amazon.alexa.ask.conversations.Inform -import com.amazon.alexa.ask.conversations.Invoke -import com.amazon.alexa.ask.conversations.Notify -import com.amazon.alexa.ask.conversations.Request -import com.amazon.alexa.ask.conversations.received -import com.amazon.alexa.ask.conversations.confirmAction - -import com.amazon.alexa.ask.conversations.expect -import com.amazon.alexa.ask.conversations.response -import com.amazon.alexa.ask.conversations.size -import com.amazon.alexa.ask.conversations.utterances -import com.amazon.alexa.schema.List -import com.amazon.alexa.schema.String -import com.amazon.alexa.schema.Nothing -import com.amazon.ask.types.builtins.AMAZON.Food -import com.amazon.ask.types.builtins.AMAZON.NUMBER -import com.weatherbot.apis.* -import com.weatherbot.apis.fruitNameAPI -import com.weatherbot.apis.numberOfVisits -import com.weatherbot.types.result -import com.weatherbot.utteracesets.GiveMeTodaySpecialsEvent -import com.weatherbot.utteracesets.affirmCookAPIEvent -import com.weatherbot.utteracesets.affirmFruitAPIEvent -import com.weatherbot.utteracesets.cookWithTwoIngredientsEvent -import com.weatherbot.utteracesets.getFruitPriceEvent -import com.weatherbot.utteracesets.informFoodNameEvent -import com.weatherbot.utteracesets.informfruitNameEvent -import prompts.SuccessGiveMeTodaySpecialsEvent_apla -import prompts.confirm_fruitName_apla -import prompts.confirm_main_addon_list_apla -import prompts.requestArgs_request_fruitName_apla -import prompts.request_listAddOns_apla -import prompts.request_mainFoodName_apla -import prompts.success_cookingAPI_apla -import prompts.success_fruitPriceAPI_apla -import slotTypes.orderStatus -import slotTypes.* -import prompts.* -import displays.* -import com.weatherbot.utteracesets.* -import com.amazon.alexa.ask.conversations.* -import com.amazon.alexa.schema.* -import com.weatherbot.types.* -type addOnShell { - List addOn -} - -action orderStatus cookingAPI(Food foodName, List addOn) - -action List todaySpecials() - -informlistAddOnsEvent = utterances( - samples = [ - "{addOn}", - "add {addOn}", - "mix {addOn}" - ] -) - -type payloadStatuscookWithTwoIngredients { - orderStatus status -} - -type payloadGiveMeTodaySpecials { - List result -} - -type payloadgetFruitPriceEvent { - result result -} - -type payloadConfirmActionComplex { - optional Food foodName - List addOn -} - -type paylaodCompleFruit { - Food fruitName -} - -type WrongpayloadGiveMeTodaySpecialsNew { - List ListOfMix1 - Mix Mix1 -} - -type payloadGiveMeTodaySpecialsNew { - List ListOfMix1 -} - - -type InteractionFoodName { - Food foodName -} - - -interaction { - received(Invoke,"let us cook") - response(response = request_listAddOns_apla,act = Request { arguments = [ cookingAPI.arguments.addOn ]}) - actual { - listAddOnsEventOneName = received(Inform, "{bread|ListOfMix1} and {jam|Mix1}") - } expected { - listAddOnsEventOne = received(Inform, "{bread|ListOfMix1} and {jam|ListOfMix1}") - } - response(response = request_mainFoodName_apla,act = Request { arguments = [ cookingAPI.arguments.foodName ]}) - FoodNameEventInte = received(Inform,"{cake|foodName}") - response(response = confirm_main_addon_list_apla,act = ConfirmAction { actionName = cookingAPI}, - payload = payloadConfirmActionComplex { foodName = FoodNameEventInte.foodName, addOn = listAddOnsEventOne.ListOfMix1}) - received(Affirm,"ok for sure") - resultOneInteList = cookingAPI(foodName = FoodNameEventInte.foodName,addOn = listAddOnsEventOne.ListOfMix1) - response(response = success_cookingAPI_apla,act = Notify { actionName = cookingAPI}, - payload = payloadStatuscookWithTwoIngredients { status = resultOneInteList}) -} - - -dialog Nothing complex() { - sample { - expect(act = Invoke,event = cookWithTwoIngredientsEvent) - response(response = request_listAddOns_apla,act = Request { arguments = [ cookingAPI.arguments.addOn ]}) - - listAddOnsEvent = expect(act = Inform,event = informlistAddOnsEvent) - response(response = request_mainFoodName_apla,act = Request { arguments = [ cookingAPI.arguments.foodName ]}) - - FoodNameEvent = expect(act = Inform,event = informFoodNameEvent) - - - response(response = confirm_main_addon_list_apla,act = ConfirmAction { actionName = cookingAPI},payload = payloadConfirmActionComplex { foodName = FoodNameEvent.foodName, addOn = listAddOnsEvent.addOn}) - // ok for sure - expect(act = Affirm,event = affirmCookAPIEvent) - - resultOne = cookingAPI(foodName = FoodNameEvent.foodName,addOn = listAddOnsEvent.addOn) - - response(response = success_cookingAPI_apla,act = Notify { actionName = cookingAPI}, - payload = payloadStatuscookWithTwoIngredients { status = resultOne}) - } - - - - - - - - sample { - expect(act = Invoke,event = GiveMeTodaySpecialsEvent) - numberOfVisits() - resultOne = todaySpecials() - if (com.amazon.alexa.ask.conversations.size(list = resultOne) == 1) { - response(response = SuccessGiveMeTodaySpecialsEvent_apla, act = Notify { actionName = todaySpecials }, payload = payloadGiveMeTodaySpecials { result = resultOne }) - } - } - - - - - - sample { - // "content": "what is the price of the fruit" - expect(act = Invoke,event = getFruitPriceEvent) - response(response = requestArgs_request_fruitName_apla,act = Request { arguments = [ fruitNameAPI.arguments.fruitName ]}) - // "content": "fruit name is apple" - fruitNameEvent = expect(act = Inform,event = informfruitNameEvent) - //response(response = confirm_fruitName_apla, act = ConfirmArgs { arguments = [fruitNameAPI.arguments.fruitName]},payload = paylaodCompleFruit { fruitName = fruitNameEvent.fruitName}) - - // expect(act = Affirm,event = affirmFruitAPIEvent) - resultOne = fruitNameAPI(fruitName = fruitNameEvent.fruitName) - // resposne1() - response(response = success_fruitPriceAPI_apla,act = Notify { actionName = fruitNameAPI},payload = payloadgetFruitPriceEvent { result = resultOne}) - - } -} - - - - - /* -type fruitEvent0 { - Food fruitName -} - -interaction { - actual { - fruitNameEvent1 = received(Inform, "fruit name is {apple|fruitName}") - resultOneTwo = fruitNameAPI(fruitName = fruitNameEvent1.fruitName) - response(response = success_fruitPriceAPI_apla,act = Notify { actionName = fruitNameAPI},payload = payloadgetFruitPriceEvent { result = resultOneTwo}) - } expected { - fruitNameEvent1 = received(Inform, "fruit name is {apple|fruitName}") - resultOne = todaySpecials() - if (com.amazon.alexa.ask.conversations.size(list = resultOne) == 1) { - response(response = SuccessGiveMeTodaySpecialsEvent_apla, act = Notify { actionName = todaySpecials }, payload = payloadGiveMeTodaySpecials { result = resultOne }) - } - } - } - -interaction { - - actual { - - - fruitNameEvent1 = received(Inform, "fruit name is {apple|fruitName}") - resultOneTwo = fruitNameAPI(fruitName = fruitNameEvent1.fruitName) - response(response = success_fruitPriceAPI_apla,act = Notify { actionName = fruitNameAPI},payload = payloadgetFruitPriceEvent { result = resultOneTwo}) - } expected { - fruitNameEvent1 = received(Inform, "fruit name is {apple|fruitName}") - } - - } - - - - - - - - - - - -interaction { - -actual { - - - fruitNameEvent1 = received(Inform, "fruit name is {apple|fruitName}") - response(response = confirm_fruitName_apla,act = ConfirmArgs { arguments = [ fruitNameAPI.arguments.fruitName ]}, - payload = paylaodCompleFruit { fruitName = fruitNameEvent1.fruitName}) - - } expected { - fruitNameEvent1 = received(Inform, "fruit name is {apple|fruitName}") - response(response = request_mainFoodName_apla, act = ConfirmAction { actionName = fruitNameAPI} , - payload = paylaodCompleFruit { fruitName = fruitNameEvent1.fruitName}) - } - -} -*/ - - - - - \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/conversations/optionalDelegate.acdl b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/conversations/optionalDelegate.acdl deleted file mode 100644 index d69ecd3d..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/conversations/optionalDelegate.acdl +++ /dev/null @@ -1,118 +0,0 @@ -namespace optionalArgACDL - -import com.amazon.alexa.ask.conversations.Affirm -import com.amazon.alexa.ask.conversations.ConfirmArgs -import com.amazon.alexa.ask.conversations.Inform -import com.amazon.alexa.ask.conversations.Invoke -import com.amazon.alexa.ask.conversations.MultiModalResponse -import com.amazon.alexa.ask.conversations.Notify -import com.amazon.alexa.ask.conversations.Request -import com.amazon.alexa.ask.conversations.expect -import com.amazon.alexa.ask.conversations.response -import com.amazon.alexa.schema.Nothing -import com.amazon.alexa.schema.Thing -import com.weatherbot.apis.favColorSign_Name -import com.weatherbot.types.payloadConfirmActionConditionComplex -import com.weatherbot.types.result_one -import com.weatherbot.utteracesets.affirmFavColorEvent - -import com.weatherbot.utteracesets.informComplexNameEvent -import prompts.request_name_apla -import prompts.success_favColorSign_Name_apla -import slotTypes.complexNames -import slotTypes.* -import prompts.* -import displays.* -import com.weatherbot.utteracesets.* -import com.amazon.alexa.ask.conversations.* -import com.amazon.alexa.schema.* -import com.weatherbot.types.* -type payloadResult_optional { - result_one result -} - -type payloadResult_optional_name { - complexNames name -} - - - -// 1. New Prompt we cant map (Not used within any samples)) -// 2. New DialogACtType alone we cant map , should be done with apla prompts -// 3. WE can make use of an exisitng apla prompt and change type -> Shoudl be . -// 4. Payload Can be changed - - -getFavColorEvent = utterances( - samples = [ - "what is my favourite color", - "tell my favourite color" - ] -) - - -getFavColorEventTwo = utterances( - samples = [ - "guess the color" - ] -) - - -dialog Nothing optiOnal() { - sample { - expect(act = Invoke,event = getFavColorEvent) - response(act = Request { arguments = [ favColorSign_Name.arguments.name ]},response = MultiModalResponse { apla = request_name_apla}) - - ComplexNameEvent = expect(act = Inform,event = informComplexNameEvent) - response(response = confirmArgs_complexNames_apla, act = ConfirmArgs { arguments = [ favColorSign_Name.arguments.name ]}, - payload = payloadConfirmActionConditionComplex { name = ComplexNameEvent.name}) - - expect(act = Affirm,event = affirmFavColorEvent) - resultOne = favColorSign_Name(name = ComplexNameEvent.name) - response(response = success_favColorSign_Name_apla,act = Notify { actionName = favColorSign_Name}, - payload = payloadResult_optional { result = resultOne}) - } -} - -type PAYLOAD_TYPE01 { complexNames name} - -dialog Nothing optiOnalTwo() { - sample { - expect(act = Invoke,event = getFavColorEventTwo) - response(act = Request { arguments = [ favColorSign_Name.arguments.name ]},response = MultiModalResponse { apla = request_name_apla}) - - ComplexNameEvent = expect(act = Inform,event = informComplexNameEvent) - response(response = confirmAction_complexNames_apla, act = ConfirmAction {actionName = favColorSign_Name}, payload = payloadConfirmActionConditionComplex { name = ComplexNameEvent.name}) - - expect(act = Affirm,event = affirmFavColorEvent) - result1 = favColorSign_Name(name = ComplexNameEvent.name) - response(response = success_favColorSign_Name_apla,act = Notify { actionName = favColorSign_Name}, payload = payloadResult_optional { result = result1}) - } -} - - - -//com.amazon.alexa.ask.conversations.response( response = confirmArgs_complexNames_apla, act = com.amazon.alexa.ask.conversations.ConfirmArgs {arguments = [com.weatherbot.apis.favColorSign_Name.arguments.name ]}, surfaceForm = "confirm Action your cool name satheesh and ?", payload = PAYLOAD_TYPE1{name = Var1.complexNames1}) - -/* -com.amazon.alexa.ask.conversations.response( response = confirmArgs_complexNames_apla, act = com.amazon.alexa.ask.conversations.ConfirmArgs { arguments = [com.weatherbot.apis.favColorSign_Name.arguments.name ]}, surfaceForm = "", payload = PAYLOAD_TYPE0{complexNames = Var0.complexNames1}) - -com.amazon.alexa.ask.conversations.response( response = confirmArgs_complexNames_apla, act = com.amazon.alexa.ask.conversations.ConfirmArgs { arguments = [ favColorSign_Name.arguments.name ]}, surfaceForm = "", payload = Type0( complexNames = Var0.complexNames1 )) - -type nameShellInteract { - complexNames name -} -interaction { - actual { - ComplexNameEvent1 = received(Inform, "name is {satheesh|name}") - response(response = confirmAction_complexNames_apla, act = ConfirmAction {actionName = favColorSign_Name}, - payload = payloadConfirmActionConditionComplex { name = ComplexNameEvent1.name}) - } expected { - ComplexNameEvent1 = received(Inform, "name is {satheesh|name}") - response(response = confirmArgs_complexNames_apla, act = ConfirmArgs { arguments = [ favColorSign_Name.arguments.name ]}, - payload = payloadConfirmActionConditionComplex { name = ComplexNameEvent1.name}) - } - } - -*/ - \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/conversations/pizza.acdl b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/conversations/pizza.acdl deleted file mode 100644 index d00a6c87..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/conversations/pizza.acdl +++ /dev/null @@ -1,189 +0,0 @@ -namespace pizzaAcdl - -import com.amazon.alexa.ask.conversations.Affirm -import com.amazon.alexa.ask.conversations.ConfirmAction -import com.amazon.alexa.ask.conversations.ConfirmArgs -import com.amazon.alexa.ask.conversations.Inform -import com.amazon.alexa.ask.conversations.Invoke -import com.amazon.alexa.ask.conversations.MultiModalResponse -import com.amazon.alexa.ask.conversations.Notify -import com.amazon.alexa.ask.conversations.Request -import com.amazon.alexa.ask.conversations.RequestArguments -import com.amazon.alexa.ask.conversations.ensure -import com.amazon.alexa.ask.conversations.expect -import com.amazon.alexa.ask.conversations.response -import com.amazon.alexa.schema.Nothing -import com.amazon.alexa.schema.Thing -import com.weatherbot.apis.OrderTwoToppingPizza -import com.weatherbot.types.PAYLOAD_TYPE6 -import com.weatherbot.types.PAYLOAD_TYPE7 -import com.weatherbot.types.PAYLOAD_TYPE88 -import com.weatherbot.types.PAYLOAD_TYPE9 -import com.weatherbot.utteracesets.Yes -import com.weatherbot.utteracesets.specifyCrust -import com.weatherbot.utteracesets.specifySize -import com.weatherbot.utteracesets.specifyTwoToppings -import com.weatherbot.utteracesets.startTwoToppingPizzaOrder -import prompts.askForCrustPrompts -import prompts.askForSizePrompts -import prompts.askForToppingOnePrompt -import prompts.askForToppingTwoPrompt -import prompts.askForTwoToppingsPrompts -import prompts.confirmSizePrompt -import prompts.confirmTwoToppingOrderPromptcopy -import prompts.confirmTwoToppingsPrompt -import prompts.twoToppingOrderSuccessPrompt -import slotTypes.* -import prompts.* -import displays.* -import com.weatherbot.utteracesets.* -import com.amazon.alexa.ask.conversations.* -import com.amazon.alexa.schema.* -import com.weatherbot.types.* -dialog Nothing orderTwoToppingPizza() { - sample { - expect( - act = Invoke, - event = startTwoToppingPizzaOrder - ) - ensure( - requestArgs = [ - RequestArguments { - arguments = [ - OrderTwoToppingPizza.arguments.first_topping - ], - response = MultiModalResponse { - apla = askForToppingOnePrompt - } - } - ] - ) - ensure( - requestArgs = [ - RequestArguments { - arguments = [ - OrderTwoToppingPizza.arguments.second_topping - ], - response = MultiModalResponse { - apla = askForToppingTwoPrompt - } - } - ] - ) - response( - act = Request { - arguments = [ - OrderTwoToppingPizza.arguments.size - ] - }, - response = MultiModalResponse { - apla = askForSizePrompts - } - ) - specifySizeRequest = expect( - act = Inform, - event = specifySize - ) - response( - act = ConfirmArgs { - arguments = [ - OrderTwoToppingPizza.arguments.size - ] - }, - payload = PAYLOAD_TYPE6 { - size = specifySizeRequest.size - }, - response = MultiModalResponse { - apla = confirmSizePrompt - } - ) - expect( - act = Affirm, - event = Yes - ) - response( - act = Request { - arguments = [ - OrderTwoToppingPizza.arguments.crust - ] - }, - response = MultiModalResponse { - apla = askForCrustPrompts - } - ) - specifyCrustRequest = expect( - act = Inform, - event = specifyCrust - ) - response( - act = Request { - arguments = [ - OrderTwoToppingPizza.arguments.first_topping, - OrderTwoToppingPizza.arguments.second_topping - ] - }, - response = MultiModalResponse { - apla = askForTwoToppingsPrompts - } - ) - specifyTwoToppingsRequest = expect( - act = Inform, - event = specifyTwoToppings - ) - response( - act = ConfirmArgs { - arguments = [ - OrderTwoToppingPizza.arguments.first_topping, - OrderTwoToppingPizza.arguments.second_topping - ] - }, - payload = PAYLOAD_TYPE7 { - second_topping = specifyTwoToppingsRequest.second_topping, - first_topping = specifyTwoToppingsRequest.first_topping - }, - response = MultiModalResponse { - apla = confirmTwoToppingsPrompt - } - ) - expect( - act = Affirm, - event = Yes - ) - response( - act = ConfirmAction { - actionName = OrderTwoToppingPizza - }, - payload = PAYLOAD_TYPE88 { - size = specifySizeRequest.size, - second_topping = specifyTwoToppingsRequest.second_topping, - first_topping = specifyTwoToppingsRequest.first_topping, - crust = specifyCrustRequest.crust - }, - response = MultiModalResponse { - apla = confirmTwoToppingOrderPromptcopy - } - ) - expect( - act = Affirm, - event = Yes - ) - stringLiteral1 = OrderTwoToppingPizza( - size = specifySizeRequest.size, - second_topping = specifyTwoToppingsRequest.second_topping, - first_topping = specifyTwoToppingsRequest.first_topping, - crust = specifyCrustRequest.crust - ) - response( - act = Notify { - success = true, - actionName = OrderTwoToppingPizza - }, - payload = PAYLOAD_TYPE9 { - speech = stringLiteral1 - }, - response = MultiModalResponse { - apla = twoToppingOrderSuccessPrompt - } - ) - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/conversations/soaDialog.acdl b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/conversations/soaDialog.acdl deleted file mode 100644 index a09e5124..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/conversations/soaDialog.acdl +++ /dev/null @@ -1,50 +0,0 @@ -namespace soaACDl - -import com.amazon.alexa.ask.conversations.Affirm -import com.amazon.alexa.ask.conversations.ConfirmArgs -import com.amazon.alexa.ask.conversations.Inform -import com.amazon.alexa.ask.conversations.Invoke -import com.amazon.alexa.ask.conversations.Notify -import com.amazon.alexa.ask.conversations.Request -import com.amazon.alexa.ask.conversations.expect -import com.amazon.alexa.ask.conversations.response -import com.amazon.alexa.schema.Nothing -import com.amazon.ask.types.builtins.AMAZON.Color -import com.weatherbot.apis.colorFruitName -import com.weatherbot.apis.fruitNameAPI -import com.weatherbot.types.result -import com.weatherbot.utteracesets.MultipleDialogEvent -import com.weatherbot.utteracesets.affirmMultipleColorEvent -import com.weatherbot.utteracesets.informColorMultipleEvent -import prompts.confirm_color_for_fruit_apla -import prompts.request_colorName_multiple_apla -import prompts.success_fruitPriceAPI_apla -import slotTypes.* -import prompts.* -import displays.* -import com.weatherbot.utteracesets.* -import com.amazon.alexa.ask.conversations.* -import com.amazon.alexa.schema.* -import com.weatherbot.types.* - -type payloadMultipleDialogEvent { - result result -} - -type payloadsOAConfirmArgs { - Color colorName -} - -dialog Nothing sOA() { - sample { - // "i want to buy a fruit" - expect(act = Invoke,event = MultipleDialogEvent) - response(response = request_colorName_multiple_apla,act = Request { arguments = [ colorFruitName.arguments.colorName ]}) - colorEvent = expect(act = Inform,event = informColorMultipleEvent) - response(response = confirm_color_for_fruit_apla,act = ConfirmArgs { arguments = [ colorFruitName.arguments.colorName ]},payload = payloadsOAConfirmArgs { colorName = colorEvent.colorName}) - expect(act = Affirm,event = affirmMultipleColorEvent) - resultEvent = colorFruitName(colorName = colorEvent.colorName) - resultOne = fruitNameAPI(fruitName = resultEvent.fruitName) - response(response = success_fruitPriceAPI_apla,act = Notify { actionName = fruitNameAPI},payload = payloadMultipleDialogEvent { result = resultOne}) - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/conversations/types.acdl b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/conversations/types.acdl deleted file mode 100644 index 057115d1..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/conversations/types.acdl +++ /dev/null @@ -1,248 +0,0 @@ -namespace com.weatherbot.types - -import com.amazon.alexa.schema.List -import com.amazon.ask.types.builtins.AMAZON.Color -import com.amazon.ask.types.builtins.AMAZON.DATE -import com.amazon.ask.types.builtins.AMAZON.Food -import com.amazon.ask.types.builtins.AMAZON.NUMBER -import slotTypes.Mix -import slotTypes.StringLiteral -import slotTypes.cheese -import slotTypes.city_name_one -import slotTypes.city_name_two -import slotTypes.complexNames -import slotTypes.crust -import slotTypes.customCity -import slotTypes.option -import slotTypes.orderStatus -import slotTypes.pickUpFrom -import slotTypes.signs -import slotTypes.size -import slotTypes.specialPizzaName -import slotTypes.toppings - -type customCityShell { - customCity cityName -} - -type signShell { - signs sign -} - -type dateValue { - DATE date -} - -type WeatherResult { - customCity cityName - NUMBER highTemp - NUMBER lowTemp - optional List itemsToUse -} - -type resultthree { - Food fruitName - Color colorName -} - -type result { - Food fruitName - NUMBER price -} - -type fruitNameShell { - Food fruitName -} - -type foodNameShell { - Food foodName -} - -type CityDateShell { - optional customCity cityName - optional DATE date -} - -type nameShell { - complexNames name -} - -type colorNameShell { - Color colorName -} - -type result_one { - Color colorName - complexNames name - signs sign -} - -type sourceShell { - city_name_one source -} - -type destinationShell { - city_name_two destination -} - -type pickUpFromShell { - pickUpFrom pickUpFrom -} - -type dropToShell { - city_name_one dropTo -} - -type bookedFlightResult { - city_name_two destination - city_name_one source - orderStatus orderStatus -} - -type bookCabResult { - pickUpFrom pickUpFrom - city_name_one dropTo - orderStatus orderStatus -} - -type ResponsePayload { - WeatherResult weatherResult -} - -type payloadConfirmActionConditionComplex { - optional complexNames name - optional signs sign -} - -type Response_Payload_one { - optional customCity cityName - optional DATE date -} - -type inform_menu_optionRequestType { - option option -} - -type specifySpecialNameRequestType { - specialPizzaName name -} - -type askMenuQuestionRequestType { - option option -} - -type specifySizeAndToppingsRequestType { - size size - List toppings -} - -type orderSpecificSizePizzaRequestType { - size size -} - -type specifyQtyRequestType { - NUMBER qty -} - -type customizePizzaReferenceSpecialRequestType { - specialPizzaName name -} - -type specifyTwoToppingsRequestType { - toppings second_topping - toppings first_topping -} - -type inquireAboutFeedingSizeRequestType { - size size -} - -type specifyToppingsRequestType { - List toppingsList -} - -type specifySizeRequestType { - size size -} - -type specifyCrustRequestType { - crust crust -} - -type specifyCheeseRequestType { - cheese cheese -} - -type pizza { - size size - List toppingsList - crust crust - cheese cheese -} - -type special { - pizza pizza - NUMBER cost - NUMBER qty - specialPizzaName name -} - -type PAYLOAD_TYPE0 { - size size - StringLiteral prompt -} - -type PAYLOAD_TYPE1 { - size size - List toppingsList - crust crust - cheese cheese -} - -type PAYLOAD_TYPE2 { - pizza pizza -} - -type PAYLOAD_TYPE3 { - size size - List toppingsList - crust crust - cheese cheese -} - -type PAYLOAD_TYPE4 { - pizza pizza -} - -type PAYLOAD_TYPE5 { - size size - StringLiteral prompt -} - -type PAYLOAD_TYPE6 { - size size -} - -type PAYLOAD_TYPE7 { - toppings second_topping - toppings first_topping -} - -type PAYLOAD_TYPE88 { - toppings second_topping - toppings first_topping - crust crust - optional size size -} - -type PAYLOAD_TYPE9 { - StringLiteral speech -} - -type PAYLOAD_TYPE10 { - StringLiteral optionResponse -} - -type PAYLOAD_TYPE11 { - StringLiteral optionResponse -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/conversations/utteracesets.acdl b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/conversations/utteracesets.acdl deleted file mode 100644 index db46e06f..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/conversations/utteracesets.acdl +++ /dev/null @@ -1,435 +0,0 @@ -namespace com.weatherbot.utteracesets - -import com.amazon.alexa.ask.conversations.utterances -import com.weatherbot.types.CityDateShell -import com.weatherbot.types.askMenuQuestionRequestType -import com.weatherbot.types.colorNameShell -import com.weatherbot.types.customCityShell -import com.weatherbot.types.customizePizzaReferenceSpecialRequestType -import com.weatherbot.types.dateValue -import com.weatherbot.types.destinationShell -import com.weatherbot.types.dropToShell -import com.weatherbot.types.foodNameShell -import com.weatherbot.types.fruitNameShell -import com.weatherbot.types.inform_menu_optionRequestType -import com.weatherbot.types.inquireAboutFeedingSizeRequestType -import com.weatherbot.types.nameShell -import com.weatherbot.types.orderSpecificSizePizzaRequestType -import com.weatherbot.types.pickUpFromShell -import com.weatherbot.types.signShell -import com.weatherbot.types.sourceShell -import com.weatherbot.types.specifyCheeseRequestType -import com.weatherbot.types.specifyCrustRequestType -import com.weatherbot.types.specifyQtyRequestType -import com.weatherbot.types.specifySizeAndToppingsRequestType -import com.weatherbot.types.specifySizeRequestType -import com.weatherbot.types.specifySpecialNameRequestType -import com.weatherbot.types.specifyToppingsRequestType -import com.weatherbot.types.specifyTwoToppingsRequestType - -values = [ - "what is the weather", - "what's the weather", - "tell me the weather" -] - -getWeatherEventNoArgs = utterances( - samples = values -) - -getWeatherEventArgs = utterances( - samples = [ - "tell me the weather in {cityName} {date}", - "how is the weather in {cityName} {date}" - ] -) - -getWeatherEvent = utterances( - samples = [ - "What's the weather {date} in {cityName}", - "what is the weather {date}", - "How is the weather {date}", - "How is weather in {cityName} {date}", - "how is weather", - "can you please give me weather report for {date}" - ] -) - -informCityEvent = utterances( - samples = [ - "{cityName}", - "city is {cityName}", - "city name is {cityName}" - ] -) - -informDateEvent = utterances( - samples = [ - "date is {date}", - "for {date}", - "{date}" - ] -) - -affirmWeatherEvent = utterances( - samples = [ - "yes", - "yeah" - ] -) - -delegateToSkill = utterances( - samples = [ - "get me to paradise", - "take me to paradise" - ] -) - -cookWithTwoIngredientsEvent = utterances( - samples = [ - "let us cook", - "start cooking", - "cook with two ingredients", - "cook two ingredients", - "switch to coltrane", - "hit coltrane", - "make coltrane DM" - ] -) - -welcome = utterances( - samples = [ - "get me car" - ] -) - -affirmMultipleColorEvent = utterances( - samples = [ - "do it" - ] -) - -informfruitNameEvent = utterances( - samples = [ - "{fruitName}", - "fruit name is {fruitName}", - "fruit is {fruitName}" - ] -) - -MultipleDialogEvent = utterances( - samples = [ - "i want to buy a fruit" - ] -) - -informColorMultipleEvent = utterances( - samples = [ - "{colorName}", - "color is {colorName}", - "color {colorName}" - ] -) - -informFoodNameEvent = utterances( - samples = [ - "{foodName}", - "food is {foodName}", - "let us make {foodName}" - ] -) - -affirmFruitAPIEvent = utterances( - samples = [ - "uh huh", - "yup" - ] -) - -affirmCookAPIEvent = utterances( - samples = [ - "ok", - "that is ok", - "ok for sure" - ] -) - -GiveMeTodaySpecialsEvent = utterances( - samples = [ - "give me today specials", - "what is special today" - ] -) - -getFruitPriceEvent = utterances( - samples = [ - "what is the price of the fruit", - "what is the price of fruit" - ] -) - - - -informsignEvent = utterances( - samples = [ - "{sign}", - "sign is {sign}", - "sun sign is {sign}" - ] -) - -informComplexNameEvent = utterances( - samples = [ - "{name}", - "name is {name}", - "i am {name}" - ] -) - -affirmFavColorEvent = utterances( - samples = [ - "correct" - ] -) - -bookFlightEvent = utterances( - samples = [ - "book a flight", - "book flight" - ] -) - -informFromBookFlight = utterances( - samples = [ - "from {source}", - "travel from {source}", - "source is {source}" - ] -) - -informToBookFlight = utterances( - samples = [ - "to {destination}", - "trave to {destination}", - "go to {destination}", - "destination to {destination}" - ] -) - -affirmCabAPIEvent = utterances( - samples = [ - "sure do", - "sure please do", - "roger", - "indeed" - ] -) - -informPickUpFromBookCab = utterances( - samples = [ - "{pickUpFrom}" - ] -) - -informdropToBookCab = utterances( - samples = [ - "{dropTo}" - ] -) - -inform_menu_option = utterances( - samples = [ - "{option}" - ] -) - -menuOptionsQuestion = utterances( - samples = [ - "what options can I change?", - "what kinds of options are there?" - ] -) - -inquireAboutFeedingSizeNoArgs = utterances( - samples = [ - "how many people does that feed", - "Is that enough for two adults and two kids" - ] -) - -specifySpecialName = utterances( - samples = [ - "{name}" - ] -) - -askMenuQuestion = utterances( - samples = [ - "what are your {option}", - "what {option} can i get", - "what types of {option} do you have", - "What kind of {option} do you have" - ] -) - -specifySizeAndToppings = utterances( - samples = [ - "add a {size} {toppings} pizza to my order", - "order a {size} {toppings} pizza", - "I want a {size} {toppings} pizza" - ] -) - -orderSpecificSizePizza = utterances( - samples = [ - "order a {size} pizza", - "I want a {size} pizza" - ] -) - -DummyInvokeOrderCustomizedPizzaReferenceSpecial = utterances( - samples = [ - "dummy invoke needed when offer API is used in NotifySuccess request template + OfferAPI for OrderCustomizedPizzaReferenceSpecial" - ] -) - -startCustomizeFlow = utterances( - samples = [ - "I want to customize a special" - ] -) - -confirmCustomizedSpecial = utterances( - samples = [ - "sounds good", - "perfect", - "go ahead", - "sure", - "yeah", - "ok", - "yep" - ] -) - -specifyQty = utterances( - samples = [ - "{qty} please", - "{qty}", - "give me {qty}", - "I will take {qty}", - "I want {qty}" - ] -) - -customizePizzaReferenceSpecial = utterances( - samples = [ - "let's customize the {name}", - "I want to customize the {name}" - ] -) - -specifyTwoToppings = utterances( - samples = [ - "no, make it {first_topping} and {second_topping}", - "no, {first_topping} and {second_topping}", - "actually make that {first_topping} and {second_topping}", - "change that to {first_topping} and {second_topping}", - "{first_topping} and {second_topping}", - "add {first_topping} and {second_topping}", - "I want {first_topping} and {second_topping}" - ] -) - -Yes = utterances( - samples = [ - "Correct", - "Uh huh", - "Right", - "Yep", - "Yes" - ] -) - -inquireAboutFeedingSize = utterances( - samples = [ - "is a {size} enough for four adults", - "how many people can a {size} feed", - "how many people can {size} pizza feed?" - ] -) - -tested = utterances( - samples = [ - "launch skill" - ] -) - -startTwoToppingPizzaOrder = utterances( - samples = [ - "order a two topping pizza", - "I want a two topping pizza" - ] -) - -specifyToppings = utterances( - samples = [ - "{toppingsList}", - "I'd like {toppingsList}", - "give me {toppingsList}", - "we like {toppingsList}", - "The kids want {toppingsList}" - ] -) - -startPizzaOrder = utterances( - samples = [ - "build my own pizza", - "I need my own custom pizza", - "Add one more order", - "I want another pizza", - "build another pizza", - "create another pizza", - "build a pizza", - "place an order for a pizza", - "add another pizza to my order", - "add another custom pizza to my order", - "create a custom pizza", - "start my pizza order", - "order me a custom pizza", - "order a pizza" - ] -) - -specifySize = utterances( - samples = [ - "change it to {size}", - "make that a {size}", - "change that to a {size} pizza", - "{size}", - "I need a {size} pizza" - ] -) - -specifyCrust = utterances( - samples = [ - "{crust}", - "I need {crust}" - ] -) - -specifyCheese = utterances( - samples = [ - "{cheese}", - "I need {cheese}", - "Please add {cheese}" - ] -) - -confirmPizzaOrder = utterances( - samples = [ - "yes", - "yup", - "go ahead", - "perfect" - ] -) diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/conversations/welcomeAPI.acdl b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/conversations/welcomeAPI.acdl deleted file mode 100644 index 26b5fc36..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/conversations/welcomeAPI.acdl +++ /dev/null @@ -1,38 +0,0 @@ -namespace welcomeAPi - -import com.amazon.alexa.ask.conversations.Invoke -import com.amazon.alexa.ask.conversations.Notify -import com.amazon.alexa.ask.conversations.expect -import com.amazon.alexa.ask.conversations.response -import com.amazon.alexa.schema.Nothing -import com.amazon.ask.types.builtins.AMAZON.NUMBER -import com.weatherbot.apis.welcomeApi -import com.weatherbot.utteracesets.welcome -import prompts.welcome_apla_custom -import slotTypes.* -import prompts.* -import displays.* -import com.weatherbot.utteracesets.* -import com.amazon.alexa.ask.conversations.* -import com.amazon.alexa.schema.* -import com.weatherbot.types.* - -type welcomeApiPayloads { - NUMBER result -} - -dialog Nothing complex() { - sample { - expect( - act = Invoke, - event = com.weatherbot.utteracesets.welcome - ) - resultDam = welcomeApi() - response( - response = welcome_apla_custom, - act = Notify { - actionName = welcomeApi - } - ) - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/interactionModels/custom/en-US.json b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/interactionModels/custom/en-US.json deleted file mode 100644 index 91c60c47..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/interactionModels/custom/en-US.json +++ /dev/null @@ -1,527 +0,0 @@ -{ - "interactionModel": { - "languageModel": { - "invocationName": "serious master test skill", - "intents": [ - { - "name": "AMAZON.CancelIntent", - "samples": [] - }, - { - "name": "AMAZON.HelpIntent", - "samples": [] - }, - { - "name": "AMAZON.StopIntent", - "samples": [] - }, - { - "name": "NoDialog", - "samples": ["show me the wonders"] - }, - { - "name": "test", - "samples": ["nanum rowdy dhann"] - }, - { - "name": "SkillToColtrane", - "samples": ["switch to coltrane", "hit coltrane", "make coltrane DM"] - }, - { - "name": "AMAZON.NavigateHomeIntent", - "samples": [] - }, - { - "name": "AMAZON.FallbackIntent", - "samples": [] - } - ], - "types": [ - { - "values": [ - { - "name": { - "value": "satheesh" - } - }, - { - "name": { - "value": "raman" - } - } - ], - "name": "request_city_apl_displaya" - }, - { - "values": [ - { - "name": { - "value": "satheesh" - } - }, - { - "name": { - "value": "raman" - } - } - ], - "name": "complexNames" - }, - { - "values": [ - { - "name": { - "value": "scorpion" - } - }, - { - "name": { - "value": "aeries" - } - }, - { - "name": { - "value": "virgo" - } - }, - { - "name": { - "value": "cancer" - } - } - ], - "name": "signs" - }, - { - "values": [ - { - "name": { - "value": "almonds" - } - }, - { - "name": { - "value": "bread" - } - }, - { - "name": { - "value": "egg" - } - }, - { - "name": { - "value": "sauce" - } - }, - { - "name": { - "value": "jam" - } - }, - { - "name": { - "value": "cheese" - } - } - ], - "name": "Mix" - }, - { - "values": [ - { - "name": { - "value": "small" - } - }, - { - "name": { - "value": "medium" - } - }, - { - "name": { - "value": "large" - } - }, - { - "name": { - "value": "extra large" - } - } - ], - "name": "size" - }, - { - "values": [ - { - "name": { - "value": "guindy" - } - }, - { - "name": { - "value": "paris" - } - }, - { - "name": { - "value": "anna nagar" - } - }, - { - "name": { - "value": "ramapuram" - } - } - ], - "name": "pickUpFrom" - }, - { - "values": [ - { - "name": { - "value": "dummy value for api response literal property" - } - } - ], - "name": "StringLiteral" - }, - { - "values": [ - { - "name": { - "value": "deep dish" - } - }, - { - "name": { - "value": "regular" - } - }, - { - "name": { - "value": "hand made" - } - }, - { - "name": { - "value": "gluten free" - } - }, - { - "name": { - "value": "thin crust" - } - }, - { - "name": { - "value": "brooklyn style" - } - } - ], - "name": "crust" - }, - { - "values": [ - { - "name": { - "value": "none", - "synonyms": ["no cheese", "dont add cheese", "nope", "no"] - } - }, - { - "name": { - "value": "light", - "synonyms": ["light cheese"] - } - }, - { - "name": { - "value": "normal", - "synonyms": ["Normal cheese"] - } - }, - { - "name": { - "value": "extra", - "synonyms": ["Extra cheese"] - } - }, - { - "name": { - "value": "double", - "synonyms": ["Double cheese"] - } - } - ], - "name": "cheese" - }, - { - "values": [ - { - "name": { - "value": "cheese", - "synonyms": ["cheeses"] - } - }, - { - "name": { - "value": "crust", - "synonyms": ["crusts"] - } - }, - { - "name": { - "value": "size", - "synonyms": ["sizes"] - } - } - ], - "name": "option" - }, - { - "values": [ - { - "name": { - "value": "two medium, two topping" - } - }, - { - "name": { - "value": "three cheese delight" - } - }, - { - "name": { - "value": "pepperoni party" - } - }, - { - "name": { - "value": "meat lovers" - } - }, - { - "name": { - "value": "veggie supreme" - } - }, - { - "name": { - "value": "kitchen sink" - } - } - ], - "name": "specialPizzaName" - }, - { - "values": [ - { - "name": { - "value": "onion", - "synonyms": ["onions"] - } - }, - { - "name": { - "value": "banana peppers", - "synonyms": ["banana pepper"] - } - }, - { - "name": { - "value": "olives", - "synonyms": ["black olives"] - } - }, - { - "name": { - "value": "mushrooms", - "synonyms": ["mushroom"] - } - }, - { - "name": { - "value": "pineapple" - } - }, - { - "name": { - "value": "spinach", - "synonyms": ["spinach"] - } - } - ], - "name": "toppings" - }, - { - "values": [ - { - "name": { - "value": "failure" - } - }, - { - "name": { - "value": "failed" - } - }, - { - "name": { - "value": "success" - } - } - ], - "name": "orderStatus" - }, - { - "values": [ - { - "name": { - "value": "san diego" - } - }, - { - "name": { - "value": "los angeles" - } - }, - { - "name": { - "value": "denver" - } - }, - { - "name": { - "value": "paris" - } - }, - { - "name": { - "value": "seattle" - } - }, - { - "name": { - "value": "portland" - } - }, - { - "name": { - "value": "ramapuram" - } - }, - { - "name": { - "value": "chennai" - } - } - ], - "name": "city_name_one" - }, - { - "values": [ - { - "name": { - "value": "denver" - } - }, - { - "name": { - "value": "sydney" - } - }, - { - "name": { - "value": "portland" - } - }, - { - "name": { - "value": "new york" - } - }, - { - "name": { - "value": "visakhapatnam" - } - }, - { - "name": { - "value": "bangalore" - } - }, - { - "name": { - "value": "mumbai" - } - }, - { - "name": { - "value": "seattle" - } - }, - { - "name": { - "value": "chennai" - } - } - ], - "name": "customCity" - }, - { - "values": [ - { - "name": { - "value": "denver" - } - }, - { - "name": { - "value": "sydney" - } - }, - { - "name": { - "value": "portland" - } - }, - { - "name": { - "value": "new york" - } - }, - { - "name": { - "value": "visakhapatnam" - } - }, - { - "name": { - "value": "bangalore" - } - }, - { - "name": { - "value": "mumbai" - } - }, - { - "name": { - "value": "seattle" - } - }, - { - "name": { - "value": "chennai" - } - } - ], - "name": "city_name_two" - } - ] - } - }, - "version": "12" -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/display/confirm_city_apl_display/document.json b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/display/confirm_city_apl_display/document.json deleted file mode 100644 index 6fea1ff7..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/display/confirm_city_apl_display/document.json +++ /dev/null @@ -1,331 +0,0 @@ -{ - "type": "APL", - "version": "1.1", - "settings": {}, - "theme": "dark", - "import": [ - { - "name": "alexa-layouts", - "version": "1.0.0" - } - ], - "resources": [ - { - "description": "Stock color for the light theme", - "colors": { - "colorTextPrimary": "#151920" - } - }, - { - "description": "Stock color for the dark theme", - "when": "${viewport.theme == 'dark'}", - "colors": { - "colorTextPrimary": "#f0f1ef" - } - }, - { - "description": "Standard font sizes", - "dimensions": { - "textSizeBody": 48, - "textSizePrimary": 27, - "textSizeSecondary": 23, - "textSizeDetails": 20, - "textSizeSecondaryHint": 25 - } - }, - { - "description": "Common spacing values", - "dimensions": { - "spacingThin": 6, - "spacingSmall": 12, - "spacingMedium": 24, - "spacingLarge": 48, - "spacingExtraLarge": 72 - } - }, - { - "description": "Common margins and padding", - "dimensions": { - "marginTop": 40, - "marginLeft": 60, - "marginRight": 60, - "marginBottom": 40 - } - } - ], - "styles": { - "textStyleBase": { - "description": "Base font description; set color", - "values": [ - { - "color": "@colorTextPrimary" - } - ] - }, - "textStyleBase0": { - "description": "Thin version of basic font", - "extend": "textStyleBase", - "values": { - "fontWeight": "100" - } - }, - "textStyleBase1": { - "description": "Light version of basic font", - "extend": "textStyleBase", - "values": { - "fontWeight": "300" - } - }, - "textStyleBase2": { - "description": "Regular version of basic font", - "extend": "textStyleBase", - "values": { - "fontWeight": "500" - } - }, - "mixinBody": { - "values": { - "fontSize": "@textSizeBody" - } - }, - "mixinPrimary": { - "values": { - "fontSize": "@textSizePrimary" - } - }, - "mixinDetails": { - "values": { - "fontSize": "@textSizeDetails" - } - }, - "mixinSecondary": { - "values": { - "fontSize": "@textSizeSecondary" - } - }, - "textStylePrimary": { - "extend": ["textStyleBase1", "mixinPrimary"] - }, - "textStyleSecondary": { - "extend": ["textStyleBase0", "mixinSecondary"] - }, - "textStyleBody": { - "extend": ["textStyleBase1", "mixinBody"] - }, - "textStyleSecondaryHint": { - "values": { - "fontFamily": "Bookerly", - "fontStyle": "italic", - "fontSize": "@textSizeSecondaryHint", - "color": "@colorTextPrimary" - } - }, - "textStyleDetails": { - "extend": ["textStyleBase2", "mixinDetails"] - } - }, - "onMount": [], - "graphics": {}, - "commands": {}, - "layouts": { - "ListTemplate1": { - "parameters": ["backgroundImage", "title", "logo", "hintText", "listData"], - "item": [ - { - "type": "Container", - "width": "100vw", - "height": "100vh", - "direction": "column", - "items": [ - { - "type": "Image", - "source": "${backgroundImage}", - "scale": "best-fill", - "width": "100vw", - "height": "100vh", - "position": "absolute" - }, - { - "type": "AlexaHeader", - "headerTitle": "${title}", - "headerAttributionImage": "${logo}" - }, - { - "type": "Sequence", - "grow": 1, - "height": "80vh", - "scrollDirection": "vertical", - "paddingLeft": "@marginLeft", - "paddingRight": "@marginRight", - "data": "${listData}", - "numbered": true, - "items": [ - { - "type": "VerticalListItem", - "image": "${data.image.sources[0].url}", - "primaryText": "${data.textContent.primaryText.text}", - "secondaryText": "${data.textContent.secondaryText.text}", - "tertiaryText": "${data.textContent.tertiaryText.text}" - } - ] - } - ] - } - ] - }, - "VerticalListItem": { - "parameters": ["primaryText", "secondaryText", "tertiaryText", "image"], - "item": [ - { - "when": "${viewport.shape == 'round'}", - "type": "Container", - "direction": "row", - "height": 200, - "width": 500, - "alignItems": "center", - "items": [ - { - "type": "Text", - "text": "${ordinal}", - "paddingBottom": "20dp", - "color": "white", - "spacing": "5dp" - }, - { - "type": "Image", - "when": "${image}", - "source": "${image}", - "height": 150, - "width": 150, - "spacing": 15, - "scale": "best-fit", - "align": "top" - }, - { - "type": "Container", - "direction": "column", - "spacing": 25, - "items": [ - { - "type": "Text", - "text": "${primaryText}", - "style": "textStyleDetail", - "grow": 1, - "shrink": 1, - "fontWeight": "300", - "maxLines": 1 - }, - { - "type": "Text", - "text": "${secondaryText}", - "style": "textStyleCaption", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - }, - { - "type": "Text", - "text": "${tertiaryText}", - "style": "textStyleDetails", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - } - ] - } - ] - }, - { - "type": "Container", - "direction": "row", - "height": 125, - "width": 800, - "alignItems": "center", - "items": [ - { - "type": "Text", - "text": "${ordinal}", - "paddingBottom": "20dp", - "color": "white", - "spacing": "5dp" - }, - { - "type": "Image", - "when": "${image}", - "source": "${image}", - "height": 100, - "width": 100, - "align": "top", - "spacing": 50, - "scale": "best-fit" - }, - { - "type": "Container", - "spacing": 30, - "direction": "column", - "items": [ - { - "type": "Text", - "text": "${primaryText}", - "style": "textStyleBody", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - }, - { - "type": "Text", - "text": "${secondaryText}", - "style": "textStyleDetails", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - } - ] - }, - { - "type": "Text", - "text": "${tertiaryText}", - "style": "textStyleBody", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "textAlign": "right", - "maxLines": 1 - } - ] - } - ] - } - }, - "mainTemplate": { - "parameters": ["payload"], - "item": [ - { - "type": "Container", - "id": "BookCabSimpleDialogAPL", - "items": [ - { - "type": "TouchWrapper", - "onPress": { - "type": "SendEvent", - "arguments": ["delegateToColtraneOld"] - }, - "item": { - "type": "Text", - "id": "BookCabSimpleDialogAPL", - "paddingTop": "100", - "paddingLeft": "100", - "color": "green", - "size": 50, - "text": "which city ?" - } - } - ] - } - ] - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/display/confirm_date_apl_display/document.json b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/display/confirm_date_apl_display/document.json deleted file mode 100644 index d41ea236..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/display/confirm_date_apl_display/document.json +++ /dev/null @@ -1,331 +0,0 @@ -{ - "type": "APL", - "version": "1.1", - "settings": {}, - "theme": "dark", - "import": [ - { - "name": "alexa-layouts", - "version": "1.0.0" - } - ], - "resources": [ - { - "description": "Stock color for the light theme", - "colors": { - "colorTextPrimary": "#151920" - } - }, - { - "description": "Stock color for the dark theme", - "when": "${viewport.theme == 'dark'}", - "colors": { - "colorTextPrimary": "#f0f1ef" - } - }, - { - "description": "Standard font sizes", - "dimensions": { - "textSizeBody": 48, - "textSizePrimary": 27, - "textSizeSecondary": 23, - "textSizeDetails": 20, - "textSizeSecondaryHint": 25 - } - }, - { - "description": "Common spacing values", - "dimensions": { - "spacingThin": 6, - "spacingSmall": 12, - "spacingMedium": 24, - "spacingLarge": 48, - "spacingExtraLarge": 72 - } - }, - { - "description": "Common margins and padding", - "dimensions": { - "marginTop": 40, - "marginLeft": 60, - "marginRight": 60, - "marginBottom": 40 - } - } - ], - "styles": { - "textStyleBase": { - "description": "Base font description; set color", - "values": [ - { - "color": "@colorTextPrimary" - } - ] - }, - "textStyleBase0": { - "description": "Thin version of basic font", - "extend": "textStyleBase", - "values": { - "fontWeight": "100" - } - }, - "textStyleBase1": { - "description": "Light version of basic font", - "extend": "textStyleBase", - "values": { - "fontWeight": "300" - } - }, - "textStyleBase2": { - "description": "Regular version of basic font", - "extend": "textStyleBase", - "values": { - "fontWeight": "500" - } - }, - "mixinBody": { - "values": { - "fontSize": "@textSizeBody" - } - }, - "mixinPrimary": { - "values": { - "fontSize": "@textSizePrimary" - } - }, - "mixinDetails": { - "values": { - "fontSize": "@textSizeDetails" - } - }, - "mixinSecondary": { - "values": { - "fontSize": "@textSizeSecondary" - } - }, - "textStylePrimary": { - "extend": ["textStyleBase1", "mixinPrimary"] - }, - "textStyleSecondary": { - "extend": ["textStyleBase0", "mixinSecondary"] - }, - "textStyleBody": { - "extend": ["textStyleBase1", "mixinBody"] - }, - "textStyleSecondaryHint": { - "values": { - "fontFamily": "Bookerly", - "fontStyle": "italic", - "fontSize": "@textSizeSecondaryHint", - "color": "@colorTextPrimary" - } - }, - "textStyleDetails": { - "extend": ["textStyleBase2", "mixinDetails"] - } - }, - "onMount": [], - "graphics": {}, - "commands": {}, - "layouts": { - "ListTemplate1": { - "parameters": ["backgroundImage", "title", "logo", "hintText", "listData"], - "item": [ - { - "type": "Container", - "width": "100vw", - "height": "100vh", - "direction": "column", - "items": [ - { - "type": "Image", - "source": "${backgroundImage}", - "scale": "best-fill", - "width": "100vw", - "height": "100vh", - "position": "absolute" - }, - { - "type": "AlexaHeader", - "headerTitle": "${title}", - "headerAttributionImage": "${logo}" - }, - { - "type": "Sequence", - "grow": 1, - "height": "80vh", - "scrollDirection": "vertical", - "paddingLeft": "@marginLeft", - "paddingRight": "@marginRight", - "data": "${listData}", - "numbered": true, - "items": [ - { - "type": "VerticalListItem", - "image": "${data.image.sources[0].url}", - "primaryText": "${data.textContent.primaryText.text}", - "secondaryText": "${data.textContent.secondaryText.text}", - "tertiaryText": "${data.textContent.tertiaryText.text}" - } - ] - } - ] - } - ] - }, - "VerticalListItem": { - "parameters": ["primaryText", "secondaryText", "tertiaryText", "image"], - "item": [ - { - "when": "${viewport.shape == 'round'}", - "type": "Container", - "direction": "row", - "height": 200, - "width": 500, - "alignItems": "center", - "items": [ - { - "type": "Text", - "text": "${ordinal}", - "paddingBottom": "20dp", - "color": "white", - "spacing": "5dp" - }, - { - "type": "Image", - "when": "${image}", - "source": "${image}", - "height": 150, - "width": 150, - "spacing": 15, - "scale": "best-fit", - "align": "top" - }, - { - "type": "Container", - "direction": "column", - "spacing": 25, - "items": [ - { - "type": "Text", - "text": "${primaryText}", - "style": "textStyleDetail", - "grow": 1, - "shrink": 1, - "fontWeight": "300", - "maxLines": 1 - }, - { - "type": "Text", - "text": "${secondaryText}", - "style": "textStyleCaption", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - }, - { - "type": "Text", - "text": "${tertiaryText}", - "style": "textStyleDetails", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - } - ] - } - ] - }, - { - "type": "Container", - "direction": "row", - "height": 125, - "width": 800, - "alignItems": "center", - "items": [ - { - "type": "Text", - "text": "${ordinal}", - "paddingBottom": "20dp", - "color": "white", - "spacing": "5dp" - }, - { - "type": "Image", - "when": "${image}", - "source": "${image}", - "height": 100, - "width": 100, - "align": "top", - "spacing": 50, - "scale": "best-fit" - }, - { - "type": "Container", - "spacing": 30, - "direction": "column", - "items": [ - { - "type": "Text", - "text": "${primaryText}", - "style": "textStyleBody", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - }, - { - "type": "Text", - "text": "${secondaryText}", - "style": "textStyleDetails", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - } - ] - }, - { - "type": "Text", - "text": "${tertiaryText}", - "style": "textStyleBody", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "textAlign": "right", - "maxLines": 1 - } - ] - } - ] - } - }, - "mainTemplate": { - "parameters": ["payload"], - "item": [ - { - "type": "Container", - "id": "BookCabSimpleDialogAPL", - "items": [ - { - "type": "TouchWrapper", - "onPress": { - "type": "SendEvent", - "arguments": ["delegateToColtraneOld"] - }, - "item": { - "type": "Text", - "id": "BookCabSimpleDialogAPL", - "paddingTop": "100", - "paddingLeft": "100", - "color": "green", - "size": 50, - "text": "which date ?" - } - } - ] - } - ] - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/display/confirm_weather_apla_display/document.json b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/display/confirm_weather_apla_display/document.json deleted file mode 100644 index 3bcc0e4a..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/display/confirm_weather_apla_display/document.json +++ /dev/null @@ -1,379 +0,0 @@ -{ - "type": "APL", - "version": "1.1", - "settings": {}, - "theme": "dark", - "import": [ - { - "name": "alexa-layouts", - "version": "1.0.0" - } - ], - "resources": [ - { - "description": "Stock color for the light theme", - "colors": { - "colorTextPrimary": "#151920" - } - }, - { - "description": "Stock color for the dark theme", - "when": "${viewport.theme == 'dark'}", - "colors": { - "colorTextPrimary": "#f0f1ef" - } - }, - { - "description": "Standard font sizes", - "dimensions": { - "textSizeBody": 48, - "textSizePrimary": 27, - "textSizeSecondary": 23, - "textSizeDetails": 20, - "textSizeSecondaryHint": 25 - } - }, - { - "description": "Common spacing values", - "dimensions": { - "spacingThin": 6, - "spacingSmall": 12, - "spacingMedium": 24, - "spacingLarge": 48, - "spacingExtraLarge": 72 - } - }, - { - "description": "Common margins and padding", - "dimensions": { - "marginTop": 40, - "marginLeft": 60, - "marginRight": 60, - "marginBottom": 40 - } - } - ], - "styles": { - "textStyleBase": { - "description": "Base font description; set color", - "values": [ - { - "color": "@colorTextPrimary" - } - ] - }, - "textStyleBase0": { - "description": "Thin version of basic font", - "extend": "textStyleBase", - "values": { - "fontWeight": "100" - } - }, - "textStyleBase1": { - "description": "Light version of basic font", - "extend": "textStyleBase", - "values": { - "fontWeight": "300" - } - }, - "textStyleBase2": { - "description": "Regular version of basic font", - "extend": "textStyleBase", - "values": { - "fontWeight": "500" - } - }, - "mixinBody": { - "values": { - "fontSize": "@textSizeBody" - } - }, - "mixinPrimary": { - "values": { - "fontSize": "@textSizePrimary" - } - }, - "mixinDetails": { - "values": { - "fontSize": "@textSizeDetails" - } - }, - "mixinSecondary": { - "values": { - "fontSize": "@textSizeSecondary" - } - }, - "textStylePrimary": { - "extend": ["textStyleBase1", "mixinPrimary"] - }, - "textStyleSecondary": { - "extend": ["textStyleBase0", "mixinSecondary"] - }, - "textStyleBody": { - "extend": ["textStyleBase1", "mixinBody"] - }, - "textStyleSecondaryHint": { - "values": { - "fontFamily": "Bookerly", - "fontStyle": "italic", - "fontSize": "@textSizeSecondaryHint", - "color": "@colorTextPrimary" - } - }, - "textStyleDetails": { - "extend": ["textStyleBase2", "mixinDetails"] - } - }, - "onMount": [], - "graphics": {}, - "commands": {}, - "layouts": { - "ListTemplate1": { - "parameters": ["backgroundImage", "title", "logo", "hintText", "listData"], - "item": [ - { - "type": "Container", - "width": "100vw", - "height": "100vh", - "direction": "column", - "items": [ - { - "type": "Image", - "source": "${backgroundImage}", - "scale": "best-fill", - "width": "100vw", - "height": "100vh", - "position": "absolute" - }, - { - "type": "AlexaHeader", - "headerTitle": "${title}", - "headerAttributionImage": "${logo}" - }, - { - "type": "Sequence", - "grow": 1, - "height": "80vh", - "scrollDirection": "vertical", - "paddingLeft": "@marginLeft", - "paddingRight": "@marginRight", - "data": "${listData}", - "numbered": true, - "items": [ - { - "type": "VerticalListItem", - "image": "${data.image.sources[0].url}", - "primaryText": "${data.textContent.primaryText.text}", - "secondaryText": "${data.textContent.secondaryText.text}", - "tertiaryText": "${data.textContent.tertiaryText.text}" - } - ] - } - ] - } - ] - }, - "VerticalListItem": { - "parameters": ["primaryText", "secondaryText", "tertiaryText", "image"], - "item": [ - { - "when": "${viewport.shape == 'round'}", - "type": "Container", - "direction": "row", - "height": 200, - "width": 500, - "alignItems": "center", - "items": [ - { - "type": "Text", - "text": "${ordinal}", - "paddingBottom": "20dp", - "color": "white", - "spacing": "5dp" - }, - { - "type": "Image", - "when": "${image}", - "source": "${image}", - "height": 150, - "width": 150, - "spacing": 15, - "scale": "best-fit", - "align": "top" - }, - { - "type": "Container", - "direction": "column", - "spacing": 25, - "items": [ - { - "type": "Text", - "text": "${primaryText}", - "style": "textStyleDetail", - "grow": 1, - "shrink": 1, - "fontWeight": "300", - "maxLines": 1 - }, - { - "type": "Text", - "text": "${secondaryText}", - "style": "textStyleCaption", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - }, - { - "type": "Text", - "text": "${tertiaryText}", - "style": "textStyleDetails", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - } - ] - } - ] - }, - { - "type": "Container", - "direction": "row", - "height": 125, - "width": 800, - "alignItems": "center", - "items": [ - { - "type": "Text", - "text": "${ordinal}", - "paddingBottom": "20dp", - "color": "white", - "spacing": "5dp" - }, - { - "type": "Image", - "when": "${image}", - "source": "${image}", - "height": 100, - "width": 100, - "align": "top", - "spacing": 50, - "scale": "best-fit" - }, - { - "type": "Container", - "spacing": 30, - "direction": "column", - "items": [ - { - "type": "Text", - "text": "${primaryText}", - "style": "textStyleBody", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - }, - { - "type": "Text", - "text": "${secondaryText}", - "style": "textStyleDetails", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - } - ] - }, - { - "type": "Text", - "text": "${tertiaryText}", - "style": "textStyleBody", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "textAlign": "right", - "maxLines": 1 - } - ] - } - ] - } - }, - "mainTemplate": { - "parameters": ["payload"], - "item": [ - { - "type": "Container", - "id": "BookCabSimpleDialogAPL", - "items": [ - { - "type": "TouchWrapper", - "onPress": { - "type": "SendEvent", - "arguments": ["delegateToSkillNew"] - }, - "item": { - "type": "Text", - "id": "BookCabSimpleDialogAPL", - "paddingTop": "100", - "paddingLeft": "100", - "color": "green", - "size": 50, - "text": "delegateToSkillNew" - } - }, - { - "type": "TouchWrapper", - "onPress": { - "type": "SendEvent", - "arguments": ["delegateToSkillOld"] - }, - "item": { - "type": "Text", - "id": "BookCabSimpleDialogAPL", - "paddingTop": "100", - "paddingLeft": "100", - "color": "green", - "size": 50, - "text": "delegateToSkillOld" - } - }, - { - "type": "TouchWrapper", - "onPress": { - "type": "SendEvent", - "arguments": ["delegateToColtraneNew"] - }, - "item": { - "type": "Text", - "id": "BookCabSimpleDialogAPL", - "paddingTop": "100", - "paddingLeft": "100", - "color": "green", - "size": 50, - "text": "delegateToColtraneNew" - } - }, - { - "type": "TouchWrapper", - "onPress": { - "type": "SendEvent", - "arguments": ["delegateToColtraneOld"] - }, - "item": { - "type": "Text", - "id": "BookCabSimpleDialogAPL", - "paddingTop": "100", - "paddingLeft": "100", - "color": "green", - "size": 50, - "text": "delegateToColtraneOld" - } - } - ] - } - ] - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/display/request_city_apl_display/document.json b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/display/request_city_apl_display/document.json deleted file mode 100644 index 6fea1ff7..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/display/request_city_apl_display/document.json +++ /dev/null @@ -1,331 +0,0 @@ -{ - "type": "APL", - "version": "1.1", - "settings": {}, - "theme": "dark", - "import": [ - { - "name": "alexa-layouts", - "version": "1.0.0" - } - ], - "resources": [ - { - "description": "Stock color for the light theme", - "colors": { - "colorTextPrimary": "#151920" - } - }, - { - "description": "Stock color for the dark theme", - "when": "${viewport.theme == 'dark'}", - "colors": { - "colorTextPrimary": "#f0f1ef" - } - }, - { - "description": "Standard font sizes", - "dimensions": { - "textSizeBody": 48, - "textSizePrimary": 27, - "textSizeSecondary": 23, - "textSizeDetails": 20, - "textSizeSecondaryHint": 25 - } - }, - { - "description": "Common spacing values", - "dimensions": { - "spacingThin": 6, - "spacingSmall": 12, - "spacingMedium": 24, - "spacingLarge": 48, - "spacingExtraLarge": 72 - } - }, - { - "description": "Common margins and padding", - "dimensions": { - "marginTop": 40, - "marginLeft": 60, - "marginRight": 60, - "marginBottom": 40 - } - } - ], - "styles": { - "textStyleBase": { - "description": "Base font description; set color", - "values": [ - { - "color": "@colorTextPrimary" - } - ] - }, - "textStyleBase0": { - "description": "Thin version of basic font", - "extend": "textStyleBase", - "values": { - "fontWeight": "100" - } - }, - "textStyleBase1": { - "description": "Light version of basic font", - "extend": "textStyleBase", - "values": { - "fontWeight": "300" - } - }, - "textStyleBase2": { - "description": "Regular version of basic font", - "extend": "textStyleBase", - "values": { - "fontWeight": "500" - } - }, - "mixinBody": { - "values": { - "fontSize": "@textSizeBody" - } - }, - "mixinPrimary": { - "values": { - "fontSize": "@textSizePrimary" - } - }, - "mixinDetails": { - "values": { - "fontSize": "@textSizeDetails" - } - }, - "mixinSecondary": { - "values": { - "fontSize": "@textSizeSecondary" - } - }, - "textStylePrimary": { - "extend": ["textStyleBase1", "mixinPrimary"] - }, - "textStyleSecondary": { - "extend": ["textStyleBase0", "mixinSecondary"] - }, - "textStyleBody": { - "extend": ["textStyleBase1", "mixinBody"] - }, - "textStyleSecondaryHint": { - "values": { - "fontFamily": "Bookerly", - "fontStyle": "italic", - "fontSize": "@textSizeSecondaryHint", - "color": "@colorTextPrimary" - } - }, - "textStyleDetails": { - "extend": ["textStyleBase2", "mixinDetails"] - } - }, - "onMount": [], - "graphics": {}, - "commands": {}, - "layouts": { - "ListTemplate1": { - "parameters": ["backgroundImage", "title", "logo", "hintText", "listData"], - "item": [ - { - "type": "Container", - "width": "100vw", - "height": "100vh", - "direction": "column", - "items": [ - { - "type": "Image", - "source": "${backgroundImage}", - "scale": "best-fill", - "width": "100vw", - "height": "100vh", - "position": "absolute" - }, - { - "type": "AlexaHeader", - "headerTitle": "${title}", - "headerAttributionImage": "${logo}" - }, - { - "type": "Sequence", - "grow": 1, - "height": "80vh", - "scrollDirection": "vertical", - "paddingLeft": "@marginLeft", - "paddingRight": "@marginRight", - "data": "${listData}", - "numbered": true, - "items": [ - { - "type": "VerticalListItem", - "image": "${data.image.sources[0].url}", - "primaryText": "${data.textContent.primaryText.text}", - "secondaryText": "${data.textContent.secondaryText.text}", - "tertiaryText": "${data.textContent.tertiaryText.text}" - } - ] - } - ] - } - ] - }, - "VerticalListItem": { - "parameters": ["primaryText", "secondaryText", "tertiaryText", "image"], - "item": [ - { - "when": "${viewport.shape == 'round'}", - "type": "Container", - "direction": "row", - "height": 200, - "width": 500, - "alignItems": "center", - "items": [ - { - "type": "Text", - "text": "${ordinal}", - "paddingBottom": "20dp", - "color": "white", - "spacing": "5dp" - }, - { - "type": "Image", - "when": "${image}", - "source": "${image}", - "height": 150, - "width": 150, - "spacing": 15, - "scale": "best-fit", - "align": "top" - }, - { - "type": "Container", - "direction": "column", - "spacing": 25, - "items": [ - { - "type": "Text", - "text": "${primaryText}", - "style": "textStyleDetail", - "grow": 1, - "shrink": 1, - "fontWeight": "300", - "maxLines": 1 - }, - { - "type": "Text", - "text": "${secondaryText}", - "style": "textStyleCaption", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - }, - { - "type": "Text", - "text": "${tertiaryText}", - "style": "textStyleDetails", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - } - ] - } - ] - }, - { - "type": "Container", - "direction": "row", - "height": 125, - "width": 800, - "alignItems": "center", - "items": [ - { - "type": "Text", - "text": "${ordinal}", - "paddingBottom": "20dp", - "color": "white", - "spacing": "5dp" - }, - { - "type": "Image", - "when": "${image}", - "source": "${image}", - "height": 100, - "width": 100, - "align": "top", - "spacing": 50, - "scale": "best-fit" - }, - { - "type": "Container", - "spacing": 30, - "direction": "column", - "items": [ - { - "type": "Text", - "text": "${primaryText}", - "style": "textStyleBody", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - }, - { - "type": "Text", - "text": "${secondaryText}", - "style": "textStyleDetails", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - } - ] - }, - { - "type": "Text", - "text": "${tertiaryText}", - "style": "textStyleBody", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "textAlign": "right", - "maxLines": 1 - } - ] - } - ] - } - }, - "mainTemplate": { - "parameters": ["payload"], - "item": [ - { - "type": "Container", - "id": "BookCabSimpleDialogAPL", - "items": [ - { - "type": "TouchWrapper", - "onPress": { - "type": "SendEvent", - "arguments": ["delegateToColtraneOld"] - }, - "item": { - "type": "Text", - "id": "BookCabSimpleDialogAPL", - "paddingTop": "100", - "paddingLeft": "100", - "color": "green", - "size": 50, - "text": "which city ?" - } - } - ] - } - ] - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/display/request_date_apl_display/document.json b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/display/request_date_apl_display/document.json deleted file mode 100644 index d41ea236..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/display/request_date_apl_display/document.json +++ /dev/null @@ -1,331 +0,0 @@ -{ - "type": "APL", - "version": "1.1", - "settings": {}, - "theme": "dark", - "import": [ - { - "name": "alexa-layouts", - "version": "1.0.0" - } - ], - "resources": [ - { - "description": "Stock color for the light theme", - "colors": { - "colorTextPrimary": "#151920" - } - }, - { - "description": "Stock color for the dark theme", - "when": "${viewport.theme == 'dark'}", - "colors": { - "colorTextPrimary": "#f0f1ef" - } - }, - { - "description": "Standard font sizes", - "dimensions": { - "textSizeBody": 48, - "textSizePrimary": 27, - "textSizeSecondary": 23, - "textSizeDetails": 20, - "textSizeSecondaryHint": 25 - } - }, - { - "description": "Common spacing values", - "dimensions": { - "spacingThin": 6, - "spacingSmall": 12, - "spacingMedium": 24, - "spacingLarge": 48, - "spacingExtraLarge": 72 - } - }, - { - "description": "Common margins and padding", - "dimensions": { - "marginTop": 40, - "marginLeft": 60, - "marginRight": 60, - "marginBottom": 40 - } - } - ], - "styles": { - "textStyleBase": { - "description": "Base font description; set color", - "values": [ - { - "color": "@colorTextPrimary" - } - ] - }, - "textStyleBase0": { - "description": "Thin version of basic font", - "extend": "textStyleBase", - "values": { - "fontWeight": "100" - } - }, - "textStyleBase1": { - "description": "Light version of basic font", - "extend": "textStyleBase", - "values": { - "fontWeight": "300" - } - }, - "textStyleBase2": { - "description": "Regular version of basic font", - "extend": "textStyleBase", - "values": { - "fontWeight": "500" - } - }, - "mixinBody": { - "values": { - "fontSize": "@textSizeBody" - } - }, - "mixinPrimary": { - "values": { - "fontSize": "@textSizePrimary" - } - }, - "mixinDetails": { - "values": { - "fontSize": "@textSizeDetails" - } - }, - "mixinSecondary": { - "values": { - "fontSize": "@textSizeSecondary" - } - }, - "textStylePrimary": { - "extend": ["textStyleBase1", "mixinPrimary"] - }, - "textStyleSecondary": { - "extend": ["textStyleBase0", "mixinSecondary"] - }, - "textStyleBody": { - "extend": ["textStyleBase1", "mixinBody"] - }, - "textStyleSecondaryHint": { - "values": { - "fontFamily": "Bookerly", - "fontStyle": "italic", - "fontSize": "@textSizeSecondaryHint", - "color": "@colorTextPrimary" - } - }, - "textStyleDetails": { - "extend": ["textStyleBase2", "mixinDetails"] - } - }, - "onMount": [], - "graphics": {}, - "commands": {}, - "layouts": { - "ListTemplate1": { - "parameters": ["backgroundImage", "title", "logo", "hintText", "listData"], - "item": [ - { - "type": "Container", - "width": "100vw", - "height": "100vh", - "direction": "column", - "items": [ - { - "type": "Image", - "source": "${backgroundImage}", - "scale": "best-fill", - "width": "100vw", - "height": "100vh", - "position": "absolute" - }, - { - "type": "AlexaHeader", - "headerTitle": "${title}", - "headerAttributionImage": "${logo}" - }, - { - "type": "Sequence", - "grow": 1, - "height": "80vh", - "scrollDirection": "vertical", - "paddingLeft": "@marginLeft", - "paddingRight": "@marginRight", - "data": "${listData}", - "numbered": true, - "items": [ - { - "type": "VerticalListItem", - "image": "${data.image.sources[0].url}", - "primaryText": "${data.textContent.primaryText.text}", - "secondaryText": "${data.textContent.secondaryText.text}", - "tertiaryText": "${data.textContent.tertiaryText.text}" - } - ] - } - ] - } - ] - }, - "VerticalListItem": { - "parameters": ["primaryText", "secondaryText", "tertiaryText", "image"], - "item": [ - { - "when": "${viewport.shape == 'round'}", - "type": "Container", - "direction": "row", - "height": 200, - "width": 500, - "alignItems": "center", - "items": [ - { - "type": "Text", - "text": "${ordinal}", - "paddingBottom": "20dp", - "color": "white", - "spacing": "5dp" - }, - { - "type": "Image", - "when": "${image}", - "source": "${image}", - "height": 150, - "width": 150, - "spacing": 15, - "scale": "best-fit", - "align": "top" - }, - { - "type": "Container", - "direction": "column", - "spacing": 25, - "items": [ - { - "type": "Text", - "text": "${primaryText}", - "style": "textStyleDetail", - "grow": 1, - "shrink": 1, - "fontWeight": "300", - "maxLines": 1 - }, - { - "type": "Text", - "text": "${secondaryText}", - "style": "textStyleCaption", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - }, - { - "type": "Text", - "text": "${tertiaryText}", - "style": "textStyleDetails", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - } - ] - } - ] - }, - { - "type": "Container", - "direction": "row", - "height": 125, - "width": 800, - "alignItems": "center", - "items": [ - { - "type": "Text", - "text": "${ordinal}", - "paddingBottom": "20dp", - "color": "white", - "spacing": "5dp" - }, - { - "type": "Image", - "when": "${image}", - "source": "${image}", - "height": 100, - "width": 100, - "align": "top", - "spacing": 50, - "scale": "best-fit" - }, - { - "type": "Container", - "spacing": 30, - "direction": "column", - "items": [ - { - "type": "Text", - "text": "${primaryText}", - "style": "textStyleBody", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - }, - { - "type": "Text", - "text": "${secondaryText}", - "style": "textStyleDetails", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - } - ] - }, - { - "type": "Text", - "text": "${tertiaryText}", - "style": "textStyleBody", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "textAlign": "right", - "maxLines": 1 - } - ] - } - ] - } - }, - "mainTemplate": { - "parameters": ["payload"], - "item": [ - { - "type": "Container", - "id": "BookCabSimpleDialogAPL", - "items": [ - { - "type": "TouchWrapper", - "onPress": { - "type": "SendEvent", - "arguments": ["delegateToColtraneOld"] - }, - "item": { - "type": "Text", - "id": "BookCabSimpleDialogAPL", - "paddingTop": "100", - "paddingLeft": "100", - "color": "green", - "size": 50, - "text": "which date ?" - } - } - ] - } - ] - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/display/weather_success_apl_display/document.json b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/display/weather_success_apl_display/document.json deleted file mode 100644 index 3bcc0e4a..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/display/weather_success_apl_display/document.json +++ /dev/null @@ -1,379 +0,0 @@ -{ - "type": "APL", - "version": "1.1", - "settings": {}, - "theme": "dark", - "import": [ - { - "name": "alexa-layouts", - "version": "1.0.0" - } - ], - "resources": [ - { - "description": "Stock color for the light theme", - "colors": { - "colorTextPrimary": "#151920" - } - }, - { - "description": "Stock color for the dark theme", - "when": "${viewport.theme == 'dark'}", - "colors": { - "colorTextPrimary": "#f0f1ef" - } - }, - { - "description": "Standard font sizes", - "dimensions": { - "textSizeBody": 48, - "textSizePrimary": 27, - "textSizeSecondary": 23, - "textSizeDetails": 20, - "textSizeSecondaryHint": 25 - } - }, - { - "description": "Common spacing values", - "dimensions": { - "spacingThin": 6, - "spacingSmall": 12, - "spacingMedium": 24, - "spacingLarge": 48, - "spacingExtraLarge": 72 - } - }, - { - "description": "Common margins and padding", - "dimensions": { - "marginTop": 40, - "marginLeft": 60, - "marginRight": 60, - "marginBottom": 40 - } - } - ], - "styles": { - "textStyleBase": { - "description": "Base font description; set color", - "values": [ - { - "color": "@colorTextPrimary" - } - ] - }, - "textStyleBase0": { - "description": "Thin version of basic font", - "extend": "textStyleBase", - "values": { - "fontWeight": "100" - } - }, - "textStyleBase1": { - "description": "Light version of basic font", - "extend": "textStyleBase", - "values": { - "fontWeight": "300" - } - }, - "textStyleBase2": { - "description": "Regular version of basic font", - "extend": "textStyleBase", - "values": { - "fontWeight": "500" - } - }, - "mixinBody": { - "values": { - "fontSize": "@textSizeBody" - } - }, - "mixinPrimary": { - "values": { - "fontSize": "@textSizePrimary" - } - }, - "mixinDetails": { - "values": { - "fontSize": "@textSizeDetails" - } - }, - "mixinSecondary": { - "values": { - "fontSize": "@textSizeSecondary" - } - }, - "textStylePrimary": { - "extend": ["textStyleBase1", "mixinPrimary"] - }, - "textStyleSecondary": { - "extend": ["textStyleBase0", "mixinSecondary"] - }, - "textStyleBody": { - "extend": ["textStyleBase1", "mixinBody"] - }, - "textStyleSecondaryHint": { - "values": { - "fontFamily": "Bookerly", - "fontStyle": "italic", - "fontSize": "@textSizeSecondaryHint", - "color": "@colorTextPrimary" - } - }, - "textStyleDetails": { - "extend": ["textStyleBase2", "mixinDetails"] - } - }, - "onMount": [], - "graphics": {}, - "commands": {}, - "layouts": { - "ListTemplate1": { - "parameters": ["backgroundImage", "title", "logo", "hintText", "listData"], - "item": [ - { - "type": "Container", - "width": "100vw", - "height": "100vh", - "direction": "column", - "items": [ - { - "type": "Image", - "source": "${backgroundImage}", - "scale": "best-fill", - "width": "100vw", - "height": "100vh", - "position": "absolute" - }, - { - "type": "AlexaHeader", - "headerTitle": "${title}", - "headerAttributionImage": "${logo}" - }, - { - "type": "Sequence", - "grow": 1, - "height": "80vh", - "scrollDirection": "vertical", - "paddingLeft": "@marginLeft", - "paddingRight": "@marginRight", - "data": "${listData}", - "numbered": true, - "items": [ - { - "type": "VerticalListItem", - "image": "${data.image.sources[0].url}", - "primaryText": "${data.textContent.primaryText.text}", - "secondaryText": "${data.textContent.secondaryText.text}", - "tertiaryText": "${data.textContent.tertiaryText.text}" - } - ] - } - ] - } - ] - }, - "VerticalListItem": { - "parameters": ["primaryText", "secondaryText", "tertiaryText", "image"], - "item": [ - { - "when": "${viewport.shape == 'round'}", - "type": "Container", - "direction": "row", - "height": 200, - "width": 500, - "alignItems": "center", - "items": [ - { - "type": "Text", - "text": "${ordinal}", - "paddingBottom": "20dp", - "color": "white", - "spacing": "5dp" - }, - { - "type": "Image", - "when": "${image}", - "source": "${image}", - "height": 150, - "width": 150, - "spacing": 15, - "scale": "best-fit", - "align": "top" - }, - { - "type": "Container", - "direction": "column", - "spacing": 25, - "items": [ - { - "type": "Text", - "text": "${primaryText}", - "style": "textStyleDetail", - "grow": 1, - "shrink": 1, - "fontWeight": "300", - "maxLines": 1 - }, - { - "type": "Text", - "text": "${secondaryText}", - "style": "textStyleCaption", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - }, - { - "type": "Text", - "text": "${tertiaryText}", - "style": "textStyleDetails", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - } - ] - } - ] - }, - { - "type": "Container", - "direction": "row", - "height": 125, - "width": 800, - "alignItems": "center", - "items": [ - { - "type": "Text", - "text": "${ordinal}", - "paddingBottom": "20dp", - "color": "white", - "spacing": "5dp" - }, - { - "type": "Image", - "when": "${image}", - "source": "${image}", - "height": 100, - "width": 100, - "align": "top", - "spacing": 50, - "scale": "best-fit" - }, - { - "type": "Container", - "spacing": 30, - "direction": "column", - "items": [ - { - "type": "Text", - "text": "${primaryText}", - "style": "textStyleBody", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - }, - { - "type": "Text", - "text": "${secondaryText}", - "style": "textStyleDetails", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - } - ] - }, - { - "type": "Text", - "text": "${tertiaryText}", - "style": "textStyleBody", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "textAlign": "right", - "maxLines": 1 - } - ] - } - ] - } - }, - "mainTemplate": { - "parameters": ["payload"], - "item": [ - { - "type": "Container", - "id": "BookCabSimpleDialogAPL", - "items": [ - { - "type": "TouchWrapper", - "onPress": { - "type": "SendEvent", - "arguments": ["delegateToSkillNew"] - }, - "item": { - "type": "Text", - "id": "BookCabSimpleDialogAPL", - "paddingTop": "100", - "paddingLeft": "100", - "color": "green", - "size": 50, - "text": "delegateToSkillNew" - } - }, - { - "type": "TouchWrapper", - "onPress": { - "type": "SendEvent", - "arguments": ["delegateToSkillOld"] - }, - "item": { - "type": "Text", - "id": "BookCabSimpleDialogAPL", - "paddingTop": "100", - "paddingLeft": "100", - "color": "green", - "size": 50, - "text": "delegateToSkillOld" - } - }, - { - "type": "TouchWrapper", - "onPress": { - "type": "SendEvent", - "arguments": ["delegateToColtraneNew"] - }, - "item": { - "type": "Text", - "id": "BookCabSimpleDialogAPL", - "paddingTop": "100", - "paddingLeft": "100", - "color": "green", - "size": 50, - "text": "delegateToColtraneNew" - } - }, - { - "type": "TouchWrapper", - "onPress": { - "type": "SendEvent", - "arguments": ["delegateToColtraneOld"] - }, - "item": { - "type": "Text", - "id": "BookCabSimpleDialogAPL", - "paddingTop": "100", - "paddingLeft": "100", - "color": "green", - "size": 50, - "text": "delegateToColtraneOld" - } - } - ] - } - ] - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/AlexaConversationsBye/document.json b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/AlexaConversationsBye/document.json deleted file mode 100644 index a0e2b3a8..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/AlexaConversationsBye/document.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": ["payload"], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "Bye.", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/AlexaConversationsNotifyFailure/document.json b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/AlexaConversationsNotifyFailure/document.json deleted file mode 100644 index 61d75e08..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/AlexaConversationsNotifyFailure/document.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": ["payload"], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "Sorry, there was an error in the request.", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/AlexaConversationsOutOfDomain/document.json b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/AlexaConversationsOutOfDomain/document.json deleted file mode 100644 index e23d5986..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/AlexaConversationsOutOfDomain/document.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": ["payload"], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "Sorry, I don't understand.", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/AlexaConversationsProvideHelp/document.json b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/AlexaConversationsProvideHelp/document.json deleted file mode 100644 index 612a6f6e..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/AlexaConversationsProvideHelp/document.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": ["payload"], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "I can give you the weather report. Just say \"what's the weather\" to start.", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/AlexaConversationsRequestMore/document.json b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/AlexaConversationsRequestMore/document.json deleted file mode 100644 index 32a98507..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/AlexaConversationsRequestMore/document.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": ["payload"], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "What do you want to do.", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/AlexaConversationsThankYou/document.json b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/AlexaConversationsThankYou/document.json deleted file mode 100644 index 4aeb6f4b..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/AlexaConversationsThankYou/document.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": ["payload"], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "Thank you.", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/AlexaConversationsWelcome/document.json b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/AlexaConversationsWelcome/document.json deleted file mode 100644 index 2b43c89b..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/AlexaConversationsWelcome/document.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": ["payload"], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "Welcome to the weatherOct16", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/AlexaConversationsYouAreWelcome/document.json b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/AlexaConversationsYouAreWelcome/document.json deleted file mode 100644 index 2cd1b9a8..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/AlexaConversationsYouAreWelcome/document.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": ["payload"], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "You are welcome.", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/SuccessGiveMeTodaySpecialsEvent_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/SuccessGiveMeTodaySpecialsEvent_apla/document.json deleted file mode 100644 index fe2a6876..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/SuccessGiveMeTodaySpecialsEvent_apla/document.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "APLA", - "version": "0.8", - "mainTemplate": { - "parameters": ["payload"], - "item": { - "type": "Selector", - "strategy": "randomItem", - "description": "Change 'type' above to try different Selector Component Types like Sequencer", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "today's special are ${payload.result.length} items , all items are ${payload.result}, first item is ${payload.result[0]}", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/SuccessGiveMeTodaySpecialsEvent_apla_failure/document.json b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/SuccessGiveMeTodaySpecialsEvent_apla_failure/document.json deleted file mode 100644 index 43a45860..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/SuccessGiveMeTodaySpecialsEvent_apla_failure/document.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "APLA", - "version": "0.8", - "mainTemplate": { - "parameters": ["payload"], - "item": { - "type": "Selector", - "strategy": "randomItem", - "description": "Change 'type' above to try different Selector Component Types like Sequencer", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "Failure : today's special are ${payload.result.length} items , all items are ${payload.result}, first item is ${payload.result[0]}", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/askForCrustPrompts/datasources/default.json b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/askForCrustPrompts/datasources/default.json deleted file mode 100644 index 0967ef42..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/askForCrustPrompts/datasources/default.json +++ /dev/null @@ -1 +0,0 @@ -{} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/askForCrustPrompts/document.json b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/askForCrustPrompts/document.json deleted file mode 100644 index f18d4e17..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/askForCrustPrompts/document.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "type": "APLA", - "version": "0.8", - "mainTemplate": { - "parameters": ["payload"], - "item": { - "type": "Selector", - "strategy": "randomItem", - "description": "Change 'type' above to try different Selector Component Types like Sequencer", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "On what kind of crust, we have thin, deep dish, regular and brooklyn style", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - }, - { - "type": "Speech", - "contentType": "text", - "content": "Ok, we have thin, deep dish, regular and brooklyn style, what would you like", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/askForSizePrompts/datasources/default.json b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/askForSizePrompts/datasources/default.json deleted file mode 100644 index 0967ef42..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/askForSizePrompts/datasources/default.json +++ /dev/null @@ -1 +0,0 @@ -{} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/askForSizePrompts/document.json b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/askForSizePrompts/document.json deleted file mode 100644 index 601c788f..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/askForSizePrompts/document.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "type": "APLA", - "version": "0.8", - "mainTemplate": { - "parameters": ["payload"], - "item": { - "type": "Selector", - "strategy": "randomItem", - "description": "Change 'type' above to try different Selector Component Types like Sequencer", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "What size? We have small, medium, large and extra large", - "description": "Prompt for size" - }, - { - "type": "Speech", - "contentType": "text", - "content": "Ok. We have small to extra large pizzas. What size would you like? ", - "description": "Prompt for size" - } - ] - } - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/askForToppingOnePrompt/datasources/default.json b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/askForToppingOnePrompt/datasources/default.json deleted file mode 100644 index 0967ef42..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/askForToppingOnePrompt/datasources/default.json +++ /dev/null @@ -1 +0,0 @@ -{} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/askForToppingOnePrompt/document.json b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/askForToppingOnePrompt/document.json deleted file mode 100644 index a0a43ab5..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/askForToppingOnePrompt/document.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "APLA", - "version": "0.8", - "mainTemplate": { - "parameters": ["payload"], - "item": { - "type": "Selector", - "strategy": "randomItem", - "description": "Change 'type' above to try different Selector Component Types like Sequencer", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "What would you like for the 1st topping?", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/askForToppingTwoPrompt/datasources/default.json b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/askForToppingTwoPrompt/datasources/default.json deleted file mode 100644 index 0967ef42..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/askForToppingTwoPrompt/datasources/default.json +++ /dev/null @@ -1 +0,0 @@ -{} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/askForToppingTwoPrompt/document.json b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/askForToppingTwoPrompt/document.json deleted file mode 100644 index a53aa22d..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/askForToppingTwoPrompt/document.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "APLA", - "version": "0.8", - "mainTemplate": { - "parameters": ["payload"], - "item": { - "type": "Selector", - "strategy": "randomItem", - "description": "Change 'type' above to try different Selector Component Types like Sequencer", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "What about the 2nd topping?", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/askForToppingsPrompts/datasources/default.json b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/askForToppingsPrompts/datasources/default.json deleted file mode 100644 index 0967ef42..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/askForToppingsPrompts/datasources/default.json +++ /dev/null @@ -1 +0,0 @@ -{} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/askForToppingsPrompts/document.json b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/askForToppingsPrompts/document.json deleted file mode 100644 index f1fea64d..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/askForToppingsPrompts/document.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "APLA", - "version": "0.8", - "mainTemplate": { - "parameters": ["payload"], - "item": { - "type": "Selector", - "strategy": "randomItem", - "description": "Change 'type' above to try different Selector Component Types like Sequencer", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "What would you like on your pizza?", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/askForTwoToppingsPrompts/datasources/default.json b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/askForTwoToppingsPrompts/datasources/default.json deleted file mode 100644 index 0967ef42..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/askForTwoToppingsPrompts/datasources/default.json +++ /dev/null @@ -1 +0,0 @@ -{} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/askForTwoToppingsPrompts/document.json b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/askForTwoToppingsPrompts/document.json deleted file mode 100644 index 7f961daf..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/askForTwoToppingsPrompts/document.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "APLA", - "version": "0.8", - "mainTemplate": { - "parameters": ["payload"], - "item": { - "type": "Selector", - "strategy": "randomItem", - "description": "Change 'type' above to try different Selector Component Types like Sequencer", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "Ok, what two toppings would you like?", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/askForTwoToppingsPrompts_copy/datasources/default.json b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/askForTwoToppingsPrompts_copy/datasources/default.json deleted file mode 100644 index 0967ef42..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/askForTwoToppingsPrompts_copy/datasources/default.json +++ /dev/null @@ -1 +0,0 @@ -{} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/askForTwoToppingsPrompts_copy/document.json b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/askForTwoToppingsPrompts_copy/document.json deleted file mode 100644 index 7f961daf..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/askForTwoToppingsPrompts_copy/document.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "APLA", - "version": "0.8", - "mainTemplate": { - "parameters": ["payload"], - "item": { - "type": "Selector", - "strategy": "randomItem", - "description": "Change 'type' above to try different Selector Component Types like Sequencer", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "Ok, what two toppings would you like?", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/confirmAction_complexNames_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/confirmAction_complexNames_apla/document.json deleted file mode 100644 index d2d72c41..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/confirmAction_complexNames_apla/document.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": ["payload"], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "confirm Action your cool name ${payload.name} and ${payload.sign}? ", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/confirmArgs_complexNames_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/confirmArgs_complexNames_apla/document.json deleted file mode 100644 index 4ada7688..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/confirmArgs_complexNames_apla/document.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": ["payload"], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "confirm args your cool name ${payload.name} and ${payload.sign}? ", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/confirmSizePrompt/datasources/default.json b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/confirmSizePrompt/datasources/default.json deleted file mode 100644 index c9c6423f..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/confirmSizePrompt/datasources/default.json +++ /dev/null @@ -1 +0,0 @@ -{"size": "extra large"} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/confirmSizePrompt/document.json b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/confirmSizePrompt/document.json deleted file mode 100644 index 070f8dba..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/confirmSizePrompt/document.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "APLA", - "version": "0.8", - "mainTemplate": { - "parameters": ["payload"], - "item": { - "type": "Sequencer", - "description": "Change 'type' above to try different Selector Component Types like Sequencer", - "items": [ - {"type": "Speech", "contentType": "text", "content": "You wanted "}, - { - "type": "Speech", - "when": "${payload.size == 'small' || payload.size == 'large' || payload.size == 'medium'}", - "content": "a ${payload.size} pizza, is that correct?" - }, - {"type": "Speech", "when": "${payload.size == 'extra large'}", "content": "an ${payload.size} pizza, is that correct?"} - ] - } - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/confirmTwoToppingOrderPrompt/datasources/default.json b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/confirmTwoToppingOrderPrompt/datasources/default.json deleted file mode 100644 index 0967ef42..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/confirmTwoToppingOrderPrompt/datasources/default.json +++ /dev/null @@ -1 +0,0 @@ -{} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/confirmTwoToppingOrderPrompt/document.json b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/confirmTwoToppingOrderPrompt/document.json deleted file mode 100644 index 25713921..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/confirmTwoToppingOrderPrompt/document.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "APLA", - "version": "0.8", - "mainTemplate": { - "parameters": ["payload"], - "item": { - "type": "Selector", - "strategy": "randomItem", - "description": "Change 'type' above to try different Selector Component Types like Sequencer", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "Ok, that's a ${payload.first_topping} and ${payload.second_topping} on ${payload.crust} crust. Is that correct?", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/confirmTwoToppingOrderPromptcopy/datasources/default.json b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/confirmTwoToppingOrderPromptcopy/datasources/default.json deleted file mode 100644 index 0967ef42..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/confirmTwoToppingOrderPromptcopy/datasources/default.json +++ /dev/null @@ -1 +0,0 @@ -{} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/confirmTwoToppingOrderPromptcopy/document.json b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/confirmTwoToppingOrderPromptcopy/document.json deleted file mode 100644 index 25c0e27b..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/confirmTwoToppingOrderPromptcopy/document.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "APLA", - "version": "0.8", - "mainTemplate": { - "parameters": ["payload"], - "item": { - "type": "Selector", - "strategy": "randomItem", - "description": "Change 'type' above to try different Selector Component Types like Sequencer", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "Ok, that's a ${payload.size} ${payload.first_topping} and ${payload.second_topping} on ${payload.crust} crust. Is that correct?", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/confirmTwoToppingsPrompt/datasources/default.json b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/confirmTwoToppingsPrompt/datasources/default.json deleted file mode 100644 index 0967ef42..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/confirmTwoToppingsPrompt/datasources/default.json +++ /dev/null @@ -1 +0,0 @@ -{} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/confirmTwoToppingsPrompt/document.json b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/confirmTwoToppingsPrompt/document.json deleted file mode 100644 index 00926d2b..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/confirmTwoToppingsPrompt/document.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "APLA", - "version": "0.8", - "mainTemplate": { - "parameters": ["payload"], - "item": { - "type": "Selector", - "strategy": "randomItem", - "description": "Change 'type' above to try different Selector Component Types like Sequencer", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "Just to confirm, you want ${payload.first_topping} and ${payload.second_topping}", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/confirm_color_for_fruit_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/confirm_color_for_fruit_apla/document.json deleted file mode 100644 index 62c9758b..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/confirm_color_for_fruit_apla/document.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": ["payload"], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "confirm color is ${payload.colorName} ? ", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/confirm_fruitName_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/confirm_fruitName_apla/document.json deleted file mode 100644 index 47433a49..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/confirm_fruitName_apla/document.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": ["payload"], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "confirm fruit ${payload.fruitName} ? ", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/confirm_main_addon_list_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/confirm_main_addon_list_apla/document.json deleted file mode 100644 index 113da0d0..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/confirm_main_addon_list_apla/document.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": ["payload"], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "confirm ${payload.foodName} with ${payload.addOn} ? ", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/confirm_weather_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/confirm_weather_apla/document.json deleted file mode 100644 index e63460da..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/confirm_weather_apla/document.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": ["payload"], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "Confirm weather forecast for ${payload.cityName} ${payload.date}?", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/confirm_weather_city_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/confirm_weather_city_apla/document.json deleted file mode 100644 index 498fa5f6..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/confirm_weather_city_apla/document.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": ["payload"], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "Confirm weather for ${payload.cityName}?", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/confirm_weather_date_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/confirm_weather_date_apla/document.json deleted file mode 100644 index b9102336..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/confirm_weather_date_apla/document.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": ["payload"], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "Confirm weather for ${payload.date}?", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/no_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/no_apla/document.json deleted file mode 100644 index 96a3af82..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/no_apla/document.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": ["payload"], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "I'm sorry you didn't like it", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/nothing2_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/nothing2_apla/document.json deleted file mode 100644 index af75a7a5..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/nothing2_apla/document.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": ["payload"], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "The number you gave us was not 3.", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/nothing_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/nothing_apla/document.json deleted file mode 100644 index bca77c74..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/nothing_apla/document.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": ["payload"], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "The number you gave us was 3.", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/numericfeedback_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/numericfeedback_apla/document.json deleted file mode 100644 index 2219120c..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/numericfeedback_apla/document.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": ["payload"], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "Your random number was ${payload.num}. How did we do? Please give this interaction a rating between 1-5, where 5 is the highest rating", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/rating_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/rating_apla/document.json deleted file mode 100644 index 06b50d68..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/rating_apla/document.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": ["payload"], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "rating please?", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/requestArgs_request_fruitName_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/requestArgs_request_fruitName_apla/document.json deleted file mode 100644 index 5e5d608a..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/requestArgs_request_fruitName_apla/document.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": ["payload"], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "tell me the fruit name ?", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - }, - { - "type": "Speech", - "contentType": "text", - "content": "random slection tell me the fruit name ?", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/requestFromBookFlight_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/requestFromBookFlight_apla/document.json deleted file mode 100644 index db1436d6..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/requestFromBookFlight_apla/document.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "APLA", - "version": "0.8", - "mainTemplate": { - "parameters": ["payload"], - "item": { - "type": "Selector", - "strategy": "randomItem", - "description": "Change 'type' above to try different Selector Component Types like Sequencer", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "from where?", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/requestPickUpFromBookCab_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/requestPickUpFromBookCab_apla/document.json deleted file mode 100644 index 7e4c3ef7..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/requestPickUpFromBookCab_apla/document.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "APLA", - "version": "0.8", - "mainTemplate": { - "parameters": ["payload"], - "item": { - "type": "Selector", - "strategy": "randomItem", - "description": "Change 'type' above to try different Selector Component Types like Sequencer", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "request PickUp From BookCab apla, from where ?", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/requestToBookFlight_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/requestToBookFlight_apla/document.json deleted file mode 100644 index aa9e23b0..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/requestToBookFlight_apla/document.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "APLA", - "version": "0.8", - "mainTemplate": { - "parameters": ["payload"], - "item": { - "type": "Selector", - "strategy": "randomItem", - "description": "Change 'type' above to try different Selector Component Types like Sequencer", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "to where ?", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/request_city_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/request_city_apla/document.json deleted file mode 100644 index 64297b5e..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/request_city_apla/document.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": ["payload"], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "Which city?", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/request_city_cityName_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/request_city_cityName_apla/document.json deleted file mode 100644 index 1bf948d1..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/request_city_cityName_apla/document.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": ["payload"], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "Which city?", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - }, - { - "type": "Speech", - "contentType": "text", - "content": "random selector Which city?", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/request_city_cityName_date_AMAZON_DATE_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/request_city_cityName_date_AMAZON_DATE_apla/document.json deleted file mode 100644 index a55ea5e1..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/request_city_cityName_date_AMAZON_DATE_apla/document.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": ["payload"], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "Which city and for which date?", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/request_colorName_multiple_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/request_colorName_multiple_apla/document.json deleted file mode 100644 index 5e5891e1..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/request_colorName_multiple_apla/document.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": ["payload"], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "which color?", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/request_date_AMAZON_DATE_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/request_date_AMAZON_DATE_apla/document.json deleted file mode 100644 index af3a3f7d..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/request_date_AMAZON_DATE_apla/document.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": ["payload"], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "Which date?", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/request_date_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/request_date_apla/document.json deleted file mode 100644 index af3a3f7d..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/request_date_apla/document.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": ["payload"], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "Which date?", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/request_listAddOns_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/request_listAddOns_apla/document.json deleted file mode 100644 index 50faed8e..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/request_listAddOns_apla/document.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": ["payload"], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "what are the add ons?", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/request_mainFoodName_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/request_mainFoodName_apla/document.json deleted file mode 100644 index 316161b3..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/request_mainFoodName_apla/document.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": ["payload"], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "What is the main food name?", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/request_name_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/request_name_apla/document.json deleted file mode 100644 index db05dfee..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/request_name_apla/document.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": ["payload"], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "SSML", - "content": "what is your cool name?", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/request_sign_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/request_sign_apla/document.json deleted file mode 100644 index b96b84ce..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/request_sign_apla/document.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": ["payload"], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "SSML", - "content": "which sign", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/requestdropToBookCab_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/requestdropToBookCab_apla/document.json deleted file mode 100644 index aa9e23b0..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/requestdropToBookCab_apla/document.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "APLA", - "version": "0.8", - "mainTemplate": { - "parameters": ["payload"], - "item": { - "type": "Selector", - "strategy": "randomItem", - "description": "Change 'type' above to try different Selector Component Types like Sequencer", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "to where ?", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/secondEarthAPI_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/secondEarthAPI_apla/document.json deleted file mode 100644 index 263c095a..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/secondEarthAPI_apla/document.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": ["payload"], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "success delegating", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/seq_offer_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/seq_offer_apla/document.json deleted file mode 100644 index 09c06d67..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/seq_offer_apla/document.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": ["payload"], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "sequence offer , lets find fav color by sign and name?", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/successBookCabAPI_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/successBookCabAPI_apla/document.json deleted file mode 100644 index 830fcf43..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/successBookCabAPI_apla/document.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "APLA", - "version": "0.8", - "mainTemplate": { - "parameters": ["payload"], - "item": { - "type": "Selector", - "strategy": "randomItem", - "description": "Change 'type' above to try different Selector Component Types like Sequencer", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "Booked cab is ${payload.result.orderStatus}", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/successBookFlightAPI_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/successBookFlightAPI_apla/document.json deleted file mode 100644 index 46c6daf3..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/successBookFlightAPI_apla/document.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "APLA", - "version": "0.8", - "mainTemplate": { - "parameters": ["payload"], - "item": { - "type": "Selector", - "strategy": "randomItem", - "description": "Change 'type' above to try different Selector Component Types like Sequencer", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "booked flight is ${payload.resultTwo.orderStatus} from ${payload.resultTwo.source} to ${payload.resultTwo.destination}, do you need cab to airport ?", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/success_cookingAPI_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/success_cookingAPI_apla/document.json deleted file mode 100644 index 2b920b3d..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/success_cookingAPI_apla/document.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": ["payload"], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "we have ${payload.status.orderStatus}", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/success_favColorSign_Name_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/success_favColorSign_Name_apla/document.json deleted file mode 100644 index 65211056..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/success_favColorSign_Name_apla/document.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": ["payload"], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "Fav color of ${payload.result.name}, is ${payload.result.color}", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/success_fruitPriceAPI_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/success_fruitPriceAPI_apla/document.json deleted file mode 100644 index 0db81389..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/success_fruitPriceAPI_apla/document.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": ["payload"], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "price of an ${payload.result.fruitName} is ${payload.result.price} bucks ", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/twoToppingOrderSuccessPrompt/datasources/default.json b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/twoToppingOrderSuccessPrompt/datasources/default.json deleted file mode 100644 index 0967ef42..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/twoToppingOrderSuccessPrompt/datasources/default.json +++ /dev/null @@ -1 +0,0 @@ -{} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/twoToppingOrderSuccessPrompt/document.json b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/twoToppingOrderSuccessPrompt/document.json deleted file mode 100644 index 24236a39..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/twoToppingOrderSuccessPrompt/document.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "APLA", - "version": "0.8", - "mainTemplate": { - "parameters": ["payload"], - "item": { - "type": "Selector", - "strategy": "randomItem", - "description": "Change 'type' above to try different Selector Component Types like Sequencer", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "${payload.speech}", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/weather_success_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/weather_success_apla/document.json deleted file mode 100644 index 21441101..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/weather_success_apla/document.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": ["payload"], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "when": "${payload.weatherResult.cityName != null && payload.weatherResult.highTemp < 3 && payload.weatherResult.lowTemp > 0}", - "type": "Speech", - "contentType": "text", - "content": "Offer In ${payload.weatherResult.cityName}, it's a high of ${payload.weatherResult.highTemp} degrees and a low of ${payload.weatherResult.lowTemp} degrees.", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - }, - { - "when": "${payload.weatherResult.cityName != null && payload.weatherResult.highTemp == null && payload.weatherResult.lowTemp == null}", - "type": "Speech", - "contentType": "text", - "content": "Alternate In ${payload.weatherResult.cityName}, it's a high of ${payload.weatherResult.highTemp} degrees and a low of ${payload.weatherResult.lowTemp} degrees.", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/welcome_apla_custom/document.json b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/welcome_apla_custom/document.json deleted file mode 100644 index 20c5a48c..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/response/prompts/welcome_apla_custom/document.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": ["payload"], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "Hi Satheesh , you have visited ${payload.result}", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/skill.json b/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/skill.json deleted file mode 100644 index 1cc857f9..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-2/skill-package/skill.json +++ /dev/null @@ -1,93 +0,0 @@ -{ - "manifest": { - "apis": { - "custom": { - "dialogManagement": { - "dialogManagers": [ - { - "type": "AMAZON.Conversations" - } - ], - "sessionStartDelegationStrategy": { - "target": "AMAZON.Conversations" - } - }, - "endpoint": { - "uri": "arn:aws:lambda:us-east-1:658396899051:function:a3588a9b-d645-4a23-9e1a-90c984de0b83:Release_0" - }, - "interfaces": [ - { - "supportedViewports": [ - { - "maxHeight": 480, - "maxWidth": 480, - "minHeight": 480, - "minWidth": 480, - "mode": "HUB", - "shape": "ROUND" - }, - { - "maxHeight": 600, - "maxWidth": 1024, - "minHeight": 600, - "minWidth": 1024, - "mode": "HUB", - "shape": "RECTANGLE" - }, - { - "maxHeight": 800, - "maxWidth": 1280, - "minHeight": 800, - "minWidth": 1280, - "mode": "HUB", - "shape": "RECTANGLE" - }, - { - "maxHeight": 540, - "maxWidth": 960, - "minHeight": 540, - "minWidth": 960, - "mode": "TV", - "shape": "RECTANGLE" - } - ], - "type": "ALEXA_PRESENTATION_APL" - } - ], - "regions": { - "EU": { - "endpoint": { - "uri": "arn:aws:lambda:eu-west-1:658396899051:function:a3588a9b-d645-4a23-9e1a-90c984de0b83:Release_0" - } - }, - "NA": { - "endpoint": { - "uri": "arn:aws:lambda:us-east-1:658396899051:function:a3588a9b-d645-4a23-9e1a-90c984de0b83:Release_0" - } - }, - "FE": { - "endpoint": { - "uri": "arn:aws:lambda:us-west-2:658396899051:function:a3588a9b-d645-4a23-9e1a-90c984de0b83:Release_0" - } - } - } - } - }, - "manifestVersion": "1.0", - "publishingInformation": { - "category": "KNOWLEDGE_AND_TRIVIA", - "distributionCountries": [], - "isAvailableWorldwide": true, - "locales": { - "en-US": { - "description": "Sample Full Description", - "examplePhrases": ["Alexa open hello world", "hello", "help"], - "keywords": [], - "name": "engineering test skill two", - "summary": "Sample Short Description" - } - }, - "testingInstructions": "Sample Testing Instructions." - } - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-3/.ask/ask-states.json b/test/unit/fixture/dialog-evaluate/test-project-3/.ask/ask-states.json deleted file mode 100644 index 18048d0e..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-3/.ask/ask-states.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "askcliStatesVersion": "2020-03-31", - "profiles": { - "TEST_PROFILE": { - "skillId": "TEST_SKILL_ID" - } - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-3/ask-resources.json b/test/unit/fixture/dialog-evaluate/test-project-3/ask-resources.json deleted file mode 100644 index 649c901b..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-3/ask-resources.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "askcliResourcesVersion": "2020-03-31", - "profiles": { - "TEST_PROFILE": { - "skillMetadata": { - "src": "./skill-package" - } - } - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/TestDataACDLi18n/deBye/document.json b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/TestDataACDLi18n/deBye/document.json deleted file mode 100644 index 5927b675..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/TestDataACDLi18n/deBye/document.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "type": "APLA", - "version": "0.8", - "mainTemplate": { - "parameters": ["payload"], - "item": { - "type": "Selector", - "strategy": "randomItem", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "Tschüss satheesh" - } - ] - } - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/TestDataACDLi18n/deHelp/document.json b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/TestDataACDLi18n/deHelp/document.json deleted file mode 100644 index 777cc487..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/TestDataACDLi18n/deHelp/document.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "type": "APLA", - "version": "0.8", - "mainTemplate": { - "parameters": ["payload"], - "item": { - "type": "Selector", - "strategy": "randomItem", - "description": "Change \u0027type\u0027 above to try different Selector Component Types like Sequencer", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "Hilfe leisten satheesh" - } - ] - } - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/TestDataACDLi18n/deOutOfDomain/datasources/default.json b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/TestDataACDLi18n/deOutOfDomain/datasources/default.json deleted file mode 100644 index 0967ef42..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/TestDataACDLi18n/deOutOfDomain/datasources/default.json +++ /dev/null @@ -1 +0,0 @@ -{} diff --git a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/TestDataACDLi18n/deOutOfDomain/document.json b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/TestDataACDLi18n/deOutOfDomain/document.json deleted file mode 100644 index e00dc420..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/TestDataACDLi18n/deOutOfDomain/document.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "type": "APLA", - "version": "0.8", - "mainTemplate": { - "parameters": ["payload"], - "item": { - "type": "Selector", - "strategy": "randomItem", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "Entschuldigung, ich verstehe Satheesh nicht" - } - ] - } - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/TestDataACDLi18n/deRequireMore/document.json b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/TestDataACDLi18n/deRequireMore/document.json deleted file mode 100644 index 3d7c5e01..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/TestDataACDLi18n/deRequireMore/document.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "type": "APLA", - "version": "0.8", - "mainTemplate": { - "parameters": ["payload"], - "item": { - "type": "Selector", - "strategy": "randomItem", - "items": [ - { - "description": "This template is emitted after we deny an API. Since we only have one, this is functionally equivalent to needing to request the city again.", - "type": "Speech", - "contentType": "text", - "content": "mehr benötigen satheesh" - } - ] - } - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/TestDataACDLi18n/deWelcome/document.json b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/TestDataACDLi18n/deWelcome/document.json deleted file mode 100644 index 9ba7f62f..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/TestDataACDLi18n/deWelcome/document.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "type": "APLA", - "version": "0.8", - "mainTemplate": { - "parameters": ["payload"], - "item": { - "type": "Selector", - "strategy": "randomItem", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "Willkommen meinen König Satheesh" - } - ] - } - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/conversations/ALexaPrize.acdl b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/conversations/ALexaPrize.acdl deleted file mode 100644 index 086efb02..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/conversations/ALexaPrize.acdl +++ /dev/null @@ -1,203 +0,0 @@ -namespace com.alexaprize - -import com.amazon.alexa.ask.conversations.Affirm -import com.amazon.alexa.ask.conversations.Deny -import com.amazon.alexa.ask.conversations.Invoke -import com.amazon.alexa.ask.conversations.Notify -import com.amazon.alexa.ask.conversations.Offer -import com.amazon.alexa.ask.conversations.expect -import com.amazon.alexa.ask.conversations.response -import com.amazon.alexa.ask.conversations.utterances -import com.amazon.alexa.schema.Boolean -import com.amazon.alexa.schema.Nothing -import com.amazon.alexa.schema.String -import com.amazon.ask.types.builtins.AMAZON.NUMBER -import prompts.alexa_prize_preconditions_apla -import slotTypes.TopicType - -type ConversationDetails { - optional TopicType Topic -} - -letsChatEvent = utterances( - samples = [ - "let's chat", - "i want to chat", - "chat", - "talk", - "let's chat about {Topic}", - "i want to talk about {Topic}", - "can we talk about {Topic}" - ] -) - -affirmEvent = utterances( - samples = [ - "yes", - "yup", - "yeah", - "sure", - "alright" - ] -) - -denyEvent = utterances( - samples = [ - "no", - "nope", - "not really", - "not", - "naah" - ] -) - -type AlexaPrizePreconditions { - NUMBER isLocaleSupported - NUMBER isDeviceSupported - NUMBER isFalseWake - NUMBER isSocialBotAvailable - NUMBER isAlexaPrizeEnabled - NUMBER isTopicBanned - String handoffPromptOverride -} - -type AlexaPrizePreconditionsPayload { - AlexaPrizePreconditions result -} - -type HandoffResults { - String handoffPromptOverride -} - -type HandoffResultsPayload { - HandoffResults result -} - -action AlexaPrizePreconditions checkPreconditionsAndHandoff(TopicType Topic = nothing) - -action HandoffResults intentConfirmedHandoff() - -action HandoffResults intentDeniedHandoff() - -dialog Nothing AlexaPrizeDialog() { - sample { - preconditionsResult = checkPrecondition() - isHandoffPossible = (((preconditionsResult.isDeviceSupported == 1 && preconditionsResult.isLocaleSupported == 1) && preconditionsResult.isSocialBotAvailable == 1) && preconditionsResult.isAlexaPrizeEnabled == 1) - if (isHandoffPossible) { - isConfirmationNeeded = (preconditionsResult.isFalseWake == 1 || preconditionsResult.isTopicBanned == 1) - responses( - isConfirmationNeeded = isConfirmationNeeded, - preconditionsResult = preconditionsResult - ) - } else { - response( - response = alexa_prize_preconditions_apla, - act = Notify { - actionName = checkPreconditionsAndHandoff, - success = false - }, - payload = AlexaPrizePreconditionsPayload { - result = preconditionsResult - } - ) - } - } -} - -dialog AlexaPrizePreconditions checkPrecondition() { - sample { - chatRequest = expect( - act = Invoke, - event = letsChatEvent - ) - checkPreconditionsAndHandoff( - Topic = chatRequest.Topic - ) - } - sample { - expect( - act = Invoke, - event = letsChatEvent - ) - preconditionsResult = checkPreconditionsAndHandoff() - } -} - -dialog Nothing responses(Boolean isConfirmationNeeded, AlexaPrizePreconditions preconditionsResult) { - sample { - if (isConfirmationNeeded) { - handoffResult( - preconditionsResult = preconditionsResult - ) - } else { - response( - response = alexa_prize_preconditions_apla, - act = Notify { - actionName = checkPreconditionsAndHandoff - }, - payload = AlexaPrizePreconditionsPayload { - result = preconditionsResult - } - ) - } - } -} - -dialog Nothing handoffResult(AlexaPrizePreconditions preconditionsResult) { - sample { - response( - response = alexa_prize_preconditions_apla, - act = Notify { - actionName = checkPreconditionsAndHandoff - }, - nextAct = Offer { - actionName = intentConfirmedHandoff - }, - payload = AlexaPrizePreconditionsPayload { - result = preconditionsResult - } - ) - expect( - act = Affirm, - event = affirmEvent - ) - handoffResults = intentConfirmedHandoff() - response( - response = alexa_prize_preconditions_apla, - act = Notify { - actionName = intentConfirmedHandoff - }, - payload = HandoffResultsPayload { - result = handoffResults - } - ) - } - sample { - response( - response = alexa_prize_preconditions_apla, - act = Notify { - actionName = checkPreconditionsAndHandoff - }, - nextAct = Offer { - actionName = intentDeniedHandoff - }, - payload = AlexaPrizePreconditionsPayload { - result = preconditionsResult - } - ) - expect( - act = Deny, - event = denyEvent - ) - handoffResults = intentDeniedHandoff() - response( - response = alexa_prize_preconditions_apla, - act = Notify { - actionName = intentDeniedHandoff - }, - payload = HandoffResultsPayload { - result = handoffResults - } - ) - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/conversations/Dialog_NonDeployable.acdl b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/conversations/Dialog_NonDeployable.acdl deleted file mode 100644 index 275632d7..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/conversations/Dialog_NonDeployable.acdl +++ /dev/null @@ -1,81 +0,0 @@ -namespace dialogs_non_deployable - -import apis.getEmployeeDetails -import com.amazon.alexa.ask.conversations.Inform -import com.amazon.alexa.ask.conversations.Request -import com.amazon.alexa.ask.conversations.expect -import com.amazon.alexa.ask.conversations.response -import com.amazon.ask.types.builtins.AMAZON.DATE -import com.amazon.ask.types.builtins.AMAZON.NUMBER -import prompts.request_dob_getDate_apla -import prompts.request_getEmploeeID_apla -import prompts.request_name_apla -import slotTypes.complexNames -import types.complexResult -import utteracesets.informComplexNameEvent -import utteracesets.informDOBEvent -import utteracesets.informEmployeeIDEvent - -dialog complexNames getName() { - sample { - response( - response = request_name_apla, - act = Request { - arguments = [ - getEmployeeDetails.arguments.name1 - ] - } - ) - complexNamesReturn = expect( - act = Inform, - event = informComplexNameEvent - ) - complexNamesReturn.name - } -} - -dialog NUMBER getEmploeeID() { - sample { - response( - response = request_getEmploeeID_apla, - act = Request { - arguments = [ - getEmployeeDetails.arguments.emplyee1id - ] - } - ) - empID = expect( - act = Inform, - event = informEmployeeIDEvent - ) - empID.emplyee1id - } -} - -dialog DATE getDate() { - sample { - response( - response = request_dob_getDate_apla, - act = Request { - arguments = [ - getEmployeeDetails.arguments.a_dateOfBirth - ] - } - ) - dobEvent = expect( - act = Inform, - event = informDOBEvent - ) - dobEvent.a_dateOfBirth - } -} - -dialog complexResult a_getEmployeeDetails(complexNames name1, NUMBER emplyee1id, DATE a_dateOfBirth) { - sample { - complexResultEvent = getEmployeeDetails( - name1 = name1, - emplyee1id = emplyee1id, - a_dateOfBirth = a_dateOfBirth - ) - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/conversations/Dialogs_reusableDialogsUsage_NonDeployableDialogs.acdl b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/conversations/Dialogs_reusableDialogsUsage_NonDeployableDialogs.acdl deleted file mode 100644 index 3132c271..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/conversations/Dialogs_reusableDialogsUsage_NonDeployableDialogs.acdl +++ /dev/null @@ -1,50 +0,0 @@ -namespace reusableDialogs.NonDeployableDialogs - -import apis.getEmployeeDetails -import com.amazon.alexa.ask.conversations.Invoke -import com.amazon.alexa.ask.conversations.Notify -import com.amazon.alexa.ask.conversations.expect -import com.amazon.alexa.ask.conversations.response -import com.amazon.alexa.schema.Nothing -import dialogs_non_deployable.a_getEmployeeDetails -import dialogs_non_deployable.getDate -import dialogs_non_deployable.getEmploeeID -import dialogs_non_deployable.getName -import prompts.getEmployeePosition_success_apla -import types.complexResult -import utteracesets.who_are_you -import slotTypes.* -import prompts.* -import displays.* -import com.amazon.ask.types.builtins.AMAZON.* -import com.amazon.alexa.schema.* -import com.amazon.alexa.ask.conversations.* -type PayLoadresult { - complexResult result -} - -dialog Nothing dilaog_getEmployeePosition() { - sample { - expect( - act = Invoke, - event = who_are_you - ) - complexNamesEvent = getName() - NUMBEREvent = getEmploeeID() - DATEEvent = getDate() - resultOne = a_getEmployeeDetails( - name1 = complexNamesEvent, - emplyee1id = NUMBEREvent, - a_dateOfBirth = DATEEvent - ) - response( - response = getEmployeePosition_success_apla, - act = Notify { - actionName = getEmployeeDetails - }, - payload = PayLoadresult { - result = resultOne - } - ) - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/conversations/Weather.acdl b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/conversations/Weather.acdl deleted file mode 100644 index dea04349..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/conversations/Weather.acdl +++ /dev/null @@ -1,152 +0,0 @@ -namespace com.weatherbot - -import com.amazon.alexa.ask.conversations.Invoke -import com.amazon.alexa.ask.conversations.Notify -import com.amazon.alexa.ask.conversations.RequestArguments -import com.amazon.alexa.ask.conversations.ensure -import com.amazon.alexa.ask.conversations.expect -import com.amazon.alexa.ask.conversations.response -import com.amazon.alexa.ask.conversations.utterances -import com.amazon.alexa.schema.Nothing -import com.amazon.alexa.schema.Thing -import com.amazon.ask.types.builtins.AMAZON.DATE -import com.amazon.ask.types.builtins.AMAZON.NUMBER -import com.amazon.ask.types.builtins.AMAZON.US_CITY -import prompts.request_city_apla -import prompts.request_date_apla - -import slotTypes.* -import prompts.* -import displays.* -import com.amazon.ask.types.builtins.AMAZON.* -import com.amazon.alexa.schema.* -import com.amazon.alexa.ask.conversations.* - -type CityAndDate { - optional myCustomCities cityNameChanged - optional US_CITY cityName - optional DATE date -} - - -@locale(Locale.en_US) -getWeatherEvent_enUS = utterances( - samples = [ - "What's the weather {date} in {cityNameChanged}", - "What's the weather {date} in {cityName}", - "What is the weather {date} in {cityName}", - "what is the weather {date}", - "how is weather" - ] -) - - -@locale(Locale.de_DE) -getWeatherEvent_deDE = utterances( - samples = [ - "Wie ist das wetter {date} in {cityNameChanged}", - "wie ist das wetter {date} in {cityName}", - "wie ist das wetter {date}", - "wie ist das wetter" - ] -) - -getWeatherEvent = variations(getWeatherEvent_enUS,getWeatherEvent_deDE) - -@locale(Locale.en_US) -weather_apla_en = apla("../../skill-package/response/prompts/weather_apla") - -@locale(Locale.de_DE) -weather_apla_de = apla("../../skill-package/response/prompts/weather_apla_de_apla") - -weather_apla_apla_apla = variations(weather_apla_en,weather_apla_de) - - -type cityNameshell{ - US_CITY cityName -} - -@locale(Locale.en_US) -weather_apl_visual_en = apl("../../skill-package/response/display/confirm_weather_apla_display") - -@locale(Locale.de_DE) -weather_apl_visual_de = apl ("../../skill-package/response/display/display_de_apl") - -weather_apl_visual = variations(weather_apl_visual_en, weather_apl_visual_de) - -weather_apla_var = MultiModalResponse (apla = weather_apla_apla_apla, apl = weather_apl_visual) - -/* -what's the weather today in seattle -what is the weather today in madurai -what's the weather today in chennai -what's the weather today in speaker - -*/ - - - -type WeatherResult { - optional myCustomCities cityNameChanged - optional US_CITY cityName - NUMBER highTemp - NUMBER lowTemp -} - -type ResponsePayload { - WeatherResult weatherResult -} - -action WeatherResult getWeather(DATE date, US_CITY cityName = nothing, myCustomCities cityNameChanged = nothing) - -dialog Nothing Weather() { - sample { - weatherRequest = expect(act = Invoke,event = getWeatherEvent) - ensure( -requestArgs = [ - RequestArguments {arguments = [ getWeather.arguments.cityNameChanged],response = request_city_apla}, - RequestArguments {arguments = [ getWeather.arguments.cityName],response = request_city_apla}, - RequestArguments { arguments = [getWeather.arguments.date],response = request_date_apla} - ] - ) - weatherResult = getWeather(date = weatherRequest.date, cityName = weatherRequest.cityName) - response( - response = weather_apla_var, - act = Notify {actionName = getWeather}, - payload = ResponsePayload { weatherResult = weatherResult} - ) - } - - sample { - weatherRequest = expect(act = Invoke,event = getWeatherEvent) - ensure( -requestArgs = [ - RequestArguments {arguments = [ getWeather.arguments.cityNameChanged],response = request_city_apla}, - RequestArguments {arguments = [ getWeather.arguments.cityName],response = request_city_apla}, - RequestArguments { arguments = [getWeather.arguments.date],response = request_date_apla} - ] - ) - weatherResult = getWeather(date = weatherRequest.date, cityNameChanged = weatherRequest.cityNameChanged) - response( - response = weather_apla_var, - act = Notify {actionName = getWeather}, - payload = ResponsePayload { weatherResult = weatherResult} - ) - } -} - -dialog Nothing ComplexTest() { - sample { - Weather() - } -} - - - -type weatherRequestEvent0 { - optional myCustomCities cityNameChanged - optional US_CITY cityName - DATE date -} - - diff --git a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/conversations/apis.acdl b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/conversations/apis.acdl deleted file mode 100644 index 22e0beb9..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/conversations/apis.acdl +++ /dev/null @@ -1,17 +0,0 @@ -namespace apis - -import com.amazon.alexa.schema.Nothing -import com.amazon.ask.types.builtins.AMAZON.DATE -import com.amazon.ask.types.builtins.AMAZON.NUMBER -import slotTypes.complexNames -import slotTypes.signs -import types.complexResult -import types.result_one -import com.amazon.alexa.ask.conversations.* - -action Nothing secondEarthAPI() - -action result_one favColorSign_Name(complexNames name, signs sign = nothing) - - -action complexResult getEmployeeDetails(complexNames name1, NUMBER emplyee1id, DATE a_dateOfBirth = nothing) diff --git a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/conversations/apisNamepaceLambda.acdl b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/conversations/apisNamepaceLambda.acdl deleted file mode 100644 index 5fcdf369..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/conversations/apisNamepaceLambda.acdl +++ /dev/null @@ -1,23 +0,0 @@ -namespace com.weatherbot.apis - -import com.amazon.ask.types.builtins.AMAZON.Color -import com.amazon.ask.types.builtins.AMAZON.Food -import com.amazon.ask.types.builtins.AMAZON.NUMBER -import slotTypes.* - -type result { - Food fruitName - NUMBER price -} - -type payloadgetFruitPriceEvent { - result result -} - -action result fruitNameAPI(Food fruitName) - -action resultthree colorFruitName(myColors colorName) - -type resultthree { - Food fruitName -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/conversations/conversation_empty.acdl b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/conversations/conversation_empty.acdl deleted file mode 100644 index 4189bdda..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/conversations/conversation_empty.acdl +++ /dev/null @@ -1,114 +0,0 @@ -namespace com.numberbot - -import com.amazon.alexa.ask.conversations.APLA -import com.amazon.alexa.ask.conversations.Action -import com.amazon.alexa.ask.conversations.Bye -import com.amazon.alexa.ask.conversations.Invoke -import com.amazon.alexa.ask.conversations.Notify -import com.amazon.alexa.ask.conversations.Offer -import com.amazon.alexa.ask.conversations.RequestArguments -import com.amazon.alexa.ask.conversations.ensure -import com.amazon.alexa.ask.conversations.expect -import com.amazon.alexa.ask.conversations.response -import com.amazon.alexa.ask.conversations.utterances -import com.amazon.alexa.schema.Nothing -import com.amazon.alexa.schema.Number -import com.amazon.alexa.schema.Thing -import com.amazon.ask.types.builtins.AMAZON.NUMBER -import prompts.AlexaConversationsBye -import prompts.numericfeedback_apla -import prompts.rating_apla - -type NumPayload { - Number num -} - -type RatingRequest { - NUMBER rating -} - -InformRatingEvent = utterances( - samples = [ - "my score is {rating}", - "that was a {rating} conversation", - "i rate you a {rating}", - "{rating}" - ] -) - -getStart = utterances( - samples = [ - "give me a number please" - ] -) - -action Nothing saveRating(Number rating) - -action Number getNumber() - -dialog Nothing GetFeedback(APLA feedback_prompt, Number num, Action notifyAction) { - sample { - response( - response = feedback_prompt, - act = Notify { - actionName = notifyAction, - success = true - }, - nextAct = Offer { - actionName = saveRating, - arguments = [ - saveRating.arguments.rating - ] - }, - payload = NumPayload { - num = num - } - ) - myRating = expect( - act = Invoke, - event = InformRatingEvent - ) - ensure( - requestArgs = [ - RequestArguments { - arguments = [ - saveRating.arguments.rating - ], - response = rating_apla - } - ] - ) - saveRating( - rating = myRating.rating - ) - } -} - -dialog Number levelOne() { - sample { - expect( - act = Invoke, - event = getStart - ) - num = getNumber() - } -} - -dialog Nothing MainDialog() { - sample { - num = levelOne() - GetFeedback( - feedback_prompt = numericfeedback_apla, - num = num, - notifyAction = getNumber - ) - response( - response = AlexaConversationsBye, - act = Notify { - actionName = saveRating, - success = true - }, - nextAct = Bye {} - ) - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/conversations/fruitNameApi.acdl b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/conversations/fruitNameApi.acdl deleted file mode 100644 index 4664f2f2..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/conversations/fruitNameApi.acdl +++ /dev/null @@ -1,34 +0,0 @@ -namespace test - -import com.amazon.alexa.ask.conversations.utterances -import com.amazon.ask.types.builtins.AMAZON.Food - -type fruitNameShell { - Food fruitName -} - -type paylaodCompleFruit { - Food fruitName -} - -getFruitPriceEvent = utterances( - samples = [ - "what is the price of the fruit", - "what is the price of fruit" - ] -) - -informfruitNameEvent = utterances( - samples = [ - "{fruitName}", - "fruit name is {fruitName}", - "fruit is {fruitName}" - ] -) - -affirmFruitAPIEvent = utterances( - samples = [ - "uh huh", - "yup" - ] -) diff --git a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/conversations/separateConfig.acdl b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/conversations/separateConfig.acdl deleted file mode 100644 index be06ae17..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/conversations/separateConfig.acdl +++ /dev/null @@ -1,98 +0,0 @@ -namespace configSkill - -import com.amazon.alexa.ask.conversations.skill -import com.amazon.alexa.ask.conversations.variations - -import com.amazon.alexa.ask.conversations.apla -import com.amazon.alexa.ask.conversations.apl -import com.amazon.alexa.ask.conversations.MultiModalResponse -import com.amazon.alexa.ask.conversations.Locale -import com.amazon.alexa.ask.conversations.locale -import com.amazon.alexa.ask.conversations.SkillLevelResponses -import com.amazon.alexa.ask.conversations.InvocationName - -import com.weatherbot.Weather -import soaACDl.sOA - -@locale(Locale.de_DE) -welcome_de = apla("../../skill-package/TestDataACDLi18n/deWelcome") - -@locale(Locale.en_US, Locale.de_DE) -welcome_en_apl_tap = apl("../../skill-package/response/display/confirm_city_apl_display") - -welcome_apl = variations(welcome_en_apl_tap) - -@locale(Locale.en_US) -welcome_en = apla("../../skill-package/response/prompts/AlexaConversationsWelcome") -combo_apla_welcome = variations( welcome_en , welcome_de) - - -@locale(Locale.en_US) -out_of_domain_en = apla("../../skill-package/response/prompts/AlexaConversationsOutOfDomain") -@locale(Locale.en_US) -bye_en = apla("../../skill-package/response/prompts/AlexaConversationsBye") -@locale(Locale.en_US) -reqmore_en = apla("../../skill-package/response/prompts/AlexaConversationsRequestMore") -@locale(Locale.en_US) -provide_help_en = apla("../../skill-package/response/prompts/AlexaConversationsProvideHelp") - - -@locale(Locale.es_US) -welcome_es_US = apla("../../skill-package/response/prompts/AlexaConversationsWelcome") -@locale(Locale.es_US) -out_of_domain_es_US = apla("../../skill-package/response/prompts/AlexaConversationsOutOfDomain") -@locale(Locale.es_US) -bye_es_US = apla("../../skill-package/response/prompts/AlexaConversationsBye") -@locale(Locale.es_US) -reqmore_es_US = apla("../../skill-package/response/prompts/AlexaConversationsRequestMore") -@locale(Locale.es_US) -provide_help_es_US = apla("../../skill-package/response/prompts/AlexaConversationsProvideHelp") - - - -@locale(Locale.de_DE) -out_of_domain_de = apla("../../skill-package/TestDataACDLi18n/deOutOfDomain") -out_of_domainResponse = variations(out_of_domain_en, out_of_domain_de, out_of_domain_es_US) - -@locale(Locale.de_DE) -bye_de = apla("../../skill-package/TestDataACDLi18n/deBye") -byeResponse = variations(bye_en, bye_de, bye_es_US) - -@locale(Locale.de_DE) -reqmore_de = apla("../../skill-package/TestDataACDLi18n/deRequireMore") -reqmoreResponse = variations(reqmore_en, reqmore_de, reqmore_es_US) - -@locale(Locale.de_DE) -provide_help_de = apla("../../skill-package/TestDataACDLi18n/deHelp") -provide_helpResponse = variations(provide_help_en, provide_help_de,provide_help_es_US ) - - -combo = MultiModalResponse {apla = combo_apla_welcome, apl = welcome_apl} - -a = skill( - locales = [Locale.es_US, Locale.de_DE], - dialogs = [Weather, sOA], - skillLevelResponses = SkillLevelResponses - { - welcome = combo - ,out_of_domain = out_of_domainResponse - ,bye = byeResponse - ,reqmore = reqmoreResponse - ,provide_help = provide_helpResponse - }, - invocationNames = [ InvocationName { - locale = Locale.en_US, - invocationName = "acdl weatherbot localized" - }, - InvocationName { - locale = Locale.en_GB, - invocationName = "acdl weatherbot localized" - }, - InvocationName { - locale = Locale.en_CA, - invocationName = "acdl weatherbot localized" - } - ] - -) - diff --git a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/conversations/soaDialog.acdl b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/conversations/soaDialog.acdl deleted file mode 100644 index 020b9f53..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/conversations/soaDialog.acdl +++ /dev/null @@ -1,132 +0,0 @@ -namespace soaACDl - -import com.amazon.alexa.ask.conversations.Affirm -import com.amazon.alexa.ask.conversations.ConfirmArgs -import com.amazon.alexa.ask.conversations.ConfirmAction -import com.weatherbot.apis.* -import com.amazon.alexa.ask.conversations.Invoke -import com.amazon.alexa.ask.conversations.Notify -import com.amazon.alexa.ask.conversations.Request -import com.amazon.alexa.ask.conversations.expect -//import com.amazon.alexa.ask.conversations.received -import com.amazon.alexa.ask.conversations.response -import com.amazon.alexa.ask.conversations.utterances -import types.* -import com.amazon.alexa.schema.String - -import com.weatherbot.apis.colorFruitName -import com.weatherbot.apis.fruitNameAPI -import com.weatherbot.apis.result -import prompts.confirm_color_for_fruit_apla -import prompts.request_colorName_multiple_apla -import prompts.success_fruitPriceAPI_apla -import prompts.request_city_apla -import slotTypes.* -import prompts.* -import displays.* -import com.amazon.ask.types.builtins.AMAZON.* -import com.amazon.alexa.schema.* -import com.amazon.alexa.ask.conversations.* - - - -type payloadMultipleDialogEvent { - resultthree result -} - -@locale(Locale.en_US) -MultipleDialogEvent_enUS = utterances( - samples = [ - "i want to buy a fruit" - ] -) -TRYTHI = MultipleDialogEvent_enUS - -@locale(Locale.de_DE, Locale.es_US) -MultipleDialogEvent_deDE = utterances( - samples = [ - "ich möchte eine frucht kaufen" - ] -) - -MultipleDialogEvent_temp = variations(TRYTHI) - -MultipleDialogEvent = variations(MultipleDialogEvent_temp, MultipleDialogEvent_deDE) - -@locale(Locale.en_US) -informColorMultipleEvent_enUS = utterances( - samples = [ - "{colorName}", - "color is {colorName}", - "color {colorName}" - ] -) -@locale(Locale.de_DE) -informColorMultipleEvent_deDE = utterances( - samples = [ - "{colorName}", - "farbe ist {colorName}", - "farbe {colorName}" - ] -) - - -informColorMultipleEvent = variations(informColorMultipleEvent_enUS, informColorMultipleEvent_deDE) - -affirmMultipleColorEvent = utterances( - samples = [ - "do it" - ] -) - - -type colorNameShell { - myColors colorName -} - - -type payloadsOAConfirmArgs { - myColors colorName -} - - - - -/* - -informColorMultipleEvent = utterances( - samples = [ - "{colorName}", - "color is {colorName}", - "color {colorName}" - ] -) - -dialog Nothing stagingAreaOne() { - sample { - expect(act = Invoke,event = MultipleDialogEvent) - response(response = request_colorName_multiple_apla,act = Request {arguments = [colorFruitName.arguments.colorName]}) - } -} - - -*/ - -//com.amazon.alexa.ask.conversations.response(response = request_colorName_multiple_apla, act = com.amazon.alexa.ask.conversations.Request {arguments = [colorFruitName.arguments.colorName]}) - -@locale(Locale.de_DE, Locale.en_US) -dialog Nothing sOA() { - //@locale(Locale.en_US) - sample { - expect(act = Invoke,event = MultipleDialogEvent) - response(response = request_colorName_multiple_apla,act = Request {arguments = [colorFruitName.arguments.colorName]}) - - colorEvent = expect(act = Inform,event = informColorMultipleEvent) - - resultEvent = colorFruitName(colorName = colorEvent.colorName) - response( response = success_colorFruitAPI_apla, act = Notify { actionName = colorFruitName}, - payload = payloadMultipleDialogEvent {result = resultEvent} - ) - } - -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/conversations/types.acdl b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/conversations/types.acdl deleted file mode 100644 index 439e8934..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/conversations/types.acdl +++ /dev/null @@ -1,43 +0,0 @@ -namespace types - -import com.amazon.ask.types.builtins.AMAZON.Color -import com.amazon.ask.types.builtins.AMAZON.DATE -import com.amazon.ask.types.builtins.AMAZON.Food -import com.amazon.ask.types.builtins.AMAZON.NUMBER -import slotTypes.complexNames -import slotTypes.position -import slotTypes.signs -import slotTypes.* - -type result_one { - Color colorName - complexNames name - signs sign -} - -type complexResult { - complexNames name1 - DATE a_dateOfBirth - NUMBER emplyee1id - position position -} - -type nameShell { - complexNames name -} - -type dobshell { - DATE a_dateOfBirth -} - -type employeeIDshell { - NUMBER emplyee1id -} - -type fruitNameShell { - Food fruitName -} -/ -type colorEvent0 { - myColors colorName -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/conversations/utteracesets.acdl b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/conversations/utteracesets.acdl deleted file mode 100644 index 5f8fe09b..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/conversations/utteracesets.acdl +++ /dev/null @@ -1,82 +0,0 @@ -namespace utteracesets - -import com.amazon.alexa.ask.conversations.utterances -import types.dobshell -import types.employeeIDshell -import types.fruitNameShell -import types.nameShell - -getFruitPriceEvent = utterances( - samples = [ - "what is the price of the fruit", - "what is the price of fruit" - ] -) - -affirmFruitAPIEvent = utterances( - samples = [ - "yeah" - ] -) - -informfruitNameEvent = utterances( - samples = [ - "{fruitName}", - "fruit name is {fruitName}", - "fruit is {fruitName}" - ] -) - -delegateToSkill = utterances( - samples = [ - "get me to paradise", - "take me to paradise" - ] -) - -getFavColorEvent = utterances( - samples = [ - "what is my favourite color", - "tell my favourite color" - ] -) - -affirmFavColorEvent = utterances( - samples = [ - "correct" - ] -) - -who_are_you = utterances( - samples = [ - "who are you", - "who is that", - "find his designation" - ] -) - -informComplexNameEvent = utterances( - samples = [ - "{name}", - "name is {name}", - "i am {name}" - ] -) - -informDOBEvent = utterances( - samples = [ - "date of birth is {a_dateOfBirth}", - "birth date is {a_dateOfBirth}" - ] -) - -informEmployeeIDEvent = utterances( - samples = [ - "employee i.d. is {emplyee1id}", - "employee identification is {emplyee1id}", - "identification is {emplyee1id}", - "employee id is {emplyee1id}", - "i.d. is {emplyee1id}", - "id is {emplyee1id}" - ] -) diff --git a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/interactionModels/custom/de-DE.json b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/interactionModels/custom/de-DE.json deleted file mode 100644 index f9d930e7..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/interactionModels/custom/de-DE.json +++ /dev/null @@ -1,919 +0,0 @@ -{ - "interactionModel": { - "languageModel": { - "invocationName": "waka waka test skill", - "intents": [ - { - "name": "AMAZON.CancelIntent", - "samples": [] - }, - { - "name": "AMAZON.HelpIntent", - "samples": [] - }, - { - "name": "AMAZON.StopIntent", - "samples": [] - }, - { - "name": "GetWeatherIntent", - "samples": ["what is the weather", "how is the weather", "tell me the weather"] - }, - { - "name": "AMAZON.NavigateHomeIntent", - "samples": [] - }, - { - "name": "AMAZON.FallbackIntent", - "samples": [] - } - ], - "types": [ - { - "values": [ - { - "id": "movies", - "name": { - "value": "movies", - "synonyms": [] - } - }, - { - "id": "politics", - "name": { - "value": "politics", - "synonyms": [] - } - }, - { - "id": "sports", - "name": { - "value": "sports", - "synonyms": [] - } - }, - { - "id": "hobbies", - "name": { - "value": "hobbies", - "synonyms": [] - } - }, - { - "id": "astronomy", - "name": { - "value": "astronomy", - "synonyms": [] - } - }, - { - "id": "physics", - "name": { - "value": "physics", - "synonyms": [] - } - }, - { - "id": "los_angeles_dodgers", - "name": { - "value": "los angeles dodgers" - } - }, - { - "id": "president_emmanuel_macron", - "name": { - "value": "president emmanuel macron" - } - }, - { - "id": "emmanuel_macron", - "name": { - "value": "emmanuel macron" - } - }, - { - "id": "tax_cuts", - "name": { - "value": "tax cuts" - } - }, - { - "id": "middle_class", - "name": { - "value": "middle class" - } - }, - { - "id": "inequality_divide", - "name": { - "value": "inequality divide" - } - }, - { - "id": "wealth_inequality", - "name": { - "value": "wealth inequality" - } - }, - { - "id": "n._p._r.", - "name": { - "value": "n. p. r." - } - }, - { - "id": "president_trump", - "name": { - "value": "president trump" - } - }, - { - "id": "fox", - "name": { - "value": "fox" - } - }, - { - "id": "police_officers", - "name": { - "value": "police officers" - } - }, - { - "id": "jerome_hall", - "name": { - "value": "jerome hall" - } - }, - { - "id": "diversity_training_program", - "name": { - "value": "diversity training program" - } - }, - { - "id": "read_preble", - "name": { - "value": "read preble" - } - }, - { - "id": "christopher_preble", - "name": { - "value": "christopher preble" - } - }, - { - "id": "pacific_rim", - "name": { - "value": "pacific rim" - } - }, - { - "id": "washington_nationals", - "name": { - "value": "washington nationals" - } - }, - { - "id": "michael_cohen", - "name": { - "value": "michael cohen" - } - }, - { - "id": "john_wall", - "name": { - "value": "john wall" - } - }, - { - "id": "united_states", - "name": { - "value": "united states" - } - }, - { - "id": "washington_wizards", - "name": { - "value": "washington wizards" - } - }, - { - "id": "bryce_harper", - "name": { - "value": "bryce harper" - } - }, - { - "id": "capitals_playoff_hockey_capitals", - "name": { - "value": "capitals playoff hockey capitals" - } - }, - { - "id": "james_b._comey", - "name": { - "value": "james b. comey" - } - }, - { - "id": "mike_pompeo", - "name": { - "value": "mike pompeo" - } - }, - { - "id": "tom_toles", - "name": { - "value": "tom toles" - } - }, - { - "id": "white_house", - "name": { - "value": "white house" - } - }, - { - "id": "manny_machado", - "name": { - "value": "manny machado" - } - }, - { - "id": "national_league_east", - "name": { - "value": "national league east" - } - }, - { - "id": "otto_porter_jr._now", - "name": { - "value": "otto porter jr. now" - } - }, - { - "id": "hillary_clinton", - "name": { - "value": "hillary clinton" - } - }, - { - "id": "trea_turner", - "name": { - "value": "trea turner" - } - }, - { - "id": "max_scherzer", - "name": { - "value": "max scherzer" - } - }, - { - "id": "donald_trump", - "name": { - "value": "donald trump" - } - }, - { - "id": "bryce_harper_nationals", - "name": { - "value": "bryce harper nationals" - } - }, - { - "id": "michael_a._taylor", - "name": { - "value": "michael a. taylor" - } - }, - { - "id": "news_media", - "name": { - "value": "news media" - } - }, - { - "id": "conservative_political_action_conference", - "name": { - "value": "conservative political action conference" - } - }, - { - "id": "mainstream_media", - "name": { - "value": "mainstream media" - } - }, - { - "id": "baltimore_orioles", - "name": { - "value": "baltimore orioles" - } - }, - { - "id": "sean_hannity", - "name": { - "value": "sean hannity" - } - }, - { - "id": "privilege", - "name": { - "value": "privilege" - } - }, - { - "id": "sarah_hart", - "name": { - "value": "sarah hart" - } - }, - { - "id": "matt_kemp", - "name": { - "value": "matt kemp" - } - }, - { - "id": "stephen_strasburg", - "name": { - "value": "stephen strasburg" - } - }, - { - "id": "police_misconduct", - "name": { - "value": "police misconduct" - } - }, - { - "id": "sarah_huckabee_sanders", - "name": { - "value": "sarah huckabee sanders" - } - }, - { - "id": "washington_wizards_april", - "name": { - "value": "washington wizards april" - } - }, - { - "id": "environmental_protection_agency_administrator_scott_pruitt", - "name": { - "value": "environmental protection agency administrator scott pruitt" - } - }, - { - "id": "dodger_stadium", - "name": { - "value": "dodger stadium" - } - }, - { - "id": "environmental_protection_agency", - "name": { - "value": "environmental protection agency" - } - }, - { - "id": "barbara_bush", - "name": { - "value": "barbara bush" - } - }, - { - "id": "lewis_\"scooter\"_libby", - "name": { - "value": "lewis \"scooter\" libby" - } - }, - { - "id": "lewis_scooter_libby", - "name": { - "value": "lewis scooter libby" - } - }, - { - "id": "game_3._lowry", - "name": { - "value": "game 3. lowry" - } - }, - { - "id": "columbus_blue_jackets", - "name": { - "value": "columbus blue jackets" - } - }, - { - "id": "john_tortorella", - "name": { - "value": "john tortorella" - } - }, - { - "id": "george_w._bush", - "name": { - "value": "george w. bush" - } - }, - { - "id": "george_h.w._bush", - "name": { - "value": "george h.w. bush" - } - }, - { - "id": "jarrett_hurd", - "name": { - "value": "jarrett hurd" - } - }, - { - "id": "said_fred_hurd_sr.", - "name": { - "value": "said fred hurd sr." - } - }, - { - "id": "fred_hurd_sr.", - "name": { - "value": "fred hurd sr." - } - }, - { - "id": "san_antonio", - "name": { - "value": "san antonio" - } - }, - { - "id": "san_antonio_spurs", - "name": { - "value": "san antonio spurs" - } - }, - { - "id": "gregg_popovich", - "name": { - "value": "gregg popovich" - } - }, - { - "id": "kawhi_leonard", - "name": { - "value": "kawhi leonard" - } - }, - { - "id": "tim_bontemps_seth_jones", - "name": { - "value": "tim bontemps seth jones" - } - }, - { - "id": "consumer_sentiment_index", - "name": { - "value": "consumer sentiment index" - } - }, - { - "id": "pew_research_center", - "name": { - "value": "pew research center" - } - }, - { - "id": "conference_board_consumer_confidence_survey", - "name": { - "value": "conference board consumer confidence survey" - } - }, - { - "id": "speech_rights", - "name": { - "value": "speech rights" - } - }, - { - "id": "first_amendment", - "name": { - "value": "first amendment" - } - }, - { - "id": "golden_state", - "name": { - "value": "golden state" - } - }, - { - "id": "north_korea", - "name": { - "value": "north korea" - } - }, - { - "id": "woman_pilot", - "name": { - "value": "woman pilot" - } - }, - { - "id": "airline_pilot_population", - "name": { - "value": "airline pilot population" - } - }, - { - "id": "air_transport_pilot", - "name": { - "value": "air transport pilot" - } - }, - { - "id": "southwest_airlines", - "name": { - "value": "southwest airlines" - } - }, - { - "id": "democratic_national_committee", - "name": { - "value": "democratic national committee" - } - }, - { - "id": "senate_foreign_relations_committee", - "name": { - "value": "senate foreign relations committee" - } - }, - { - "id": "cia_director_mike_pompeo", - "name": { - "value": "cia director mike pompeo" - } - }, - { - "id": "playoff_overtime_games", - "name": { - "value": "playoff overtime games" - } - }, - { - "id": "lord_jesus", - "name": { - "value": "lord jesus" - } - }, - { - "id": "lgbtq_community", - "name": { - "value": "lgbtq community" - } - }, - { - "id": "health_and_human_services_department", - "name": { - "value": "health and human services department" - } - }, - { - "id": "group_prayer", - "name": { - "value": "group prayer" - } - }, - { - "id": "princess_charlotte_elizabeth_diana", - "name": { - "value": "princess charlotte elizabeth diana" - } - }, - { - "id": "term_war_economy", - "name": { - "value": "term war economy" - } - }, - { - "id": "melissa_kirk", - "name": { - "value": "melissa kirk" - } - }, - { - "id": "captain_america", - "name": { - "value": "captain america" - } - }, - { - "id": "draft_position", - "name": { - "value": "draft position" - } - }, - { - "id": "elysee_mbem-bosse", - "name": { - "value": "elysee mbem-bosse" - } - }, - { - "id": "water_crisis", - "name": { - "value": "water crisis" - } - }, - { - "id": "nationals_pitchers", - "name": { - "value": "nationals pitchers" - } - }, - { - "id": "sen._jennifer_t._wexton", - "name": { - "value": "sen. jennifer t. wexton" - } - }, - { - "id": "interest_rates", - "name": { - "value": "interest rates" - } - }, - { - "id": "town_crier", - "name": { - "value": "town crier" - } - }, - { - "id": "nancy_goes_millennial", - "name": { - "value": "nancy goes millennial" - } - }, - { - "id": "steve_rogers", - "name": { - "value": "steve rogers" - } - }, - { - "id": "game_3._lebron_james", - "name": { - "value": "game 3. lebron james" - } - }, - { - "id": "anthony_rendon", - "name": { - "value": "anthony rendon" - } - }, - { - "id": "buckingham_palace", - "name": { - "value": "buckingham palace" - } - }, - { - "id": "travis_reinking_suspected", - "name": { - "value": "travis reinking suspected" - } - }, - { - "id": "detroit_free_press", - "name": { - "value": "detroit free press" - } - }, - { - "id": "national_rifle_association", - "name": { - "value": "national rifle association" - } - }, - { - "id": "ed_harris", - "name": { - "value": "ed harris" - } - }, - { - "id": "overtime_playoff_games", - "name": { - "value": "overtime playoff games" - } - }, - { - "id": "republican_sen._bob_corker", - "name": { - "value": "republican sen. bob corker" - } - }, - { - "id": "electricity_sector_reforms", - "name": { - "value": "electricity sector reforms" - } - }, - { - "id": "baltimore_manager_buck_showalter", - "name": { - "value": "baltimore manager buck showalter" - } - }, - { - "id": "sen._joe_manchin_iii", - "name": { - "value": "sen. joe manchin iii" - } - }, - { - "id": "car_seat_belts", - "name": { - "value": "car seat belts" - } - }, - { - "id": "andrews_mcmeel.", - "name": { - "value": "andrews mcmeel." - } - }, - { - "id": "north_africa_program", - "name": { - "value": "north africa program" - } - }, - { - "id": "state_prosecutor_lobby", - "name": { - "value": "state prosecutor lobby" - } - }, - { - "id": "cape_town", - "name": { - "value": "cape town" - } - }, - { - "id": "data_privacy_law", - "name": { - "value": "data privacy law" - } - }, - { - "id": "president_trump_down", - "name": { - "value": "president trump down" - } - }, - { - "id": "christian_kirk", - "name": { - "value": "christian kirk" - } - }, - { - "id": "mitch_mcconnell", - "name": { - "value": "mitch mcconnell" - } - }, - { - "id": "federal_reserve", - "name": { - "value": "federal reserve" - } - } - ], - "name": "TopicType" - }, - { - "values": [ - { - "name": { - "value": "cancer" - } - }, - { - "name": { - "value": "scorpio" - } - }, - { - "name": { - "value": "scorpion" - } - } - ], - "name": "signs" - }, - { - "values": [ - { - "name": { - "value": "satheesh" - } - }, - { - "name": { - "value": "raman" - } - }, - { - "name": { - "value": "yadhu" - } - } - ], - "name": "complexNames" - }, - { - "values": [ - { - "name": { - "value": "tester" - } - }, - { - "name": { - "value": "engineer" - } - }, - { - "name": { - "value": "manager" - } - } - ], - "name": "position" - }, - { - "values": [ - { - "name": { - "value": "blue" - } - }, - { - "name": { - "value": "red" - } - }, - { - "name": { - "value": "rocket" - } - } - ], - "name": "myColors" - }, - { - "values": [ - { - "name": { - "value": "flower city" - } - }, - { - "name": { - "value": "temple city" - } - }, - { - "name": { - "value": "ramapuram" - } - }, - { - "name": { - "value": "guindy" - } - }, - { - "name": { - "value": "porur" - } - } - ], - "name": "myCustomCities" - } - ] - } - }, - "version": "18" -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/interactionModels/custom/en-US.json b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/interactionModels/custom/en-US.json deleted file mode 100644 index f9d930e7..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/interactionModels/custom/en-US.json +++ /dev/null @@ -1,919 +0,0 @@ -{ - "interactionModel": { - "languageModel": { - "invocationName": "waka waka test skill", - "intents": [ - { - "name": "AMAZON.CancelIntent", - "samples": [] - }, - { - "name": "AMAZON.HelpIntent", - "samples": [] - }, - { - "name": "AMAZON.StopIntent", - "samples": [] - }, - { - "name": "GetWeatherIntent", - "samples": ["what is the weather", "how is the weather", "tell me the weather"] - }, - { - "name": "AMAZON.NavigateHomeIntent", - "samples": [] - }, - { - "name": "AMAZON.FallbackIntent", - "samples": [] - } - ], - "types": [ - { - "values": [ - { - "id": "movies", - "name": { - "value": "movies", - "synonyms": [] - } - }, - { - "id": "politics", - "name": { - "value": "politics", - "synonyms": [] - } - }, - { - "id": "sports", - "name": { - "value": "sports", - "synonyms": [] - } - }, - { - "id": "hobbies", - "name": { - "value": "hobbies", - "synonyms": [] - } - }, - { - "id": "astronomy", - "name": { - "value": "astronomy", - "synonyms": [] - } - }, - { - "id": "physics", - "name": { - "value": "physics", - "synonyms": [] - } - }, - { - "id": "los_angeles_dodgers", - "name": { - "value": "los angeles dodgers" - } - }, - { - "id": "president_emmanuel_macron", - "name": { - "value": "president emmanuel macron" - } - }, - { - "id": "emmanuel_macron", - "name": { - "value": "emmanuel macron" - } - }, - { - "id": "tax_cuts", - "name": { - "value": "tax cuts" - } - }, - { - "id": "middle_class", - "name": { - "value": "middle class" - } - }, - { - "id": "inequality_divide", - "name": { - "value": "inequality divide" - } - }, - { - "id": "wealth_inequality", - "name": { - "value": "wealth inequality" - } - }, - { - "id": "n._p._r.", - "name": { - "value": "n. p. r." - } - }, - { - "id": "president_trump", - "name": { - "value": "president trump" - } - }, - { - "id": "fox", - "name": { - "value": "fox" - } - }, - { - "id": "police_officers", - "name": { - "value": "police officers" - } - }, - { - "id": "jerome_hall", - "name": { - "value": "jerome hall" - } - }, - { - "id": "diversity_training_program", - "name": { - "value": "diversity training program" - } - }, - { - "id": "read_preble", - "name": { - "value": "read preble" - } - }, - { - "id": "christopher_preble", - "name": { - "value": "christopher preble" - } - }, - { - "id": "pacific_rim", - "name": { - "value": "pacific rim" - } - }, - { - "id": "washington_nationals", - "name": { - "value": "washington nationals" - } - }, - { - "id": "michael_cohen", - "name": { - "value": "michael cohen" - } - }, - { - "id": "john_wall", - "name": { - "value": "john wall" - } - }, - { - "id": "united_states", - "name": { - "value": "united states" - } - }, - { - "id": "washington_wizards", - "name": { - "value": "washington wizards" - } - }, - { - "id": "bryce_harper", - "name": { - "value": "bryce harper" - } - }, - { - "id": "capitals_playoff_hockey_capitals", - "name": { - "value": "capitals playoff hockey capitals" - } - }, - { - "id": "james_b._comey", - "name": { - "value": "james b. comey" - } - }, - { - "id": "mike_pompeo", - "name": { - "value": "mike pompeo" - } - }, - { - "id": "tom_toles", - "name": { - "value": "tom toles" - } - }, - { - "id": "white_house", - "name": { - "value": "white house" - } - }, - { - "id": "manny_machado", - "name": { - "value": "manny machado" - } - }, - { - "id": "national_league_east", - "name": { - "value": "national league east" - } - }, - { - "id": "otto_porter_jr._now", - "name": { - "value": "otto porter jr. now" - } - }, - { - "id": "hillary_clinton", - "name": { - "value": "hillary clinton" - } - }, - { - "id": "trea_turner", - "name": { - "value": "trea turner" - } - }, - { - "id": "max_scherzer", - "name": { - "value": "max scherzer" - } - }, - { - "id": "donald_trump", - "name": { - "value": "donald trump" - } - }, - { - "id": "bryce_harper_nationals", - "name": { - "value": "bryce harper nationals" - } - }, - { - "id": "michael_a._taylor", - "name": { - "value": "michael a. taylor" - } - }, - { - "id": "news_media", - "name": { - "value": "news media" - } - }, - { - "id": "conservative_political_action_conference", - "name": { - "value": "conservative political action conference" - } - }, - { - "id": "mainstream_media", - "name": { - "value": "mainstream media" - } - }, - { - "id": "baltimore_orioles", - "name": { - "value": "baltimore orioles" - } - }, - { - "id": "sean_hannity", - "name": { - "value": "sean hannity" - } - }, - { - "id": "privilege", - "name": { - "value": "privilege" - } - }, - { - "id": "sarah_hart", - "name": { - "value": "sarah hart" - } - }, - { - "id": "matt_kemp", - "name": { - "value": "matt kemp" - } - }, - { - "id": "stephen_strasburg", - "name": { - "value": "stephen strasburg" - } - }, - { - "id": "police_misconduct", - "name": { - "value": "police misconduct" - } - }, - { - "id": "sarah_huckabee_sanders", - "name": { - "value": "sarah huckabee sanders" - } - }, - { - "id": "washington_wizards_april", - "name": { - "value": "washington wizards april" - } - }, - { - "id": "environmental_protection_agency_administrator_scott_pruitt", - "name": { - "value": "environmental protection agency administrator scott pruitt" - } - }, - { - "id": "dodger_stadium", - "name": { - "value": "dodger stadium" - } - }, - { - "id": "environmental_protection_agency", - "name": { - "value": "environmental protection agency" - } - }, - { - "id": "barbara_bush", - "name": { - "value": "barbara bush" - } - }, - { - "id": "lewis_\"scooter\"_libby", - "name": { - "value": "lewis \"scooter\" libby" - } - }, - { - "id": "lewis_scooter_libby", - "name": { - "value": "lewis scooter libby" - } - }, - { - "id": "game_3._lowry", - "name": { - "value": "game 3. lowry" - } - }, - { - "id": "columbus_blue_jackets", - "name": { - "value": "columbus blue jackets" - } - }, - { - "id": "john_tortorella", - "name": { - "value": "john tortorella" - } - }, - { - "id": "george_w._bush", - "name": { - "value": "george w. bush" - } - }, - { - "id": "george_h.w._bush", - "name": { - "value": "george h.w. bush" - } - }, - { - "id": "jarrett_hurd", - "name": { - "value": "jarrett hurd" - } - }, - { - "id": "said_fred_hurd_sr.", - "name": { - "value": "said fred hurd sr." - } - }, - { - "id": "fred_hurd_sr.", - "name": { - "value": "fred hurd sr." - } - }, - { - "id": "san_antonio", - "name": { - "value": "san antonio" - } - }, - { - "id": "san_antonio_spurs", - "name": { - "value": "san antonio spurs" - } - }, - { - "id": "gregg_popovich", - "name": { - "value": "gregg popovich" - } - }, - { - "id": "kawhi_leonard", - "name": { - "value": "kawhi leonard" - } - }, - { - "id": "tim_bontemps_seth_jones", - "name": { - "value": "tim bontemps seth jones" - } - }, - { - "id": "consumer_sentiment_index", - "name": { - "value": "consumer sentiment index" - } - }, - { - "id": "pew_research_center", - "name": { - "value": "pew research center" - } - }, - { - "id": "conference_board_consumer_confidence_survey", - "name": { - "value": "conference board consumer confidence survey" - } - }, - { - "id": "speech_rights", - "name": { - "value": "speech rights" - } - }, - { - "id": "first_amendment", - "name": { - "value": "first amendment" - } - }, - { - "id": "golden_state", - "name": { - "value": "golden state" - } - }, - { - "id": "north_korea", - "name": { - "value": "north korea" - } - }, - { - "id": "woman_pilot", - "name": { - "value": "woman pilot" - } - }, - { - "id": "airline_pilot_population", - "name": { - "value": "airline pilot population" - } - }, - { - "id": "air_transport_pilot", - "name": { - "value": "air transport pilot" - } - }, - { - "id": "southwest_airlines", - "name": { - "value": "southwest airlines" - } - }, - { - "id": "democratic_national_committee", - "name": { - "value": "democratic national committee" - } - }, - { - "id": "senate_foreign_relations_committee", - "name": { - "value": "senate foreign relations committee" - } - }, - { - "id": "cia_director_mike_pompeo", - "name": { - "value": "cia director mike pompeo" - } - }, - { - "id": "playoff_overtime_games", - "name": { - "value": "playoff overtime games" - } - }, - { - "id": "lord_jesus", - "name": { - "value": "lord jesus" - } - }, - { - "id": "lgbtq_community", - "name": { - "value": "lgbtq community" - } - }, - { - "id": "health_and_human_services_department", - "name": { - "value": "health and human services department" - } - }, - { - "id": "group_prayer", - "name": { - "value": "group prayer" - } - }, - { - "id": "princess_charlotte_elizabeth_diana", - "name": { - "value": "princess charlotte elizabeth diana" - } - }, - { - "id": "term_war_economy", - "name": { - "value": "term war economy" - } - }, - { - "id": "melissa_kirk", - "name": { - "value": "melissa kirk" - } - }, - { - "id": "captain_america", - "name": { - "value": "captain america" - } - }, - { - "id": "draft_position", - "name": { - "value": "draft position" - } - }, - { - "id": "elysee_mbem-bosse", - "name": { - "value": "elysee mbem-bosse" - } - }, - { - "id": "water_crisis", - "name": { - "value": "water crisis" - } - }, - { - "id": "nationals_pitchers", - "name": { - "value": "nationals pitchers" - } - }, - { - "id": "sen._jennifer_t._wexton", - "name": { - "value": "sen. jennifer t. wexton" - } - }, - { - "id": "interest_rates", - "name": { - "value": "interest rates" - } - }, - { - "id": "town_crier", - "name": { - "value": "town crier" - } - }, - { - "id": "nancy_goes_millennial", - "name": { - "value": "nancy goes millennial" - } - }, - { - "id": "steve_rogers", - "name": { - "value": "steve rogers" - } - }, - { - "id": "game_3._lebron_james", - "name": { - "value": "game 3. lebron james" - } - }, - { - "id": "anthony_rendon", - "name": { - "value": "anthony rendon" - } - }, - { - "id": "buckingham_palace", - "name": { - "value": "buckingham palace" - } - }, - { - "id": "travis_reinking_suspected", - "name": { - "value": "travis reinking suspected" - } - }, - { - "id": "detroit_free_press", - "name": { - "value": "detroit free press" - } - }, - { - "id": "national_rifle_association", - "name": { - "value": "national rifle association" - } - }, - { - "id": "ed_harris", - "name": { - "value": "ed harris" - } - }, - { - "id": "overtime_playoff_games", - "name": { - "value": "overtime playoff games" - } - }, - { - "id": "republican_sen._bob_corker", - "name": { - "value": "republican sen. bob corker" - } - }, - { - "id": "electricity_sector_reforms", - "name": { - "value": "electricity sector reforms" - } - }, - { - "id": "baltimore_manager_buck_showalter", - "name": { - "value": "baltimore manager buck showalter" - } - }, - { - "id": "sen._joe_manchin_iii", - "name": { - "value": "sen. joe manchin iii" - } - }, - { - "id": "car_seat_belts", - "name": { - "value": "car seat belts" - } - }, - { - "id": "andrews_mcmeel.", - "name": { - "value": "andrews mcmeel." - } - }, - { - "id": "north_africa_program", - "name": { - "value": "north africa program" - } - }, - { - "id": "state_prosecutor_lobby", - "name": { - "value": "state prosecutor lobby" - } - }, - { - "id": "cape_town", - "name": { - "value": "cape town" - } - }, - { - "id": "data_privacy_law", - "name": { - "value": "data privacy law" - } - }, - { - "id": "president_trump_down", - "name": { - "value": "president trump down" - } - }, - { - "id": "christian_kirk", - "name": { - "value": "christian kirk" - } - }, - { - "id": "mitch_mcconnell", - "name": { - "value": "mitch mcconnell" - } - }, - { - "id": "federal_reserve", - "name": { - "value": "federal reserve" - } - } - ], - "name": "TopicType" - }, - { - "values": [ - { - "name": { - "value": "cancer" - } - }, - { - "name": { - "value": "scorpio" - } - }, - { - "name": { - "value": "scorpion" - } - } - ], - "name": "signs" - }, - { - "values": [ - { - "name": { - "value": "satheesh" - } - }, - { - "name": { - "value": "raman" - } - }, - { - "name": { - "value": "yadhu" - } - } - ], - "name": "complexNames" - }, - { - "values": [ - { - "name": { - "value": "tester" - } - }, - { - "name": { - "value": "engineer" - } - }, - { - "name": { - "value": "manager" - } - } - ], - "name": "position" - }, - { - "values": [ - { - "name": { - "value": "blue" - } - }, - { - "name": { - "value": "red" - } - }, - { - "name": { - "value": "rocket" - } - } - ], - "name": "myColors" - }, - { - "values": [ - { - "name": { - "value": "flower city" - } - }, - { - "name": { - "value": "temple city" - } - }, - { - "name": { - "value": "ramapuram" - } - }, - { - "name": { - "value": "guindy" - } - }, - { - "name": { - "value": "porur" - } - } - ], - "name": "myCustomCities" - } - ] - } - }, - "version": "18" -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/display/confirm_city_apl_display/document.json b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/display/confirm_city_apl_display/document.json deleted file mode 100644 index 6fea1ff7..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/display/confirm_city_apl_display/document.json +++ /dev/null @@ -1,331 +0,0 @@ -{ - "type": "APL", - "version": "1.1", - "settings": {}, - "theme": "dark", - "import": [ - { - "name": "alexa-layouts", - "version": "1.0.0" - } - ], - "resources": [ - { - "description": "Stock color for the light theme", - "colors": { - "colorTextPrimary": "#151920" - } - }, - { - "description": "Stock color for the dark theme", - "when": "${viewport.theme == 'dark'}", - "colors": { - "colorTextPrimary": "#f0f1ef" - } - }, - { - "description": "Standard font sizes", - "dimensions": { - "textSizeBody": 48, - "textSizePrimary": 27, - "textSizeSecondary": 23, - "textSizeDetails": 20, - "textSizeSecondaryHint": 25 - } - }, - { - "description": "Common spacing values", - "dimensions": { - "spacingThin": 6, - "spacingSmall": 12, - "spacingMedium": 24, - "spacingLarge": 48, - "spacingExtraLarge": 72 - } - }, - { - "description": "Common margins and padding", - "dimensions": { - "marginTop": 40, - "marginLeft": 60, - "marginRight": 60, - "marginBottom": 40 - } - } - ], - "styles": { - "textStyleBase": { - "description": "Base font description; set color", - "values": [ - { - "color": "@colorTextPrimary" - } - ] - }, - "textStyleBase0": { - "description": "Thin version of basic font", - "extend": "textStyleBase", - "values": { - "fontWeight": "100" - } - }, - "textStyleBase1": { - "description": "Light version of basic font", - "extend": "textStyleBase", - "values": { - "fontWeight": "300" - } - }, - "textStyleBase2": { - "description": "Regular version of basic font", - "extend": "textStyleBase", - "values": { - "fontWeight": "500" - } - }, - "mixinBody": { - "values": { - "fontSize": "@textSizeBody" - } - }, - "mixinPrimary": { - "values": { - "fontSize": "@textSizePrimary" - } - }, - "mixinDetails": { - "values": { - "fontSize": "@textSizeDetails" - } - }, - "mixinSecondary": { - "values": { - "fontSize": "@textSizeSecondary" - } - }, - "textStylePrimary": { - "extend": ["textStyleBase1", "mixinPrimary"] - }, - "textStyleSecondary": { - "extend": ["textStyleBase0", "mixinSecondary"] - }, - "textStyleBody": { - "extend": ["textStyleBase1", "mixinBody"] - }, - "textStyleSecondaryHint": { - "values": { - "fontFamily": "Bookerly", - "fontStyle": "italic", - "fontSize": "@textSizeSecondaryHint", - "color": "@colorTextPrimary" - } - }, - "textStyleDetails": { - "extend": ["textStyleBase2", "mixinDetails"] - } - }, - "onMount": [], - "graphics": {}, - "commands": {}, - "layouts": { - "ListTemplate1": { - "parameters": ["backgroundImage", "title", "logo", "hintText", "listData"], - "item": [ - { - "type": "Container", - "width": "100vw", - "height": "100vh", - "direction": "column", - "items": [ - { - "type": "Image", - "source": "${backgroundImage}", - "scale": "best-fill", - "width": "100vw", - "height": "100vh", - "position": "absolute" - }, - { - "type": "AlexaHeader", - "headerTitle": "${title}", - "headerAttributionImage": "${logo}" - }, - { - "type": "Sequence", - "grow": 1, - "height": "80vh", - "scrollDirection": "vertical", - "paddingLeft": "@marginLeft", - "paddingRight": "@marginRight", - "data": "${listData}", - "numbered": true, - "items": [ - { - "type": "VerticalListItem", - "image": "${data.image.sources[0].url}", - "primaryText": "${data.textContent.primaryText.text}", - "secondaryText": "${data.textContent.secondaryText.text}", - "tertiaryText": "${data.textContent.tertiaryText.text}" - } - ] - } - ] - } - ] - }, - "VerticalListItem": { - "parameters": ["primaryText", "secondaryText", "tertiaryText", "image"], - "item": [ - { - "when": "${viewport.shape == 'round'}", - "type": "Container", - "direction": "row", - "height": 200, - "width": 500, - "alignItems": "center", - "items": [ - { - "type": "Text", - "text": "${ordinal}", - "paddingBottom": "20dp", - "color": "white", - "spacing": "5dp" - }, - { - "type": "Image", - "when": "${image}", - "source": "${image}", - "height": 150, - "width": 150, - "spacing": 15, - "scale": "best-fit", - "align": "top" - }, - { - "type": "Container", - "direction": "column", - "spacing": 25, - "items": [ - { - "type": "Text", - "text": "${primaryText}", - "style": "textStyleDetail", - "grow": 1, - "shrink": 1, - "fontWeight": "300", - "maxLines": 1 - }, - { - "type": "Text", - "text": "${secondaryText}", - "style": "textStyleCaption", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - }, - { - "type": "Text", - "text": "${tertiaryText}", - "style": "textStyleDetails", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - } - ] - } - ] - }, - { - "type": "Container", - "direction": "row", - "height": 125, - "width": 800, - "alignItems": "center", - "items": [ - { - "type": "Text", - "text": "${ordinal}", - "paddingBottom": "20dp", - "color": "white", - "spacing": "5dp" - }, - { - "type": "Image", - "when": "${image}", - "source": "${image}", - "height": 100, - "width": 100, - "align": "top", - "spacing": 50, - "scale": "best-fit" - }, - { - "type": "Container", - "spacing": 30, - "direction": "column", - "items": [ - { - "type": "Text", - "text": "${primaryText}", - "style": "textStyleBody", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - }, - { - "type": "Text", - "text": "${secondaryText}", - "style": "textStyleDetails", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - } - ] - }, - { - "type": "Text", - "text": "${tertiaryText}", - "style": "textStyleBody", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "textAlign": "right", - "maxLines": 1 - } - ] - } - ] - } - }, - "mainTemplate": { - "parameters": ["payload"], - "item": [ - { - "type": "Container", - "id": "BookCabSimpleDialogAPL", - "items": [ - { - "type": "TouchWrapper", - "onPress": { - "type": "SendEvent", - "arguments": ["delegateToColtraneOld"] - }, - "item": { - "type": "Text", - "id": "BookCabSimpleDialogAPL", - "paddingTop": "100", - "paddingLeft": "100", - "color": "green", - "size": 50, - "text": "which city ?" - } - } - ] - } - ] - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/display/confirm_date_apl_display/document.json b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/display/confirm_date_apl_display/document.json deleted file mode 100644 index d41ea236..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/display/confirm_date_apl_display/document.json +++ /dev/null @@ -1,331 +0,0 @@ -{ - "type": "APL", - "version": "1.1", - "settings": {}, - "theme": "dark", - "import": [ - { - "name": "alexa-layouts", - "version": "1.0.0" - } - ], - "resources": [ - { - "description": "Stock color for the light theme", - "colors": { - "colorTextPrimary": "#151920" - } - }, - { - "description": "Stock color for the dark theme", - "when": "${viewport.theme == 'dark'}", - "colors": { - "colorTextPrimary": "#f0f1ef" - } - }, - { - "description": "Standard font sizes", - "dimensions": { - "textSizeBody": 48, - "textSizePrimary": 27, - "textSizeSecondary": 23, - "textSizeDetails": 20, - "textSizeSecondaryHint": 25 - } - }, - { - "description": "Common spacing values", - "dimensions": { - "spacingThin": 6, - "spacingSmall": 12, - "spacingMedium": 24, - "spacingLarge": 48, - "spacingExtraLarge": 72 - } - }, - { - "description": "Common margins and padding", - "dimensions": { - "marginTop": 40, - "marginLeft": 60, - "marginRight": 60, - "marginBottom": 40 - } - } - ], - "styles": { - "textStyleBase": { - "description": "Base font description; set color", - "values": [ - { - "color": "@colorTextPrimary" - } - ] - }, - "textStyleBase0": { - "description": "Thin version of basic font", - "extend": "textStyleBase", - "values": { - "fontWeight": "100" - } - }, - "textStyleBase1": { - "description": "Light version of basic font", - "extend": "textStyleBase", - "values": { - "fontWeight": "300" - } - }, - "textStyleBase2": { - "description": "Regular version of basic font", - "extend": "textStyleBase", - "values": { - "fontWeight": "500" - } - }, - "mixinBody": { - "values": { - "fontSize": "@textSizeBody" - } - }, - "mixinPrimary": { - "values": { - "fontSize": "@textSizePrimary" - } - }, - "mixinDetails": { - "values": { - "fontSize": "@textSizeDetails" - } - }, - "mixinSecondary": { - "values": { - "fontSize": "@textSizeSecondary" - } - }, - "textStylePrimary": { - "extend": ["textStyleBase1", "mixinPrimary"] - }, - "textStyleSecondary": { - "extend": ["textStyleBase0", "mixinSecondary"] - }, - "textStyleBody": { - "extend": ["textStyleBase1", "mixinBody"] - }, - "textStyleSecondaryHint": { - "values": { - "fontFamily": "Bookerly", - "fontStyle": "italic", - "fontSize": "@textSizeSecondaryHint", - "color": "@colorTextPrimary" - } - }, - "textStyleDetails": { - "extend": ["textStyleBase2", "mixinDetails"] - } - }, - "onMount": [], - "graphics": {}, - "commands": {}, - "layouts": { - "ListTemplate1": { - "parameters": ["backgroundImage", "title", "logo", "hintText", "listData"], - "item": [ - { - "type": "Container", - "width": "100vw", - "height": "100vh", - "direction": "column", - "items": [ - { - "type": "Image", - "source": "${backgroundImage}", - "scale": "best-fill", - "width": "100vw", - "height": "100vh", - "position": "absolute" - }, - { - "type": "AlexaHeader", - "headerTitle": "${title}", - "headerAttributionImage": "${logo}" - }, - { - "type": "Sequence", - "grow": 1, - "height": "80vh", - "scrollDirection": "vertical", - "paddingLeft": "@marginLeft", - "paddingRight": "@marginRight", - "data": "${listData}", - "numbered": true, - "items": [ - { - "type": "VerticalListItem", - "image": "${data.image.sources[0].url}", - "primaryText": "${data.textContent.primaryText.text}", - "secondaryText": "${data.textContent.secondaryText.text}", - "tertiaryText": "${data.textContent.tertiaryText.text}" - } - ] - } - ] - } - ] - }, - "VerticalListItem": { - "parameters": ["primaryText", "secondaryText", "tertiaryText", "image"], - "item": [ - { - "when": "${viewport.shape == 'round'}", - "type": "Container", - "direction": "row", - "height": 200, - "width": 500, - "alignItems": "center", - "items": [ - { - "type": "Text", - "text": "${ordinal}", - "paddingBottom": "20dp", - "color": "white", - "spacing": "5dp" - }, - { - "type": "Image", - "when": "${image}", - "source": "${image}", - "height": 150, - "width": 150, - "spacing": 15, - "scale": "best-fit", - "align": "top" - }, - { - "type": "Container", - "direction": "column", - "spacing": 25, - "items": [ - { - "type": "Text", - "text": "${primaryText}", - "style": "textStyleDetail", - "grow": 1, - "shrink": 1, - "fontWeight": "300", - "maxLines": 1 - }, - { - "type": "Text", - "text": "${secondaryText}", - "style": "textStyleCaption", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - }, - { - "type": "Text", - "text": "${tertiaryText}", - "style": "textStyleDetails", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - } - ] - } - ] - }, - { - "type": "Container", - "direction": "row", - "height": 125, - "width": 800, - "alignItems": "center", - "items": [ - { - "type": "Text", - "text": "${ordinal}", - "paddingBottom": "20dp", - "color": "white", - "spacing": "5dp" - }, - { - "type": "Image", - "when": "${image}", - "source": "${image}", - "height": 100, - "width": 100, - "align": "top", - "spacing": 50, - "scale": "best-fit" - }, - { - "type": "Container", - "spacing": 30, - "direction": "column", - "items": [ - { - "type": "Text", - "text": "${primaryText}", - "style": "textStyleBody", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - }, - { - "type": "Text", - "text": "${secondaryText}", - "style": "textStyleDetails", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - } - ] - }, - { - "type": "Text", - "text": "${tertiaryText}", - "style": "textStyleBody", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "textAlign": "right", - "maxLines": 1 - } - ] - } - ] - } - }, - "mainTemplate": { - "parameters": ["payload"], - "item": [ - { - "type": "Container", - "id": "BookCabSimpleDialogAPL", - "items": [ - { - "type": "TouchWrapper", - "onPress": { - "type": "SendEvent", - "arguments": ["delegateToColtraneOld"] - }, - "item": { - "type": "Text", - "id": "BookCabSimpleDialogAPL", - "paddingTop": "100", - "paddingLeft": "100", - "color": "green", - "size": 50, - "text": "which date ?" - } - } - ] - } - ] - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/display/confirm_weather_apla_display/document.json b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/display/confirm_weather_apla_display/document.json deleted file mode 100644 index 3bcc0e4a..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/display/confirm_weather_apla_display/document.json +++ /dev/null @@ -1,379 +0,0 @@ -{ - "type": "APL", - "version": "1.1", - "settings": {}, - "theme": "dark", - "import": [ - { - "name": "alexa-layouts", - "version": "1.0.0" - } - ], - "resources": [ - { - "description": "Stock color for the light theme", - "colors": { - "colorTextPrimary": "#151920" - } - }, - { - "description": "Stock color for the dark theme", - "when": "${viewport.theme == 'dark'}", - "colors": { - "colorTextPrimary": "#f0f1ef" - } - }, - { - "description": "Standard font sizes", - "dimensions": { - "textSizeBody": 48, - "textSizePrimary": 27, - "textSizeSecondary": 23, - "textSizeDetails": 20, - "textSizeSecondaryHint": 25 - } - }, - { - "description": "Common spacing values", - "dimensions": { - "spacingThin": 6, - "spacingSmall": 12, - "spacingMedium": 24, - "spacingLarge": 48, - "spacingExtraLarge": 72 - } - }, - { - "description": "Common margins and padding", - "dimensions": { - "marginTop": 40, - "marginLeft": 60, - "marginRight": 60, - "marginBottom": 40 - } - } - ], - "styles": { - "textStyleBase": { - "description": "Base font description; set color", - "values": [ - { - "color": "@colorTextPrimary" - } - ] - }, - "textStyleBase0": { - "description": "Thin version of basic font", - "extend": "textStyleBase", - "values": { - "fontWeight": "100" - } - }, - "textStyleBase1": { - "description": "Light version of basic font", - "extend": "textStyleBase", - "values": { - "fontWeight": "300" - } - }, - "textStyleBase2": { - "description": "Regular version of basic font", - "extend": "textStyleBase", - "values": { - "fontWeight": "500" - } - }, - "mixinBody": { - "values": { - "fontSize": "@textSizeBody" - } - }, - "mixinPrimary": { - "values": { - "fontSize": "@textSizePrimary" - } - }, - "mixinDetails": { - "values": { - "fontSize": "@textSizeDetails" - } - }, - "mixinSecondary": { - "values": { - "fontSize": "@textSizeSecondary" - } - }, - "textStylePrimary": { - "extend": ["textStyleBase1", "mixinPrimary"] - }, - "textStyleSecondary": { - "extend": ["textStyleBase0", "mixinSecondary"] - }, - "textStyleBody": { - "extend": ["textStyleBase1", "mixinBody"] - }, - "textStyleSecondaryHint": { - "values": { - "fontFamily": "Bookerly", - "fontStyle": "italic", - "fontSize": "@textSizeSecondaryHint", - "color": "@colorTextPrimary" - } - }, - "textStyleDetails": { - "extend": ["textStyleBase2", "mixinDetails"] - } - }, - "onMount": [], - "graphics": {}, - "commands": {}, - "layouts": { - "ListTemplate1": { - "parameters": ["backgroundImage", "title", "logo", "hintText", "listData"], - "item": [ - { - "type": "Container", - "width": "100vw", - "height": "100vh", - "direction": "column", - "items": [ - { - "type": "Image", - "source": "${backgroundImage}", - "scale": "best-fill", - "width": "100vw", - "height": "100vh", - "position": "absolute" - }, - { - "type": "AlexaHeader", - "headerTitle": "${title}", - "headerAttributionImage": "${logo}" - }, - { - "type": "Sequence", - "grow": 1, - "height": "80vh", - "scrollDirection": "vertical", - "paddingLeft": "@marginLeft", - "paddingRight": "@marginRight", - "data": "${listData}", - "numbered": true, - "items": [ - { - "type": "VerticalListItem", - "image": "${data.image.sources[0].url}", - "primaryText": "${data.textContent.primaryText.text}", - "secondaryText": "${data.textContent.secondaryText.text}", - "tertiaryText": "${data.textContent.tertiaryText.text}" - } - ] - } - ] - } - ] - }, - "VerticalListItem": { - "parameters": ["primaryText", "secondaryText", "tertiaryText", "image"], - "item": [ - { - "when": "${viewport.shape == 'round'}", - "type": "Container", - "direction": "row", - "height": 200, - "width": 500, - "alignItems": "center", - "items": [ - { - "type": "Text", - "text": "${ordinal}", - "paddingBottom": "20dp", - "color": "white", - "spacing": "5dp" - }, - { - "type": "Image", - "when": "${image}", - "source": "${image}", - "height": 150, - "width": 150, - "spacing": 15, - "scale": "best-fit", - "align": "top" - }, - { - "type": "Container", - "direction": "column", - "spacing": 25, - "items": [ - { - "type": "Text", - "text": "${primaryText}", - "style": "textStyleDetail", - "grow": 1, - "shrink": 1, - "fontWeight": "300", - "maxLines": 1 - }, - { - "type": "Text", - "text": "${secondaryText}", - "style": "textStyleCaption", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - }, - { - "type": "Text", - "text": "${tertiaryText}", - "style": "textStyleDetails", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - } - ] - } - ] - }, - { - "type": "Container", - "direction": "row", - "height": 125, - "width": 800, - "alignItems": "center", - "items": [ - { - "type": "Text", - "text": "${ordinal}", - "paddingBottom": "20dp", - "color": "white", - "spacing": "5dp" - }, - { - "type": "Image", - "when": "${image}", - "source": "${image}", - "height": 100, - "width": 100, - "align": "top", - "spacing": 50, - "scale": "best-fit" - }, - { - "type": "Container", - "spacing": 30, - "direction": "column", - "items": [ - { - "type": "Text", - "text": "${primaryText}", - "style": "textStyleBody", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - }, - { - "type": "Text", - "text": "${secondaryText}", - "style": "textStyleDetails", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - } - ] - }, - { - "type": "Text", - "text": "${tertiaryText}", - "style": "textStyleBody", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "textAlign": "right", - "maxLines": 1 - } - ] - } - ] - } - }, - "mainTemplate": { - "parameters": ["payload"], - "item": [ - { - "type": "Container", - "id": "BookCabSimpleDialogAPL", - "items": [ - { - "type": "TouchWrapper", - "onPress": { - "type": "SendEvent", - "arguments": ["delegateToSkillNew"] - }, - "item": { - "type": "Text", - "id": "BookCabSimpleDialogAPL", - "paddingTop": "100", - "paddingLeft": "100", - "color": "green", - "size": 50, - "text": "delegateToSkillNew" - } - }, - { - "type": "TouchWrapper", - "onPress": { - "type": "SendEvent", - "arguments": ["delegateToSkillOld"] - }, - "item": { - "type": "Text", - "id": "BookCabSimpleDialogAPL", - "paddingTop": "100", - "paddingLeft": "100", - "color": "green", - "size": 50, - "text": "delegateToSkillOld" - } - }, - { - "type": "TouchWrapper", - "onPress": { - "type": "SendEvent", - "arguments": ["delegateToColtraneNew"] - }, - "item": { - "type": "Text", - "id": "BookCabSimpleDialogAPL", - "paddingTop": "100", - "paddingLeft": "100", - "color": "green", - "size": 50, - "text": "delegateToColtraneNew" - } - }, - { - "type": "TouchWrapper", - "onPress": { - "type": "SendEvent", - "arguments": ["delegateToColtraneOld"] - }, - "item": { - "type": "Text", - "id": "BookCabSimpleDialogAPL", - "paddingTop": "100", - "paddingLeft": "100", - "color": "green", - "size": 50, - "text": "delegateToColtraneOld" - } - } - ] - } - ] - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/display/display_de_apl/document.json b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/display/display_de_apl/document.json deleted file mode 100644 index 6fea1ff7..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/display/display_de_apl/document.json +++ /dev/null @@ -1,331 +0,0 @@ -{ - "type": "APL", - "version": "1.1", - "settings": {}, - "theme": "dark", - "import": [ - { - "name": "alexa-layouts", - "version": "1.0.0" - } - ], - "resources": [ - { - "description": "Stock color for the light theme", - "colors": { - "colorTextPrimary": "#151920" - } - }, - { - "description": "Stock color for the dark theme", - "when": "${viewport.theme == 'dark'}", - "colors": { - "colorTextPrimary": "#f0f1ef" - } - }, - { - "description": "Standard font sizes", - "dimensions": { - "textSizeBody": 48, - "textSizePrimary": 27, - "textSizeSecondary": 23, - "textSizeDetails": 20, - "textSizeSecondaryHint": 25 - } - }, - { - "description": "Common spacing values", - "dimensions": { - "spacingThin": 6, - "spacingSmall": 12, - "spacingMedium": 24, - "spacingLarge": 48, - "spacingExtraLarge": 72 - } - }, - { - "description": "Common margins and padding", - "dimensions": { - "marginTop": 40, - "marginLeft": 60, - "marginRight": 60, - "marginBottom": 40 - } - } - ], - "styles": { - "textStyleBase": { - "description": "Base font description; set color", - "values": [ - { - "color": "@colorTextPrimary" - } - ] - }, - "textStyleBase0": { - "description": "Thin version of basic font", - "extend": "textStyleBase", - "values": { - "fontWeight": "100" - } - }, - "textStyleBase1": { - "description": "Light version of basic font", - "extend": "textStyleBase", - "values": { - "fontWeight": "300" - } - }, - "textStyleBase2": { - "description": "Regular version of basic font", - "extend": "textStyleBase", - "values": { - "fontWeight": "500" - } - }, - "mixinBody": { - "values": { - "fontSize": "@textSizeBody" - } - }, - "mixinPrimary": { - "values": { - "fontSize": "@textSizePrimary" - } - }, - "mixinDetails": { - "values": { - "fontSize": "@textSizeDetails" - } - }, - "mixinSecondary": { - "values": { - "fontSize": "@textSizeSecondary" - } - }, - "textStylePrimary": { - "extend": ["textStyleBase1", "mixinPrimary"] - }, - "textStyleSecondary": { - "extend": ["textStyleBase0", "mixinSecondary"] - }, - "textStyleBody": { - "extend": ["textStyleBase1", "mixinBody"] - }, - "textStyleSecondaryHint": { - "values": { - "fontFamily": "Bookerly", - "fontStyle": "italic", - "fontSize": "@textSizeSecondaryHint", - "color": "@colorTextPrimary" - } - }, - "textStyleDetails": { - "extend": ["textStyleBase2", "mixinDetails"] - } - }, - "onMount": [], - "graphics": {}, - "commands": {}, - "layouts": { - "ListTemplate1": { - "parameters": ["backgroundImage", "title", "logo", "hintText", "listData"], - "item": [ - { - "type": "Container", - "width": "100vw", - "height": "100vh", - "direction": "column", - "items": [ - { - "type": "Image", - "source": "${backgroundImage}", - "scale": "best-fill", - "width": "100vw", - "height": "100vh", - "position": "absolute" - }, - { - "type": "AlexaHeader", - "headerTitle": "${title}", - "headerAttributionImage": "${logo}" - }, - { - "type": "Sequence", - "grow": 1, - "height": "80vh", - "scrollDirection": "vertical", - "paddingLeft": "@marginLeft", - "paddingRight": "@marginRight", - "data": "${listData}", - "numbered": true, - "items": [ - { - "type": "VerticalListItem", - "image": "${data.image.sources[0].url}", - "primaryText": "${data.textContent.primaryText.text}", - "secondaryText": "${data.textContent.secondaryText.text}", - "tertiaryText": "${data.textContent.tertiaryText.text}" - } - ] - } - ] - } - ] - }, - "VerticalListItem": { - "parameters": ["primaryText", "secondaryText", "tertiaryText", "image"], - "item": [ - { - "when": "${viewport.shape == 'round'}", - "type": "Container", - "direction": "row", - "height": 200, - "width": 500, - "alignItems": "center", - "items": [ - { - "type": "Text", - "text": "${ordinal}", - "paddingBottom": "20dp", - "color": "white", - "spacing": "5dp" - }, - { - "type": "Image", - "when": "${image}", - "source": "${image}", - "height": 150, - "width": 150, - "spacing": 15, - "scale": "best-fit", - "align": "top" - }, - { - "type": "Container", - "direction": "column", - "spacing": 25, - "items": [ - { - "type": "Text", - "text": "${primaryText}", - "style": "textStyleDetail", - "grow": 1, - "shrink": 1, - "fontWeight": "300", - "maxLines": 1 - }, - { - "type": "Text", - "text": "${secondaryText}", - "style": "textStyleCaption", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - }, - { - "type": "Text", - "text": "${tertiaryText}", - "style": "textStyleDetails", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - } - ] - } - ] - }, - { - "type": "Container", - "direction": "row", - "height": 125, - "width": 800, - "alignItems": "center", - "items": [ - { - "type": "Text", - "text": "${ordinal}", - "paddingBottom": "20dp", - "color": "white", - "spacing": "5dp" - }, - { - "type": "Image", - "when": "${image}", - "source": "${image}", - "height": 100, - "width": 100, - "align": "top", - "spacing": 50, - "scale": "best-fit" - }, - { - "type": "Container", - "spacing": 30, - "direction": "column", - "items": [ - { - "type": "Text", - "text": "${primaryText}", - "style": "textStyleBody", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - }, - { - "type": "Text", - "text": "${secondaryText}", - "style": "textStyleDetails", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - } - ] - }, - { - "type": "Text", - "text": "${tertiaryText}", - "style": "textStyleBody", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "textAlign": "right", - "maxLines": 1 - } - ] - } - ] - } - }, - "mainTemplate": { - "parameters": ["payload"], - "item": [ - { - "type": "Container", - "id": "BookCabSimpleDialogAPL", - "items": [ - { - "type": "TouchWrapper", - "onPress": { - "type": "SendEvent", - "arguments": ["delegateToColtraneOld"] - }, - "item": { - "type": "Text", - "id": "BookCabSimpleDialogAPL", - "paddingTop": "100", - "paddingLeft": "100", - "color": "green", - "size": 50, - "text": "which city ?" - } - } - ] - } - ] - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/display/request_city_apl_display/document.json b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/display/request_city_apl_display/document.json deleted file mode 100644 index 6fea1ff7..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/display/request_city_apl_display/document.json +++ /dev/null @@ -1,331 +0,0 @@ -{ - "type": "APL", - "version": "1.1", - "settings": {}, - "theme": "dark", - "import": [ - { - "name": "alexa-layouts", - "version": "1.0.0" - } - ], - "resources": [ - { - "description": "Stock color for the light theme", - "colors": { - "colorTextPrimary": "#151920" - } - }, - { - "description": "Stock color for the dark theme", - "when": "${viewport.theme == 'dark'}", - "colors": { - "colorTextPrimary": "#f0f1ef" - } - }, - { - "description": "Standard font sizes", - "dimensions": { - "textSizeBody": 48, - "textSizePrimary": 27, - "textSizeSecondary": 23, - "textSizeDetails": 20, - "textSizeSecondaryHint": 25 - } - }, - { - "description": "Common spacing values", - "dimensions": { - "spacingThin": 6, - "spacingSmall": 12, - "spacingMedium": 24, - "spacingLarge": 48, - "spacingExtraLarge": 72 - } - }, - { - "description": "Common margins and padding", - "dimensions": { - "marginTop": 40, - "marginLeft": 60, - "marginRight": 60, - "marginBottom": 40 - } - } - ], - "styles": { - "textStyleBase": { - "description": "Base font description; set color", - "values": [ - { - "color": "@colorTextPrimary" - } - ] - }, - "textStyleBase0": { - "description": "Thin version of basic font", - "extend": "textStyleBase", - "values": { - "fontWeight": "100" - } - }, - "textStyleBase1": { - "description": "Light version of basic font", - "extend": "textStyleBase", - "values": { - "fontWeight": "300" - } - }, - "textStyleBase2": { - "description": "Regular version of basic font", - "extend": "textStyleBase", - "values": { - "fontWeight": "500" - } - }, - "mixinBody": { - "values": { - "fontSize": "@textSizeBody" - } - }, - "mixinPrimary": { - "values": { - "fontSize": "@textSizePrimary" - } - }, - "mixinDetails": { - "values": { - "fontSize": "@textSizeDetails" - } - }, - "mixinSecondary": { - "values": { - "fontSize": "@textSizeSecondary" - } - }, - "textStylePrimary": { - "extend": ["textStyleBase1", "mixinPrimary"] - }, - "textStyleSecondary": { - "extend": ["textStyleBase0", "mixinSecondary"] - }, - "textStyleBody": { - "extend": ["textStyleBase1", "mixinBody"] - }, - "textStyleSecondaryHint": { - "values": { - "fontFamily": "Bookerly", - "fontStyle": "italic", - "fontSize": "@textSizeSecondaryHint", - "color": "@colorTextPrimary" - } - }, - "textStyleDetails": { - "extend": ["textStyleBase2", "mixinDetails"] - } - }, - "onMount": [], - "graphics": {}, - "commands": {}, - "layouts": { - "ListTemplate1": { - "parameters": ["backgroundImage", "title", "logo", "hintText", "listData"], - "item": [ - { - "type": "Container", - "width": "100vw", - "height": "100vh", - "direction": "column", - "items": [ - { - "type": "Image", - "source": "${backgroundImage}", - "scale": "best-fill", - "width": "100vw", - "height": "100vh", - "position": "absolute" - }, - { - "type": "AlexaHeader", - "headerTitle": "${title}", - "headerAttributionImage": "${logo}" - }, - { - "type": "Sequence", - "grow": 1, - "height": "80vh", - "scrollDirection": "vertical", - "paddingLeft": "@marginLeft", - "paddingRight": "@marginRight", - "data": "${listData}", - "numbered": true, - "items": [ - { - "type": "VerticalListItem", - "image": "${data.image.sources[0].url}", - "primaryText": "${data.textContent.primaryText.text}", - "secondaryText": "${data.textContent.secondaryText.text}", - "tertiaryText": "${data.textContent.tertiaryText.text}" - } - ] - } - ] - } - ] - }, - "VerticalListItem": { - "parameters": ["primaryText", "secondaryText", "tertiaryText", "image"], - "item": [ - { - "when": "${viewport.shape == 'round'}", - "type": "Container", - "direction": "row", - "height": 200, - "width": 500, - "alignItems": "center", - "items": [ - { - "type": "Text", - "text": "${ordinal}", - "paddingBottom": "20dp", - "color": "white", - "spacing": "5dp" - }, - { - "type": "Image", - "when": "${image}", - "source": "${image}", - "height": 150, - "width": 150, - "spacing": 15, - "scale": "best-fit", - "align": "top" - }, - { - "type": "Container", - "direction": "column", - "spacing": 25, - "items": [ - { - "type": "Text", - "text": "${primaryText}", - "style": "textStyleDetail", - "grow": 1, - "shrink": 1, - "fontWeight": "300", - "maxLines": 1 - }, - { - "type": "Text", - "text": "${secondaryText}", - "style": "textStyleCaption", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - }, - { - "type": "Text", - "text": "${tertiaryText}", - "style": "textStyleDetails", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - } - ] - } - ] - }, - { - "type": "Container", - "direction": "row", - "height": 125, - "width": 800, - "alignItems": "center", - "items": [ - { - "type": "Text", - "text": "${ordinal}", - "paddingBottom": "20dp", - "color": "white", - "spacing": "5dp" - }, - { - "type": "Image", - "when": "${image}", - "source": "${image}", - "height": 100, - "width": 100, - "align": "top", - "spacing": 50, - "scale": "best-fit" - }, - { - "type": "Container", - "spacing": 30, - "direction": "column", - "items": [ - { - "type": "Text", - "text": "${primaryText}", - "style": "textStyleBody", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - }, - { - "type": "Text", - "text": "${secondaryText}", - "style": "textStyleDetails", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - } - ] - }, - { - "type": "Text", - "text": "${tertiaryText}", - "style": "textStyleBody", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "textAlign": "right", - "maxLines": 1 - } - ] - } - ] - } - }, - "mainTemplate": { - "parameters": ["payload"], - "item": [ - { - "type": "Container", - "id": "BookCabSimpleDialogAPL", - "items": [ - { - "type": "TouchWrapper", - "onPress": { - "type": "SendEvent", - "arguments": ["delegateToColtraneOld"] - }, - "item": { - "type": "Text", - "id": "BookCabSimpleDialogAPL", - "paddingTop": "100", - "paddingLeft": "100", - "color": "green", - "size": 50, - "text": "which city ?" - } - } - ] - } - ] - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/display/request_date_apl_display/document.json b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/display/request_date_apl_display/document.json deleted file mode 100644 index d41ea236..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/display/request_date_apl_display/document.json +++ /dev/null @@ -1,331 +0,0 @@ -{ - "type": "APL", - "version": "1.1", - "settings": {}, - "theme": "dark", - "import": [ - { - "name": "alexa-layouts", - "version": "1.0.0" - } - ], - "resources": [ - { - "description": "Stock color for the light theme", - "colors": { - "colorTextPrimary": "#151920" - } - }, - { - "description": "Stock color for the dark theme", - "when": "${viewport.theme == 'dark'}", - "colors": { - "colorTextPrimary": "#f0f1ef" - } - }, - { - "description": "Standard font sizes", - "dimensions": { - "textSizeBody": 48, - "textSizePrimary": 27, - "textSizeSecondary": 23, - "textSizeDetails": 20, - "textSizeSecondaryHint": 25 - } - }, - { - "description": "Common spacing values", - "dimensions": { - "spacingThin": 6, - "spacingSmall": 12, - "spacingMedium": 24, - "spacingLarge": 48, - "spacingExtraLarge": 72 - } - }, - { - "description": "Common margins and padding", - "dimensions": { - "marginTop": 40, - "marginLeft": 60, - "marginRight": 60, - "marginBottom": 40 - } - } - ], - "styles": { - "textStyleBase": { - "description": "Base font description; set color", - "values": [ - { - "color": "@colorTextPrimary" - } - ] - }, - "textStyleBase0": { - "description": "Thin version of basic font", - "extend": "textStyleBase", - "values": { - "fontWeight": "100" - } - }, - "textStyleBase1": { - "description": "Light version of basic font", - "extend": "textStyleBase", - "values": { - "fontWeight": "300" - } - }, - "textStyleBase2": { - "description": "Regular version of basic font", - "extend": "textStyleBase", - "values": { - "fontWeight": "500" - } - }, - "mixinBody": { - "values": { - "fontSize": "@textSizeBody" - } - }, - "mixinPrimary": { - "values": { - "fontSize": "@textSizePrimary" - } - }, - "mixinDetails": { - "values": { - "fontSize": "@textSizeDetails" - } - }, - "mixinSecondary": { - "values": { - "fontSize": "@textSizeSecondary" - } - }, - "textStylePrimary": { - "extend": ["textStyleBase1", "mixinPrimary"] - }, - "textStyleSecondary": { - "extend": ["textStyleBase0", "mixinSecondary"] - }, - "textStyleBody": { - "extend": ["textStyleBase1", "mixinBody"] - }, - "textStyleSecondaryHint": { - "values": { - "fontFamily": "Bookerly", - "fontStyle": "italic", - "fontSize": "@textSizeSecondaryHint", - "color": "@colorTextPrimary" - } - }, - "textStyleDetails": { - "extend": ["textStyleBase2", "mixinDetails"] - } - }, - "onMount": [], - "graphics": {}, - "commands": {}, - "layouts": { - "ListTemplate1": { - "parameters": ["backgroundImage", "title", "logo", "hintText", "listData"], - "item": [ - { - "type": "Container", - "width": "100vw", - "height": "100vh", - "direction": "column", - "items": [ - { - "type": "Image", - "source": "${backgroundImage}", - "scale": "best-fill", - "width": "100vw", - "height": "100vh", - "position": "absolute" - }, - { - "type": "AlexaHeader", - "headerTitle": "${title}", - "headerAttributionImage": "${logo}" - }, - { - "type": "Sequence", - "grow": 1, - "height": "80vh", - "scrollDirection": "vertical", - "paddingLeft": "@marginLeft", - "paddingRight": "@marginRight", - "data": "${listData}", - "numbered": true, - "items": [ - { - "type": "VerticalListItem", - "image": "${data.image.sources[0].url}", - "primaryText": "${data.textContent.primaryText.text}", - "secondaryText": "${data.textContent.secondaryText.text}", - "tertiaryText": "${data.textContent.tertiaryText.text}" - } - ] - } - ] - } - ] - }, - "VerticalListItem": { - "parameters": ["primaryText", "secondaryText", "tertiaryText", "image"], - "item": [ - { - "when": "${viewport.shape == 'round'}", - "type": "Container", - "direction": "row", - "height": 200, - "width": 500, - "alignItems": "center", - "items": [ - { - "type": "Text", - "text": "${ordinal}", - "paddingBottom": "20dp", - "color": "white", - "spacing": "5dp" - }, - { - "type": "Image", - "when": "${image}", - "source": "${image}", - "height": 150, - "width": 150, - "spacing": 15, - "scale": "best-fit", - "align": "top" - }, - { - "type": "Container", - "direction": "column", - "spacing": 25, - "items": [ - { - "type": "Text", - "text": "${primaryText}", - "style": "textStyleDetail", - "grow": 1, - "shrink": 1, - "fontWeight": "300", - "maxLines": 1 - }, - { - "type": "Text", - "text": "${secondaryText}", - "style": "textStyleCaption", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - }, - { - "type": "Text", - "text": "${tertiaryText}", - "style": "textStyleDetails", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - } - ] - } - ] - }, - { - "type": "Container", - "direction": "row", - "height": 125, - "width": 800, - "alignItems": "center", - "items": [ - { - "type": "Text", - "text": "${ordinal}", - "paddingBottom": "20dp", - "color": "white", - "spacing": "5dp" - }, - { - "type": "Image", - "when": "${image}", - "source": "${image}", - "height": 100, - "width": 100, - "align": "top", - "spacing": 50, - "scale": "best-fit" - }, - { - "type": "Container", - "spacing": 30, - "direction": "column", - "items": [ - { - "type": "Text", - "text": "${primaryText}", - "style": "textStyleBody", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - }, - { - "type": "Text", - "text": "${secondaryText}", - "style": "textStyleDetails", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - } - ] - }, - { - "type": "Text", - "text": "${tertiaryText}", - "style": "textStyleBody", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "textAlign": "right", - "maxLines": 1 - } - ] - } - ] - } - }, - "mainTemplate": { - "parameters": ["payload"], - "item": [ - { - "type": "Container", - "id": "BookCabSimpleDialogAPL", - "items": [ - { - "type": "TouchWrapper", - "onPress": { - "type": "SendEvent", - "arguments": ["delegateToColtraneOld"] - }, - "item": { - "type": "Text", - "id": "BookCabSimpleDialogAPL", - "paddingTop": "100", - "paddingLeft": "100", - "color": "green", - "size": 50, - "text": "which date ?" - } - } - ] - } - ] - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/display/weather_success_apl_display/document.json b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/display/weather_success_apl_display/document.json deleted file mode 100644 index 3bcc0e4a..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/display/weather_success_apl_display/document.json +++ /dev/null @@ -1,379 +0,0 @@ -{ - "type": "APL", - "version": "1.1", - "settings": {}, - "theme": "dark", - "import": [ - { - "name": "alexa-layouts", - "version": "1.0.0" - } - ], - "resources": [ - { - "description": "Stock color for the light theme", - "colors": { - "colorTextPrimary": "#151920" - } - }, - { - "description": "Stock color for the dark theme", - "when": "${viewport.theme == 'dark'}", - "colors": { - "colorTextPrimary": "#f0f1ef" - } - }, - { - "description": "Standard font sizes", - "dimensions": { - "textSizeBody": 48, - "textSizePrimary": 27, - "textSizeSecondary": 23, - "textSizeDetails": 20, - "textSizeSecondaryHint": 25 - } - }, - { - "description": "Common spacing values", - "dimensions": { - "spacingThin": 6, - "spacingSmall": 12, - "spacingMedium": 24, - "spacingLarge": 48, - "spacingExtraLarge": 72 - } - }, - { - "description": "Common margins and padding", - "dimensions": { - "marginTop": 40, - "marginLeft": 60, - "marginRight": 60, - "marginBottom": 40 - } - } - ], - "styles": { - "textStyleBase": { - "description": "Base font description; set color", - "values": [ - { - "color": "@colorTextPrimary" - } - ] - }, - "textStyleBase0": { - "description": "Thin version of basic font", - "extend": "textStyleBase", - "values": { - "fontWeight": "100" - } - }, - "textStyleBase1": { - "description": "Light version of basic font", - "extend": "textStyleBase", - "values": { - "fontWeight": "300" - } - }, - "textStyleBase2": { - "description": "Regular version of basic font", - "extend": "textStyleBase", - "values": { - "fontWeight": "500" - } - }, - "mixinBody": { - "values": { - "fontSize": "@textSizeBody" - } - }, - "mixinPrimary": { - "values": { - "fontSize": "@textSizePrimary" - } - }, - "mixinDetails": { - "values": { - "fontSize": "@textSizeDetails" - } - }, - "mixinSecondary": { - "values": { - "fontSize": "@textSizeSecondary" - } - }, - "textStylePrimary": { - "extend": ["textStyleBase1", "mixinPrimary"] - }, - "textStyleSecondary": { - "extend": ["textStyleBase0", "mixinSecondary"] - }, - "textStyleBody": { - "extend": ["textStyleBase1", "mixinBody"] - }, - "textStyleSecondaryHint": { - "values": { - "fontFamily": "Bookerly", - "fontStyle": "italic", - "fontSize": "@textSizeSecondaryHint", - "color": "@colorTextPrimary" - } - }, - "textStyleDetails": { - "extend": ["textStyleBase2", "mixinDetails"] - } - }, - "onMount": [], - "graphics": {}, - "commands": {}, - "layouts": { - "ListTemplate1": { - "parameters": ["backgroundImage", "title", "logo", "hintText", "listData"], - "item": [ - { - "type": "Container", - "width": "100vw", - "height": "100vh", - "direction": "column", - "items": [ - { - "type": "Image", - "source": "${backgroundImage}", - "scale": "best-fill", - "width": "100vw", - "height": "100vh", - "position": "absolute" - }, - { - "type": "AlexaHeader", - "headerTitle": "${title}", - "headerAttributionImage": "${logo}" - }, - { - "type": "Sequence", - "grow": 1, - "height": "80vh", - "scrollDirection": "vertical", - "paddingLeft": "@marginLeft", - "paddingRight": "@marginRight", - "data": "${listData}", - "numbered": true, - "items": [ - { - "type": "VerticalListItem", - "image": "${data.image.sources[0].url}", - "primaryText": "${data.textContent.primaryText.text}", - "secondaryText": "${data.textContent.secondaryText.text}", - "tertiaryText": "${data.textContent.tertiaryText.text}" - } - ] - } - ] - } - ] - }, - "VerticalListItem": { - "parameters": ["primaryText", "secondaryText", "tertiaryText", "image"], - "item": [ - { - "when": "${viewport.shape == 'round'}", - "type": "Container", - "direction": "row", - "height": 200, - "width": 500, - "alignItems": "center", - "items": [ - { - "type": "Text", - "text": "${ordinal}", - "paddingBottom": "20dp", - "color": "white", - "spacing": "5dp" - }, - { - "type": "Image", - "when": "${image}", - "source": "${image}", - "height": 150, - "width": 150, - "spacing": 15, - "scale": "best-fit", - "align": "top" - }, - { - "type": "Container", - "direction": "column", - "spacing": 25, - "items": [ - { - "type": "Text", - "text": "${primaryText}", - "style": "textStyleDetail", - "grow": 1, - "shrink": 1, - "fontWeight": "300", - "maxLines": 1 - }, - { - "type": "Text", - "text": "${secondaryText}", - "style": "textStyleCaption", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - }, - { - "type": "Text", - "text": "${tertiaryText}", - "style": "textStyleDetails", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - } - ] - } - ] - }, - { - "type": "Container", - "direction": "row", - "height": 125, - "width": 800, - "alignItems": "center", - "items": [ - { - "type": "Text", - "text": "${ordinal}", - "paddingBottom": "20dp", - "color": "white", - "spacing": "5dp" - }, - { - "type": "Image", - "when": "${image}", - "source": "${image}", - "height": 100, - "width": 100, - "align": "top", - "spacing": 50, - "scale": "best-fit" - }, - { - "type": "Container", - "spacing": 30, - "direction": "column", - "items": [ - { - "type": "Text", - "text": "${primaryText}", - "style": "textStyleBody", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - }, - { - "type": "Text", - "text": "${secondaryText}", - "style": "textStyleDetails", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - } - ] - }, - { - "type": "Text", - "text": "${tertiaryText}", - "style": "textStyleBody", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "textAlign": "right", - "maxLines": 1 - } - ] - } - ] - } - }, - "mainTemplate": { - "parameters": ["payload"], - "item": [ - { - "type": "Container", - "id": "BookCabSimpleDialogAPL", - "items": [ - { - "type": "TouchWrapper", - "onPress": { - "type": "SendEvent", - "arguments": ["delegateToSkillNew"] - }, - "item": { - "type": "Text", - "id": "BookCabSimpleDialogAPL", - "paddingTop": "100", - "paddingLeft": "100", - "color": "green", - "size": 50, - "text": "delegateToSkillNew" - } - }, - { - "type": "TouchWrapper", - "onPress": { - "type": "SendEvent", - "arguments": ["delegateToSkillOld"] - }, - "item": { - "type": "Text", - "id": "BookCabSimpleDialogAPL", - "paddingTop": "100", - "paddingLeft": "100", - "color": "green", - "size": 50, - "text": "delegateToSkillOld" - } - }, - { - "type": "TouchWrapper", - "onPress": { - "type": "SendEvent", - "arguments": ["delegateToColtraneNew"] - }, - "item": { - "type": "Text", - "id": "BookCabSimpleDialogAPL", - "paddingTop": "100", - "paddingLeft": "100", - "color": "green", - "size": 50, - "text": "delegateToColtraneNew" - } - }, - { - "type": "TouchWrapper", - "onPress": { - "type": "SendEvent", - "arguments": ["delegateToColtraneOld"] - }, - "item": { - "type": "Text", - "id": "BookCabSimpleDialogAPL", - "paddingTop": "100", - "paddingLeft": "100", - "color": "green", - "size": 50, - "text": "delegateToColtraneOld" - } - } - ] - } - ] - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/AlexaConversationsBye/document.json b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/AlexaConversationsBye/document.json deleted file mode 100644 index a0e2b3a8..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/AlexaConversationsBye/document.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": ["payload"], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "Bye.", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/AlexaConversationsNotifyFailure/document.json b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/AlexaConversationsNotifyFailure/document.json deleted file mode 100644 index 61d75e08..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/AlexaConversationsNotifyFailure/document.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": ["payload"], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "Sorry, there was an error in the request.", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/AlexaConversationsOutOfDomain/document.json b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/AlexaConversationsOutOfDomain/document.json deleted file mode 100644 index e23d5986..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/AlexaConversationsOutOfDomain/document.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": ["payload"], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "Sorry, I don't understand.", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/AlexaConversationsProvideHelp/document.json b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/AlexaConversationsProvideHelp/document.json deleted file mode 100644 index 612a6f6e..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/AlexaConversationsProvideHelp/document.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": ["payload"], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "I can give you the weather report. Just say \"what's the weather\" to start.", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/AlexaConversationsRequestMore/document.json b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/AlexaConversationsRequestMore/document.json deleted file mode 100644 index 32a98507..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/AlexaConversationsRequestMore/document.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": ["payload"], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "What do you want to do.", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/AlexaConversationsThankYou/document.json b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/AlexaConversationsThankYou/document.json deleted file mode 100644 index 4aeb6f4b..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/AlexaConversationsThankYou/document.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": ["payload"], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "Thank you.", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/AlexaConversationsWelcome/document.json b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/AlexaConversationsWelcome/document.json deleted file mode 100644 index b4ce85fe..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/AlexaConversationsWelcome/document.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": ["payload"], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "Welcome to the weather bot, I can give you the weather report. Just say \"what's the weather\" to start.", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/AlexaConversationsYouAreWelcome/document.json b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/AlexaConversationsYouAreWelcome/document.json deleted file mode 100644 index 2cd1b9a8..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/AlexaConversationsYouAreWelcome/document.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": ["payload"], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "You are welcome.", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/alexa_prize_preconditions_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/alexa_prize_preconditions_apla/document.json deleted file mode 100644 index 60503182..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/alexa_prize_preconditions_apla/document.json +++ /dev/null @@ -1,89 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": ["payload"], - "item": { - "type": "Selector", - "description": "Selects the speech response to render when device/locale is not supported", - "items": [ - { - "when": "${payload.result.isDeviceSupported == 0}", - "type": "Speech", - "contentType": "text", - "content": "Sorry, Alexa Prize is not available on this device.", - "description": "" - }, - { - "when": "${payload.result.isLocaleSupported == 0}", - "type": "Speech", - "contentType": "text", - "content": "Sorry, Alexa Prize is not available in your locale.", - "description": "" - }, - { - "when": "${payload.result.isSocialBotAvailable == 0}", - "type": "Speech", - "contentType": "text", - "content": "Right now the Alexa Prize socialbots are busy. Please try again soon and help the university students in their competition to advance conversational A I.", - "description": "" - }, - { - "when": "${payload.result.isAlexaPrizeEnabled == 0}", - "type": "Speech", - "contentType": "text", - "content": "Alexa Prize is currently disabled for this account. Please visit the skill store in the Alexa App to re-enable it.", - "description": "" - }, - { - "when": "${payload.result.isTopicBanned == 1}", - "type": "Speech", - "contentType": "text", - "content": "I’d rather not talk about that, but there’s lots of other things to chat about. Do you still wanna chat?", - "description": "The topic that user wants to talk about is banned, ask if they still want to chat about something else" - }, - { - "when": "${payload.result.isFalseWake == 1}", - "type": "Speech", - "contentType": "text", - "content": "Would you like to chat with an Alexa Prize socialbot?", - "description": "" - }, - { - "when": "${payload.result.handoffPromptOverride == 'HandOffConversationForFilming'}", - "type": "Speech", - "contentType": "text", - "content": "Welcome to the Finals of the Alexa Prize Socialbot Grand Challenge 3, a university competition to advance AI. I’ll get you a socialbot now.", - "description": "" - }, - { - "when": "${payload.result.handoffPromptOverride == 'HandOffConversationForFinals'}", - "type": "Speech", - "contentType": "text", - "content": "Welcome to the Alexa Prize Socialbot Grand Challenge 3: Grand Finale. Here’s one of the finalists.", - "description": "" - }, - { - "when": "${payload.result.handoffPromptOverride == 'HandOffConversationForRepeatUser'}", - "type": "Speech", - "contentType": "text", - "content": "Welcome to the Alexa Prize, a university competition to advance AI. It’s quarterfinals for these socialbots and your ratings help determine who makes it to the semifinals. I’ll get you a socialbot now. When you’re done, say stop, and I’ll ask you for your rating. Your conversation and feedback will be shared with the university to help the socialbots improve.", - "description": "" - }, - { - "when": "${payload.result.handoffPromptOverride == 'CancelHandoff'}", - "type": "Speech", - "contentType": "text", - "content": "Okay", - "description": "" - }, - { - "type": "Speech", - "contentType": "text", - "content": "Welcome to the Alexa Prize, a university competition to advance AI. It’s quarterfinals for these socialbots and your ratings help determine who makes it to the semifinals. I’ll get you a socialbot now. When you’re done, say stop, and I’ll ask you for your rating. Your conversation and feedback will be shared with the university to help the socialbots improve.", - "description": "This is the current default handoff prompt" - } - ] - } - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/confirm_color_for_fruit_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/confirm_color_for_fruit_apla/document.json deleted file mode 100644 index 62c9758b..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/confirm_color_for_fruit_apla/document.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": ["payload"], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "confirm color is ${payload.colorName} ? ", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/confirm_fruitName_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/confirm_fruitName_apla/document.json deleted file mode 100644 index 47433a49..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/confirm_fruitName_apla/document.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": ["payload"], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "confirm fruit ${payload.fruitName} ? ", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/getEmployeePosition_success_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/getEmployeePosition_success_apla/document.json deleted file mode 100644 index d0a91481..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/getEmployeePosition_success_apla/document.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": ["payload"], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "${payload.result.name1} born on ${payload.result.a_dateOfBirth} with employee id ${payload.result.emplyee1id} , is an ${payload.result.position} ", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/no_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/no_apla/document.json deleted file mode 100644 index 96a3af82..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/no_apla/document.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": ["payload"], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "I'm sorry you didn't like it", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/nothing2_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/nothing2_apla/document.json deleted file mode 100644 index af75a7a5..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/nothing2_apla/document.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": ["payload"], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "The number you gave us was not 3.", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/nothing_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/nothing_apla/document.json deleted file mode 100644 index bca77c74..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/nothing_apla/document.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": ["payload"], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "The number you gave us was 3.", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/numericfeedback_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/numericfeedback_apla/document.json deleted file mode 100644 index 2219120c..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/numericfeedback_apla/document.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": ["payload"], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "Your random number was ${payload.num}. How did we do? Please give this interaction a rating between 1-5, where 5 is the highest rating", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/rating_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/rating_apla/document.json deleted file mode 100644 index 06b50d68..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/rating_apla/document.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": ["payload"], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "rating please?", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/requestArgs_request_fruitName_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/requestArgs_request_fruitName_apla/document.json deleted file mode 100644 index 5e5d608a..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/requestArgs_request_fruitName_apla/document.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": ["payload"], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "tell me the fruit name ?", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - }, - { - "type": "Speech", - "contentType": "text", - "content": "random slection tell me the fruit name ?", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/request_city_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/request_city_apla/document.json deleted file mode 100644 index 64297b5e..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/request_city_apla/document.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": ["payload"], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "Which city?", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/request_city_date_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/request_city_date_apla/document.json deleted file mode 100644 index a55ea5e1..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/request_city_date_apla/document.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": ["payload"], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "Which city and for which date?", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/request_colorName_multiple_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/request_colorName_multiple_apla/document.json deleted file mode 100644 index 5e5891e1..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/request_colorName_multiple_apla/document.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": ["payload"], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "which color?", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/request_date_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/request_date_apla/document.json deleted file mode 100644 index af3a3f7d..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/request_date_apla/document.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": ["payload"], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "Which date?", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/request_dob_getDate_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/request_dob_getDate_apla/document.json deleted file mode 100644 index b70a2ac6..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/request_dob_getDate_apla/document.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": ["payload"], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "SSML", - "content": "provide date?", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/request_getEmploeeID_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/request_getEmploeeID_apla/document.json deleted file mode 100644 index 32c39133..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/request_getEmploeeID_apla/document.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": ["payload"], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "SSML", - "content": "provide employee id?", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/request_name_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/request_name_apla/document.json deleted file mode 100644 index db05dfee..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/request_name_apla/document.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": ["payload"], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "SSML", - "content": "what is your cool name?", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/success_colorFruitAPI_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/success_colorFruitAPI_apla/document.json deleted file mode 100644 index b566e3fb..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/success_colorFruitAPI_apla/document.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": ["payload"], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "price of an ${payload.result.fruitName} is free bucks ", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/success_fruitPriceAPI_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/success_fruitPriceAPI_apla/document.json deleted file mode 100644 index 0db81389..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/success_fruitPriceAPI_apla/document.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": ["payload"], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "price of an ${payload.result.fruitName} is ${payload.result.price} bucks ", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/weather_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/weather_apla/document.json deleted file mode 100644 index b2f5f3d9..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/weather_apla/document.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": ["payload"], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "when": "${payload.weatherResult != null && payload.weatherResult.cityName != null && payload.weatherResult.highTemp != null && payload.weatherResult.lowTemp != null}", - "type": "Speech", - "contentType": "text", - "content": "In ${payload.weatherResult.cityName}, it's a high of ${payload.weatherResult.highTemp} degrees and a low of ${payload.weatherResult.lowTemp} degrees.", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - }, - { - "when": "${payload.weatherResult != null && payload.weatherResult.cityNameChanged != null && payload.weatherResult.highTemp != null && payload.weatherResult.lowTemp != null}", - "type": "Speech", - "contentType": "text", - "content": "In ${payload.weatherResult.cityName}, it's a high of ${payload.weatherResult.highTemp} degrees and a low of ${payload.weatherResult.lowTemp} degrees.", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/weather_apla_de_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/weather_apla_de_apla/document.json deleted file mode 100644 index 1571f788..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/weather_apla_de_apla/document.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": ["payload"], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "when": "${payload.weatherResult != null && payload.weatherResult.cityName != null && payload.weatherResult.highTemp != null && payload.weatherResult.lowTemp != null}", - "type": "Speech", - "contentType": "text", - "content": "German result satheesh In ${payload.weatherResult.cityName}, it's a high of ${payload.weatherResult.highTemp} degrees and a low of ${payload.weatherResult.lowTemp} degrees.", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - }, - { - "when": "${payload.weatherResult != null && payload.weatherResult.cityNameChanged != null && payload.weatherResult.highTemp != null && payload.weatherResult.lowTemp != null}", - "type": "Speech", - "contentType": "text", - "content": "German result satheesh In ${payload.weatherResult.cityName}, it's a high of ${payload.weatherResult.highTemp} degrees and a low of ${payload.weatherResult.lowTemp} degrees.", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/yes_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/yes_apla/document.json deleted file mode 100644 index a443c91e..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/yes_apla/document.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": ["payload"], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "Nice! Glad you like it", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/yesnofeedback_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/yesnofeedback_apla/document.json deleted file mode 100644 index fd08347e..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/response/prompts/yesnofeedback_apla/document.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": ["payload"], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "Your number was ${payload.num}. Is this a good number, yes or no?", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/skill.json b/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/skill.json deleted file mode 100644 index 8cc42910..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-3/skill-package/skill.json +++ /dev/null @@ -1,105 +0,0 @@ -{ - "manifest": { - "apis": { - "custom": { - "dialogManagement": { - "dialogManagers": [ - { - "type": "AMAZON.Conversations" - } - ] - }, - "endpoint": { - "uri": "arn:aws:lambda:us-east-1:658396899051:function:6735d9fd-a8b2-4a97-bb37-7435c55c9ff0:Release_0" - }, - "interfaces": [ - { - "supportedViewports": [ - { - "maxHeight": 540, - "maxWidth": 960, - "minHeight": 540, - "minWidth": 960, - "mode": "TV", - "shape": "RECTANGLE" - }, - { - "maxHeight": 480, - "maxWidth": 480, - "minHeight": 480, - "minWidth": 480, - "mode": "HUB", - "shape": "ROUND" - }, - { - "maxHeight": 600, - "maxWidth": 1024, - "minHeight": 600, - "minWidth": 1024, - "mode": "HUB", - "shape": "RECTANGLE" - }, - { - "maxHeight": 800, - "maxWidth": 1280, - "minHeight": 800, - "minWidth": 1280, - "mode": "HUB", - "shape": "RECTANGLE" - }, - { - "maxHeight": 480, - "maxWidth": 960, - "minHeight": 480, - "minWidth": 960, - "mode": "HUB", - "shape": "RECTANGLE" - } - ], - "type": "ALEXA_PRESENTATION_APL" - } - ], - "regions": { - "EU": { - "endpoint": { - "uri": "arn:aws:lambda:eu-west-1:658396899051:function:6735d9fd-a8b2-4a97-bb37-7435c55c9ff0:Release_0" - } - }, - "NA": { - "endpoint": { - "uri": "arn:aws:lambda:us-east-1:658396899051:function:6735d9fd-a8b2-4a97-bb37-7435c55c9ff0:Release_0" - } - }, - "FE": { - "endpoint": { - "uri": "arn:aws:lambda:us-west-2:658396899051:function:6735d9fd-a8b2-4a97-bb37-7435c55c9ff0:Release_0" - } - } - } - } - }, - "manifestVersion": "1.0", - "publishingInformation": { - "category": "KNOWLEDGE_AND_TRIVIA", - "distributionCountries": [], - "isAvailableWorldwide": true, - "locales": { - "en-US": { - "description": "Sample Full Description", - "examplePhrases": ["Alexa open pizza reference", "order a pizza", "help"], - "keywords": [], - "name": "engineering test skill three", - "summary": "Sample Short Description" - }, - "de-DE": { - "description": "Sample Full Description", - "examplePhrases": ["Alexa open pizza reference", "order a pizza", "help"], - "keywords": [], - "name": "engineering test skill three", - "summary": "Sample Short Description" - } - }, - "testingInstructions": "Sample Testing Instructions." - } - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/.ask/ask-states.json b/test/unit/fixture/dialog-evaluate/test-project-5/.ask/ask-states.json deleted file mode 100644 index e605e322..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-5/.ask/ask-states.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "askcliStatesVersion": "2020-03-31", - "profiles": { - "default": { - "skillId": "amzn1.ask.skill.b2d1f6dd-e43f-40eb-87a5-8cfd9650d249" - } - } -} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/ask-resources.json b/test/unit/fixture/dialog-evaluate/test-project-5/ask-resources.json deleted file mode 100644 index be9cb8d1..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-5/ask-resources.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "askcliResourcesVersion": "2020-03-31", - "profiles": { - "default": { - "skillMetadata": { - "src": "./skill-package" - } - } - } -} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/conversations/Samenamespace.acdl b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/conversations/Samenamespace.acdl deleted file mode 100644 index b173cdf7..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/conversations/Samenamespace.acdl +++ /dev/null @@ -1,7 +0,0 @@ -namespace com.weatherbot.apis - -import com.amazon.ask.types.builtins.AMAZON.DATE -import com.weatherbot.types.WeatherResult -import slotTypes.customCity - -action WeatherResult getWeather(customCity cityName, DATE date) diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/conversations/apisMine.acdl b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/conversations/apisMine.acdl deleted file mode 100644 index 8154a222..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/conversations/apisMine.acdl +++ /dev/null @@ -1,50 +0,0 @@ -namespace com.weatherbot.apis - -import com.amazon.alexa.schema.Nothing -import com.amazon.ask.types.builtins.AMAZON.Color -import com.amazon.ask.types.builtins.AMAZON.Food -import com.amazon.ask.types.builtins.AMAZON.NUMBER -import com.amazon.ask.types.builtins.AMAZON.US_CITY -import com.weatherbot.types.bookCabResult -import com.weatherbot.types.bookedFlightResult -import com.weatherbot.types.result -import com.weatherbot.types.result_one -import com.weatherbot.types.resultthree -import slotTypes.StringLiteral -import slotTypes.city_name_one -import slotTypes.city_name_two -import slotTypes.complexNames -import slotTypes.crust -import slotTypes.pickUpFrom -import slotTypes.size -import slotTypes.toppings - -action result colorFruitNameAAA(Food fruitName = nothing) - -action resultthree colorFruitName(Color colorName, Food fruitName = nothing) - -action result fruitNameAPI(Color colorName = nothing, Food fruitName = nothing) - -action result fruitNameAPIAA(Color colorName) - -action NUMBER numberOfVisits() - -action NUMBER getCooler() - -action NUMBER welcomeApi() - -action Nothing getHeater() - -action result_one favColorSign_Name(complexNames name) - -action bookedFlightResult bookFlightAPI(city_name_one source, city_name_two destination) - -action bookCabResult bookCabAPI(pickUpFrom pickUpFrom, city_name_one dropTo) - -action Nothing secondEarthAPI() - -action StringLiteral OrderTwoToppingPizza(toppings second_topping, toppings first_topping, crust crust, size size = nothing) - -action Nothing satheesh(US_CITY citsy) - -action Nothing Satheesh(US_CITY citsy) diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/conversations/basicOfferDialog.acdl b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/conversations/basicOfferDialog.acdl deleted file mode 100644 index c53a0a9f..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/conversations/basicOfferDialog.acdl +++ /dev/null @@ -1,134 +0,0 @@ -namespace offerDialogFile - -import com.amazon.alexa.ask.conversations.Affirm -import com.amazon.alexa.ask.conversations.CarryOverArgument -import com.amazon.alexa.ask.conversations.Inform -import com.amazon.alexa.ask.conversations.Invoke -import com.amazon.alexa.ask.conversations.Notify -import com.amazon.alexa.ask.conversations.Offer -import com.amazon.alexa.ask.conversations.Request -import com.amazon.alexa.ask.conversations.expect -import com.amazon.alexa.ask.conversations.response -import com.amazon.alexa.schema.Nothing -import com.weatherbot.apis.bookCabAPI -import com.weatherbot.apis.bookFlightAPI -import com.weatherbot.types.bookCabResult -import com.weatherbot.types.bookedFlightResult -import com.weatherbot.utteracesets.affirmCabAPIEvent -import com.weatherbot.utteracesets.bookFlightEvent -import com.weatherbot.utteracesets.informFromBookFlight -import com.weatherbot.utteracesets.informPickUpFromBookCab -import com.weatherbot.utteracesets.informToBookFlight -import prompts.requestFromBookFlight_apla -import prompts.requestPickUpFromBookCab_apla -import prompts.requestToBookFlight_apla -import prompts.successBookCabAPI_apla -import prompts.successBookFlightAPI_apla - -type payloadBookFlightAPI { - bookedFlightResult resultTwo -} - -type payloadOfferResult { - bookCabResult result -} - -dialog Nothing complex_two() { - sample { - expect( - Invoke, - bookFlightEvent - ) - response( - requestFromBookFlight_apla, - Request { - arguments = [ - bookFlightAPI.arguments.source - ] - }, - nothing, - nothing, - nothing - ) - sourceFlightEvent = expect( - Inform, - informFromBookFlight - ) - response( - requestToBookFlight_apla, - Request { - arguments = [ - bookFlightAPI.arguments.destination - ] - }, - nothing, - nothing, - nothing - ) - destinationFlightEvent = expect( - Inform, - informToBookFlight - ) - resultFlightApi = bookFlightAPI( - sourceFlightEvent.source, - destinationFlightEvent.destination - ) - response( - successBookFlightAPI_apla, - Notify { - actionName = bookFlightAPI, - success = true - }, - Offer { - actionName = bookCabAPI, - arguments = [ - bookCabAPI.arguments.pickUpFrom - ], - carryOverArguments = [ - CarryOverArgument { - argument = bookCabAPI.arguments.dropTo, - source = resultFlightApi.source - } - ] - }, - payloadBookFlightAPI { - resultTwo = resultFlightApi - }, - nothing - ) - expect( - Affirm, - affirmCabAPIEvent - ) - response( - requestPickUpFromBookCab_apla, - Request { - arguments = [ - bookCabAPI.arguments.pickUpFrom - ] - }, - nothing, - nothing, - nothing - ) - PickUpCabEvent = expect( - Inform, - informPickUpFromBookCab - ) - resultOne = bookCabAPI( - PickUpCabEvent.pickUpFrom, - resultFlightApi.source - ) - response( - successBookCabAPI_apla, - Notify { - actionName = bookCabAPI - }, - nothing, - payloadOfferResult { - result = resultOne - }, - nothing - ) - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/conversations/conditions.acdl b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/conversations/conditions.acdl deleted file mode 100644 index b14437ee..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/conversations/conditions.acdl +++ /dev/null @@ -1,172 +0,0 @@ -namespace conditionsACDlFile - -import com.amazon.alexa.ask.conversations.Inform -import com.amazon.alexa.ask.conversations.Invoke -import com.amazon.alexa.ask.conversations.MultiModalResponse -import com.amazon.alexa.ask.conversations.Notify -import com.amazon.alexa.ask.conversations.Offer -import com.amazon.alexa.ask.conversations.ReqAlt -import com.amazon.alexa.ask.conversations.Request -import com.amazon.alexa.ask.conversations.RequestArguments -import com.amazon.alexa.ask.conversations.ensure -import com.amazon.alexa.ask.conversations.expect -import com.amazon.alexa.ask.conversations.response -import com.amazon.alexa.ask.conversations.size -import com.amazon.alexa.schema.Nothing -import com.amazon.alexa.schema.Thing -import com.weatherbot.apis.favColorSign_Name -import com.weatherbot.apis.getWeather -import com.weatherbot.types.WeatherResult -import com.weatherbot.types.result_one -import com.weatherbot.utteracesets.getWeatherEventNoArgs -import com.weatherbot.utteracesets.informCityEvent -import com.weatherbot.utteracesets.informComplexNameEvent -import com.weatherbot.utteracesets.informDateEvent -import displays.request_city_apl_display -import prompts.request_city_apla -import prompts.request_date_apla -import prompts.request_name_apla -import prompts.success_favColorSign_Name_apla -import prompts.weather_success_apla - -type payload_one { - result_one result -} - -type payload_one_two { - WeatherResult weatherResult -} - -dialog Nothing conditionComplex() { - sample { - expect( - Invoke, - getWeatherEventNoArgs - ) - request_city_multimodal = MultiModalResponse { - apla = request_city_apla, - apl = request_city_apl_display - } - request_date_multimodal = MultiModalResponse { - apla = request_date_apla, - apl = request_city_apl_display - } - response( - request_city_multimodal, - Request { - arguments = [ - getWeather.arguments.cityName - ] - }, - nothing, - nothing, - nothing - ) - cityEvent = expect( - Inform, - informCityEvent - ) - response( - request_date_multimodal, - Request { - arguments = [ - getWeather.arguments.date - ] - }, - nothing, - nothing, - nothing - ) - dateEvent = expect( - Inform, - informDateEvent - ) - weatherResult = getWeather( - cityEvent.cityName, - dateEvent.date - ) - if (((weatherResult.highTemp < 3 && weatherResult.lowTemp > 0) && size( - weatherResult.itemsToUse - ) > 1)) { - response( - weather_success_apla, - Notify { - actionName = getWeather - }, - Offer { - actionName = favColorSign_Name, - arguments = [ - favColorSign_Name.arguments.name - ] - }, - nothing, - nothing - ) - ensure( - RequestArguments { - arguments = [ - favColorSign_Name.arguments.name - ], - response = request_name_apla - } - ) - ComplexNameEvent = expect( - Inform, - informComplexNameEvent - ) - resultOne_one = favColorSign_Name( - ComplexNameEvent.name - ) - response( - success_favColorSign_Name_apla, - Notify { - actionName = favColorSign_Name - }, - nothing, - payload_one { - result = resultOne_one - }, - nothing - ) - } else { - response( - weather_success_apla, - Notify { - actionName = getWeather, - success = false - }, - ReqAlt { - arguments = [ - getWeather.arguments.cityName - ] - }, - payload_one_two { - weatherResult = weatherResult - }, - nothing - ) - cityEvent_new = expect( - Inform, - informCityEvent - ) - weatherResult_two = getWeather( - cityEvent_new.cityName, - dateEvent.date - ) - successAPLWithAPLsa_nw = MultiModalResponse { - apla = weather_success_apla - } - response( - successAPLWithAPLsa_nw, - Notify { - actionName = getWeather - }, - nothing, - payload_one_two { - weatherResult = weatherResult_two - }, - nothing - ) - } - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/conversations/conversation_empty.acdl b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/conversations/conversation_empty.acdl deleted file mode 100644 index 0c63977c..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/conversations/conversation_empty.acdl +++ /dev/null @@ -1,109 +0,0 @@ -namespace com.numberbot - -import com.amazon.alexa.ask.conversations.APLA -import com.amazon.alexa.ask.conversations.Action -import com.amazon.alexa.ask.conversations.Bye -import com.amazon.alexa.ask.conversations.Invoke -import com.amazon.alexa.ask.conversations.Notify -import com.amazon.alexa.ask.conversations.Offer -import com.amazon.alexa.ask.conversations.RequestArguments -import com.amazon.alexa.ask.conversations.ensure -import com.amazon.alexa.ask.conversations.expect -import com.amazon.alexa.ask.conversations.response -import com.amazon.alexa.ask.conversations.utterances -import com.amazon.alexa.schema.Nothing -import com.amazon.alexa.schema.Number -import com.amazon.alexa.schema.Thing -import com.amazon.ask.types.builtins.AMAZON.NUMBER -import prompts.AlexaConversationsBye -import prompts.numericfeedback_apla -import prompts.rating_apla - -type NumPayload { - Number num -} - -type RatingRequest { - NUMBER rating -} - -InformRatingEvent = utterances( - [ - "my score is {rating}", - "that was a {rating} conversation", - "i rate you a {rating}", - "{rating}" - ] -) - -getStart = utterances( - [ - "give me a number please" - ] -) - -action Nothing saveRating(Number rating) - -action Number getNumber() - -dialog Nothing GetFeedback(APLA feedback_prompt, Thing payload, Action notifyAction) { - sample { - response( - feedback_prompt, - Notify { - actionName = notifyAction, - success = true - }, - Offer { - actionName = saveRating, - arguments = [ - saveRating.arguments.rating - ] - }, - payload, - nothing - ) - myRating = expect( - Invoke, - InformRatingEvent - ) - ensure( - RequestArguments { - arguments = [ - saveRating.arguments.rating - ], - response = rating_apla - } - ) - saveRating( - myRating.rating - ) - } -} - -dialog Nothing MainDialog() { - sample { - expect( - Invoke, - getStart - ) - num = getNumber() - GetFeedback( - feedback_prompt = numericfeedback_apla, - payload = NumPayload { - num = num - }, - notifyAction = getNumber - ) - response( - AlexaConversationsBye, - Notify { - actionName = saveRating, - success = true - }, - Bye {}, - nothing, - nothing - ) - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/conversations/delegateToSkill.acdl b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/conversations/delegateToSkill.acdl deleted file mode 100644 index e9c9d884..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/conversations/delegateToSkill.acdl +++ /dev/null @@ -1,29 +0,0 @@ -namespace delegateToSkill - -import com.amazon.alexa.ask.conversations.Invoke -import com.amazon.alexa.ask.conversations.Notify -import com.amazon.alexa.ask.conversations.expect -import com.amazon.alexa.ask.conversations.response -import com.amazon.alexa.schema.Nothing -import com.weatherbot.apis.secondEarthAPI -import com.weatherbot.utteracesets.delegateToSkill -import prompts.secondEarthAPI_apla - -dialog Nothing testTwo() { - sample { - expect( - Invoke, - delegateToSkill - ) - secondEarthAPI() - response( - secondEarthAPI_apla, - Notify { - actionName = secondEarthAPI - }, - nothing, - nothing, - nothing - ) - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/conversations/dialogWeather.acdl b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/conversations/dialogWeather.acdl deleted file mode 100644 index 60962dc9..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/conversations/dialogWeather.acdl +++ /dev/null @@ -1,9 +0,0 @@ -namespace dialogWeather - -import com.amazon.ask.types.builtins.AMAZON.DATE -import slotTypes.customCity - -type payloadConfirmArgsDialogWeather { - optional customCity cityName - optional DATE date -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/conversations/listDialogWithConditions.acdl b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/conversations/listDialogWithConditions.acdl deleted file mode 100644 index 58f932f7..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/conversations/listDialogWithConditions.acdl +++ /dev/null @@ -1,250 +0,0 @@ -namespace listDialog - -import com.amazon.alexa.ask.conversations.Affirm -import com.amazon.alexa.ask.conversations.ConfirmAction -import com.amazon.alexa.ask.conversations.Inform -import com.amazon.alexa.ask.conversations.Invoke -import com.amazon.alexa.ask.conversations.Notify -import com.amazon.alexa.ask.conversations.Request -import com.amazon.alexa.ask.conversations.expect -import com.amazon.alexa.ask.conversations.response -import com.amazon.alexa.ask.conversations.size -import com.amazon.alexa.ask.conversations.utterances -import com.amazon.alexa.schema.List -import com.amazon.alexa.schema.Nothing -import com.amazon.ask.types.builtins.AMAZON.Food -import com.weatherbot.apis.colorFruitNameAAA -import com.weatherbot.apis.fruitNameAPI -import com.weatherbot.apis.numberOfVisits -import com.weatherbot.types.result -import com.weatherbot.utteracesets.GiveMeTodaySpecialsEvent -import com.weatherbot.utteracesets.affirmCookAPIEvent -import com.weatherbot.utteracesets.cookWithTwoIngredientsEvent -import com.weatherbot.utteracesets.getFruitPriceEvent -import com.weatherbot.utteracesets.getMarketPlaceEvent -import com.weatherbot.utteracesets.informFoodNameEvent -import com.weatherbot.utteracesets.informMarketPlaceNameEvent -import com.weatherbot.utteracesets.informfruitNameEvent -import prompts.SuccessGiveMeTodaySpecialsEvent_apla -import prompts.confirm_main_addon_list_apla -import prompts.requestArgs_request_fruitName_apla -import prompts.request_listAddOns_apla -import prompts.request_mainFoodName_apla -import prompts.success_cookingAPI_apla -import prompts.success_fruitPriceAPI_apla -import slotTypes.Mix -import slotTypes.orderStatus - -type addOnShell { - List addOn -} - -action orderStatus cookingAPI(Food foodName, List addOn) - -action List todaySpecials() - -informlistAddOnsEvent = utterances( - [ - "{addOn}", - "add {addOn}", - "mix {addOn}" - ] -) - -type payloadStatuscookWithTwoIngredients { - orderStatus status -} - -type payloadGiveMeTodaySpecials { - List result -} - -type payloadgetFruitPriceEvent { - result result -} - -type payloadConfirmActionComplex { - optional Food foodName - List addOn -} - -type paylaodCompleFruit { - Food fruitName -} - -type WrongpayloadGiveMeTodaySpecialsNew { - List ListOfMix1 - Mix Mix1 -} - -type payloadGiveMeTodaySpecialsNew { - List ListOfMix1 -} - -type InteractionFoodName { - Food foodName -} - -dialog Nothing complex() { - sample { - expect( - Invoke, - cookWithTwoIngredientsEvent - ) - response( - request_listAddOns_apla, - Request { - arguments = [ - cookingAPI.arguments.addOn - ] - }, - nothing, - nothing, - nothing - ) - listAddOnsEvent = expect( - Inform, - informlistAddOnsEvent - ) - response( - request_mainFoodName_apla, - Request { - arguments = [ - cookingAPI.arguments.foodName - ] - }, - nothing, - nothing, - nothing - ) - FoodNameEvent = expect( - Inform, - informFoodNameEvent - ) - response( - confirm_main_addon_list_apla, - ConfirmAction { - actionName = cookingAPI - }, - nothing, - payloadConfirmActionComplex { - foodName = FoodNameEvent.foodName, - addOn = listAddOnsEvent.addOn - }, - nothing - ) - expect( - Affirm, - affirmCookAPIEvent - ) - resultOne = cookingAPI( - FoodNameEvent.foodName, - listAddOnsEvent.addOn - ) - response( - success_cookingAPI_apla, - Notify { - actionName = cookingAPI - }, - nothing, - payloadStatuscookWithTwoIngredients { - status = resultOne - }, - nothing - ) - } - sample { - expect( - Invoke, - GiveMeTodaySpecialsEvent - ) - numberOfVisits() - resultOne = todaySpecials() - if (size( - resultOne - ) == 1) { - response( - SuccessGiveMeTodaySpecialsEvent_apla, - Notify { - actionName = todaySpecials - }, - nothing, - payloadGiveMeTodaySpecials { - result = resultOne - }, - nothing - ) - } - } - sample { - expect( - Invoke, - getFruitPriceEvent - ) - response( - requestArgs_request_fruitName_apla, - Request { - arguments = [ - fruitNameAPI.arguments.fruitName - ] - }, - nothing, - nothing, - nothing - ) - fruitNameEvent = expect( - Inform, - informfruitNameEvent - ) - resultOne = fruitNameAPI( - nothing, - fruitNameEvent.fruitName - ) - response( - success_fruitPriceAPI_apla, - Notify { - actionName = fruitNameAPI - }, - nothing, - payloadgetFruitPriceEvent { - result = resultOne - }, - nothing - ) - } - sample { - expect( - Invoke, - getMarketPlaceEvent - ) - response( - requestArgs_request_fruitName_apla, - Request { - arguments = [ - colorFruitNameAAA.arguments.fruitName - ] - }, - nothing, - nothing, - nothing - ) - MarketPlaceInformResponseEvent = expect( - Inform, - informMarketPlaceNameEvent - ) - resultOne = colorFruitNameAAA( - MarketPlaceInformResponseEvent.fruitName - ) - response( - success_fruitPriceAPI_apla, - Notify { - actionName = colorFruitNameAAA - }, - nothing, - payloadgetFruitPriceEvent { - result = resultOne - }, - nothing - ) - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/conversations/optionalDelegate.acdl b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/conversations/optionalDelegate.acdl deleted file mode 100644 index 200a624f..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/conversations/optionalDelegate.acdl +++ /dev/null @@ -1,162 +0,0 @@ -namespace optionalArgACDL - -import com.amazon.alexa.ask.conversations.Affirm -import com.amazon.alexa.ask.conversations.ConfirmAction -import com.amazon.alexa.ask.conversations.ConfirmArgs -import com.amazon.alexa.ask.conversations.Inform -import com.amazon.alexa.ask.conversations.Invoke -import com.amazon.alexa.ask.conversations.MultiModalResponse -import com.amazon.alexa.ask.conversations.Notify -import com.amazon.alexa.ask.conversations.Request -import com.amazon.alexa.ask.conversations.expect -import com.amazon.alexa.ask.conversations.response -import com.amazon.alexa.ask.conversations.utterances -import com.amazon.alexa.schema.Nothing -import com.amazon.alexa.schema.Thing -import com.weatherbot.apis.favColorSign_Name -import com.weatherbot.types.payloadConfirmActionConditionComplex -import com.weatherbot.types.result_one -import com.weatherbot.utteracesets.affirmFavColorEvent -import com.weatherbot.utteracesets.informComplexNameEvent -import prompts.confirmAction_complexNames_apla -import prompts.confirmArgs_complexNames_apla -import prompts.request_name_apla -import prompts.success_favColorSign_Name_apla -import slotTypes.complexNames - -type payloadResult_optional { - result_one result -} - -type payloadResult_optional_name { - complexNames name -} - -getFavColorEvent = utterances( - [ - "what is my favourite color", - "tell my favourite color" - ] -) - -getFavColorEventTwo = utterances( - [ - "guess the color" - ] -) - -dialog Nothing optiOnal() { - sample { - expect( - Invoke, - getFavColorEvent - ) - response( - MultiModalResponse { - apla = request_name_apla - }, - Request { - arguments = [ - favColorSign_Name.arguments.name - ] - }, - nothing, - nothing, - nothing - ) - ComplexNameEvent = expect( - Inform, - informComplexNameEvent - ) - response( - confirmArgs_complexNames_apla, - ConfirmArgs { - arguments = [ - favColorSign_Name.arguments.name - ] - }, - nothing, - payloadConfirmActionConditionComplex { - name = ComplexNameEvent.name - }, - nothing - ) - expect( - Affirm, - affirmFavColorEvent - ) - resultOne = favColorSign_Name( - ComplexNameEvent.name - ) - response( - success_favColorSign_Name_apla, - Notify { - actionName = favColorSign_Name - }, - nothing, - payloadResult_optional { - result = resultOne - }, - nothing - ) - } -} - -type PAYLOAD_TYPE01 { - complexNames name -} - -dialog Nothing optiOnalTwo() { - sample { - expect( - Invoke, - getFavColorEventTwo - ) - response( - MultiModalResponse { - apla = request_name_apla - }, - Request { - arguments = [ - favColorSign_Name.arguments.name - ] - }, - nothing, - nothing, - nothing - ) - ComplexNameEvent = expect( - Inform, - informComplexNameEvent - ) - response( - confirmAction_complexNames_apla, - ConfirmAction { - actionName = favColorSign_Name - }, - nothing, - payloadConfirmActionConditionComplex { - name = ComplexNameEvent.name - }, - nothing - ) - expect( - Affirm, - affirmFavColorEvent - ) - result1 = favColorSign_Name( - ComplexNameEvent.name - ) - response( - success_favColorSign_Name_apla, - Notify { - actionName = favColorSign_Name - }, - nothing, - payloadResult_optional { - result = result1 - }, - nothing - ) - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/conversations/pizza.acdl b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/conversations/pizza.acdl deleted file mode 100644 index 777ac168..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/conversations/pizza.acdl +++ /dev/null @@ -1,196 +0,0 @@ -namespace pizzaAcdl - -import com.amazon.alexa.ask.conversations.Affirm -import com.amazon.alexa.ask.conversations.ConfirmAction -import com.amazon.alexa.ask.conversations.ConfirmArgs -import com.amazon.alexa.ask.conversations.Inform -import com.amazon.alexa.ask.conversations.Invoke -import com.amazon.alexa.ask.conversations.MultiModalResponse -import com.amazon.alexa.ask.conversations.Notify -import com.amazon.alexa.ask.conversations.Request -import com.amazon.alexa.ask.conversations.RequestArguments -import com.amazon.alexa.ask.conversations.ensure -import com.amazon.alexa.ask.conversations.expect -import com.amazon.alexa.ask.conversations.response -import com.amazon.alexa.schema.Nothing -import com.amazon.alexa.schema.Thing -import com.weatherbot.apis.OrderTwoToppingPizza -import com.weatherbot.types.PAYLOAD_TYPE6 -import com.weatherbot.types.PAYLOAD_TYPE7 -import com.weatherbot.types.PAYLOAD_TYPE88 -import com.weatherbot.types.PAYLOAD_TYPE9 -import com.weatherbot.utteracesets.Yes -import com.weatherbot.utteracesets.specifyCrust -import com.weatherbot.utteracesets.specifySize -import com.weatherbot.utteracesets.specifyTwoToppings -import com.weatherbot.utteracesets.startTwoToppingPizzaOrder -import prompts.askForCrustPrompts -import prompts.askForSizePrompts -import prompts.askForToppingOnePrompt -import prompts.askForToppingTwoPrompt -import prompts.askForTwoToppingsPrompts -import prompts.confirmSizePrompt -import prompts.confirmTwoToppingOrderPromptcopy -import prompts.confirmTwoToppingsPrompt -import prompts.twoToppingOrderSuccessPrompt - -dialog Nothing orderTwoToppingPizza() { - sample { - expect( - Invoke, - startTwoToppingPizzaOrder - ) - ensure( - RequestArguments { - arguments = [ - OrderTwoToppingPizza.arguments.first_topping - ], - response = MultiModalResponse { - apla = askForToppingOnePrompt - } - } - ) - ensure( - RequestArguments { - arguments = [ - OrderTwoToppingPizza.arguments.second_topping - ], - response = MultiModalResponse { - apla = askForToppingTwoPrompt - } - } - ) - response( - MultiModalResponse { - apla = askForSizePrompts - }, - Request { - arguments = [ - OrderTwoToppingPizza.arguments.size - ] - }, - nothing, - nothing, - nothing - ) - specifySizeRequest = expect( - Inform, - specifySize - ) - response( - MultiModalResponse { - apla = confirmSizePrompt - }, - ConfirmArgs { - arguments = [ - OrderTwoToppingPizza.arguments.size - ] - }, - nothing, - PAYLOAD_TYPE6 { - size = specifySizeRequest.size - }, - nothing - ) - expect( - Affirm, - Yes - ) - response( - MultiModalResponse { - apla = askForCrustPrompts - }, - Request { - arguments = [ - OrderTwoToppingPizza.arguments.crust - ] - }, - nothing, - nothing, - nothing - ) - specifyCrustRequest = expect( - Inform, - specifyCrust - ) - response( - MultiModalResponse { - apla = askForTwoToppingsPrompts - }, - Request { - arguments = [ - OrderTwoToppingPizza.arguments.first_topping, - OrderTwoToppingPizza.arguments.second_topping - ] - }, - nothing, - nothing, - nothing - ) - specifyTwoToppingsRequest = expect( - Inform, - specifyTwoToppings - ) - response( - MultiModalResponse { - apla = confirmTwoToppingsPrompt - }, - ConfirmArgs { - arguments = [ - OrderTwoToppingPizza.arguments.first_topping, - OrderTwoToppingPizza.arguments.second_topping - ] - }, - nothing, - PAYLOAD_TYPE7 { - second_topping = specifyTwoToppingsRequest.second_topping, - first_topping = specifyTwoToppingsRequest.first_topping - }, - nothing - ) - expect( - Affirm, - Yes - ) - response( - MultiModalResponse { - apla = confirmTwoToppingOrderPromptcopy - }, - ConfirmAction { - actionName = OrderTwoToppingPizza - }, - nothing, - PAYLOAD_TYPE88 { - size = specifySizeRequest.size, - second_topping = specifyTwoToppingsRequest.second_topping, - first_topping = specifyTwoToppingsRequest.first_topping, - crust = specifyCrustRequest.crust - }, - nothing - ) - expect( - Affirm, - Yes - ) - stringLiteral1 = OrderTwoToppingPizza( - specifyTwoToppingsRequest.second_topping, - specifyTwoToppingsRequest.first_topping, - specifyCrustRequest.crust, - specifySizeRequest.size - ) - response( - MultiModalResponse { - apla = twoToppingOrderSuccessPrompt - }, - Notify { - success = true, - actionName = OrderTwoToppingPizza - }, - nothing, - PAYLOAD_TYPE9 { - speech = stringLiteral1 - }, - nothing - ) - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/conversations/soaDialog.acdl b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/conversations/soaDialog.acdl deleted file mode 100644 index d4c0acb5..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/conversations/soaDialog.acdl +++ /dev/null @@ -1,89 +0,0 @@ -namespace soaACDl - -import com.amazon.alexa.ask.conversations.Affirm -import com.amazon.alexa.ask.conversations.ConfirmArgs -import com.amazon.alexa.ask.conversations.Inform -import com.amazon.alexa.ask.conversations.Invoke -import com.amazon.alexa.ask.conversations.Notify -import com.amazon.alexa.ask.conversations.Request -import com.amazon.alexa.ask.conversations.expect -import com.amazon.alexa.ask.conversations.response -import com.amazon.alexa.schema.Nothing -import com.amazon.ask.types.builtins.AMAZON.Color -import com.weatherbot.apis.colorFruitName -import com.weatherbot.apis.fruitNameAPI -import com.weatherbot.types.result -import com.weatherbot.utteracesets.MultipleDialogEvent -import com.weatherbot.utteracesets.affirmMultipleColorEvent -import com.weatherbot.utteracesets.informColorMultipleEvent -import prompts.confirm_color_for_fruit_apla -import prompts.request_colorName_multiple_apla -import prompts.success_fruitPriceAPI_apla - -type payloadMultipleDialogEvent { - result result -} - -type payloadsOAConfirmArgs { - Color colorName -} - -dialog Nothing sOA() { - sample { - expect( - Invoke, - MultipleDialogEvent - ) - response( - request_colorName_multiple_apla, - Request { - arguments = [ - colorFruitName.arguments.colorName - ] - }, - nothing, - nothing, - nothing - ) - colorEvent = expect( - Inform, - informColorMultipleEvent - ) - response( - confirm_color_for_fruit_apla, - ConfirmArgs { - arguments = [ - colorFruitName.arguments.colorName - ] - }, - nothing, - payloadsOAConfirmArgs { - colorName = colorEvent.colorName - }, - nothing - ) - expect( - Affirm, - affirmMultipleColorEvent - ) - resultEvent = colorFruitName( - colorEvent.colorName, - nothing - ) - resultOne = fruitNameAPI( - nothing, - resultEvent.fruitName - ) - response( - success_fruitPriceAPI_apla, - Notify { - actionName = fruitNameAPI - }, - nothing, - payloadMultipleDialogEvent { - result = resultOne - }, - nothing - ) - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/conversations/typesMine.acdl b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/conversations/typesMine.acdl deleted file mode 100644 index 057115d1..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/conversations/typesMine.acdl +++ /dev/null @@ -1,248 +0,0 @@ -namespace com.weatherbot.types - -import com.amazon.alexa.schema.List -import com.amazon.ask.types.builtins.AMAZON.Color -import com.amazon.ask.types.builtins.AMAZON.DATE -import com.amazon.ask.types.builtins.AMAZON.Food -import com.amazon.ask.types.builtins.AMAZON.NUMBER -import slotTypes.Mix -import slotTypes.StringLiteral -import slotTypes.cheese -import slotTypes.city_name_one -import slotTypes.city_name_two -import slotTypes.complexNames -import slotTypes.crust -import slotTypes.customCity -import slotTypes.option -import slotTypes.orderStatus -import slotTypes.pickUpFrom -import slotTypes.signs -import slotTypes.size -import slotTypes.specialPizzaName -import slotTypes.toppings - -type customCityShell { - customCity cityName -} - -type signShell { - signs sign -} - -type dateValue { - DATE date -} - -type WeatherResult { - customCity cityName - NUMBER highTemp - NUMBER lowTemp - optional List itemsToUse -} - -type resultthree { - Food fruitName - Color colorName -} - -type result { - Food fruitName - NUMBER price -} - -type fruitNameShell { - Food fruitName -} - -type foodNameShell { - Food foodName -} - -type CityDateShell { - optional customCity cityName - optional DATE date -} - -type nameShell { - complexNames name -} - -type colorNameShell { - Color colorName -} - -type result_one { - Color colorName - complexNames name - signs sign -} - -type sourceShell { - city_name_one source -} - -type destinationShell { - city_name_two destination -} - -type pickUpFromShell { - pickUpFrom pickUpFrom -} - -type dropToShell { - city_name_one dropTo -} - -type bookedFlightResult { - city_name_two destination - city_name_one source - orderStatus orderStatus -} - -type bookCabResult { - pickUpFrom pickUpFrom - city_name_one dropTo - orderStatus orderStatus -} - -type ResponsePayload { - WeatherResult weatherResult -} - -type payloadConfirmActionConditionComplex { - optional complexNames name - optional signs sign -} - -type Response_Payload_one { - optional customCity cityName - optional DATE date -} - -type inform_menu_optionRequestType { - option option -} - -type specifySpecialNameRequestType { - specialPizzaName name -} - -type askMenuQuestionRequestType { - option option -} - -type specifySizeAndToppingsRequestType { - size size - List toppings -} - -type orderSpecificSizePizzaRequestType { - size size -} - -type specifyQtyRequestType { - NUMBER qty -} - -type customizePizzaReferenceSpecialRequestType { - specialPizzaName name -} - -type specifyTwoToppingsRequestType { - toppings second_topping - toppings first_topping -} - -type inquireAboutFeedingSizeRequestType { - size size -} - -type specifyToppingsRequestType { - List toppingsList -} - -type specifySizeRequestType { - size size -} - -type specifyCrustRequestType { - crust crust -} - -type specifyCheeseRequestType { - cheese cheese -} - -type pizza { - size size - List toppingsList - crust crust - cheese cheese -} - -type special { - pizza pizza - NUMBER cost - NUMBER qty - specialPizzaName name -} - -type PAYLOAD_TYPE0 { - size size - StringLiteral prompt -} - -type PAYLOAD_TYPE1 { - size size - List toppingsList - crust crust - cheese cheese -} - -type PAYLOAD_TYPE2 { - pizza pizza -} - -type PAYLOAD_TYPE3 { - size size - List toppingsList - crust crust - cheese cheese -} - -type PAYLOAD_TYPE4 { - pizza pizza -} - -type PAYLOAD_TYPE5 { - size size - StringLiteral prompt -} - -type PAYLOAD_TYPE6 { - size size -} - -type PAYLOAD_TYPE7 { - toppings second_topping - toppings first_topping -} - -type PAYLOAD_TYPE88 { - toppings second_topping - toppings first_topping - crust crust - optional size size -} - -type PAYLOAD_TYPE9 { - StringLiteral speech -} - -type PAYLOAD_TYPE10 { - StringLiteral optionResponse -} - -type PAYLOAD_TYPE11 { - StringLiteral optionResponse -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/conversations/utteracesetsMine.acdl b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/conversations/utteracesetsMine.acdl deleted file mode 100644 index 17a71d57..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/conversations/utteracesetsMine.acdl +++ /dev/null @@ -1,455 +0,0 @@ -namespace com.weatherbot.utteracesets - -import com.amazon.alexa.ask.conversations.utterances -import com.weatherbot.types.CityDateShell -import com.weatherbot.types.askMenuQuestionRequestType -import com.weatherbot.types.colorNameShell -import com.weatherbot.types.customCityShell -import com.weatherbot.types.customizePizzaReferenceSpecialRequestType -import com.weatherbot.types.dateValue -import com.weatherbot.types.destinationShell -import com.weatherbot.types.dropToShell -import com.weatherbot.types.foodNameShell -import com.weatherbot.types.fruitNameShell -import com.weatherbot.types.inform_menu_optionRequestType -import com.weatherbot.types.inquireAboutFeedingSizeRequestType -import com.weatherbot.types.nameShell -import com.weatherbot.types.orderSpecificSizePizzaRequestType -import com.weatherbot.types.pickUpFromShell -import com.weatherbot.types.signShell -import com.weatherbot.types.sourceShell -import com.weatherbot.types.specifyCheeseRequestType -import com.weatherbot.types.specifyCrustRequestType -import com.weatherbot.types.specifyQtyRequestType -import com.weatherbot.types.specifySizeAndToppingsRequestType -import com.weatherbot.types.specifySizeRequestType -import com.weatherbot.types.specifySpecialNameRequestType -import com.weatherbot.types.specifyToppingsRequestType -import com.weatherbot.types.specifyTwoToppingsRequestType - -values = [ - "what is the weather", - "what's the weather", - "tell me the weather" -] - -getWeatherEventNoArgs = utterances( - values -) - -getWeatherEventArgs = utterances( - [ - "tell me the weather in {cityName} {date}", - "how is the weather in {cityName} {date}" - ] -) - -getWeatherEvent = utterances( - [ - "What's the weather {date} in {cityName}", - "what is the weather {date}", - "How is the weather {date}", - "How is weather in {cityName} {date}", - "how is weather", - "can you please give me weather report for {date}" - ] -) - -informCityEvent = utterances( - [ - "{cityName}", - "city is {cityName}", - "city name is {cityName}" - ] -) - -informDateEvent = utterances( - [ - "date is {date}", - "for {date}", - "{date}" - ] -) - -affirmWeatherEvent = utterances( - [ - "yes", - "yeah" - ] -) - -delegateToSkill = utterances( - [ - "get me to paradise", - "take me to paradise" - ] -) - -getMarketPlaceEvent = utterances( - [ - "take me to marketplace", - "take me to market place", - "take me to market", - "take me to shopping", - "what is in marketplace", - "what is in market place", - "what is in market" - ] -) - -cookWithTwoIngredientsEvent = utterances( - [ - "let us cook", - "start cooking", - "cook with two ingredients", - "cook two ingredients", - "switch to coltrane", - "hit coltrane", - "make coltrane DM" - ] -) - -welcome = utterances( - [ - "get me car" - ] -) - -affirmMultipleColorEvent = utterances( - [ - "do it" - ] -) - -informMarketPlaceNameEvent = utterances( - [ - "{fruitName}", - "marketplace name is {fruitName}", - "marketplace is {fruitName}", - "market place is {fruitName}", - "market place name is {fruitName}" - ] -) - -informfruitNameEvent = utterances( - [ - "{fruitName}", - "fruit name is {fruitName}", - "fruit is {fruitName}" - ] -) - -MultipleDialogEvent = utterances( - [ - "i want to buy a fruit" - ] -) - -informColorMultipleEvent = utterances( - [ - "{colorName}", - "color is {colorName}", - "color {colorName}" - ] -) - -informFoodNameEvent = utterances( - [ - "{foodName}", - "food is {foodName}", - "let us make {foodName}" - ] -) - -affirmFruitAPIEvent = utterances( - [ - "uh huh", - "yup" - ] -) - -affirmCookAPIEvent = utterances( - [ - "ok", - "that is ok", - "ok for sure" - ] -) - -GiveMeTodaySpecialsEvent = utterances( - [ - "give me today specials", - "what is special today" - ] -) - -getFruitPriceEvent = utterances( - [ - "what is the price of the fruit", - "what is the price of fruit" - ] -) - -informsignEvent = utterances( - [ - "{sign}", - "sign is {sign}", - "sun sign is {sign}" - ] -) - -informComplexNameEvent = utterances( - [ - "{name}", - "name is {name}", - "i am {name}" - ] -) - -affirmFavColorEvent = utterances( - [ - "correct" - ] -) - -bookFlightEvent = utterances( - [ - "book a flight", - "book flight" - ] -) - -informFromBookFlight = utterances( - [ - "from {source}", - "travel from {source}", - "source is {source}" - ] -) - -informToBookFlight = utterances( - [ - "to {destination}", - "trave to {destination}", - "go to {destination}", - "destination to {destination}" - ] -) - -affirmCabAPIEvent = utterances( - [ - "sure do", - "sure please do", - "roger", - "indeed" - ] -) - -informPickUpFromBookCab = utterances( - [ - "{pickUpFrom}" - ] -) - -informdropToBookCab = utterances( - [ - "{dropTo}" - ] -) - -inform_menu_option = utterances( - [ - "{option}" - ] -) - -menuOptionsQuestion = utterances( - [ - "what options can I change?", - "what kinds of options are there?" - ] -) - -inquireAboutFeedingSizeNoArgs = utterances( - [ - "how many people does that feed", - "Is that enough for two adults and two kids" - ] -) - -specifySpecialName = utterances( - [ - "{name}" - ] -) - -askMenuQuestion = utterances( - [ - "what are your {option}", - "what {option} can i get", - "what types of {option} do you have", - "What kind of {option} do you have" - ] -) - -specifySizeAndToppings = utterances( - [ - "add a {size} {toppings} pizza to my order", - "order a {size} {toppings} pizza", - "I want a {size} {toppings} pizza" - ] -) - -orderSpecificSizePizza = utterances( - [ - "order a {size} pizza", - "I want a {size} pizza" - ] -) - -DummyInvokeOrderCustomizedPizzaReferenceSpecial = utterances( - [ - "dummy invoke needed when offer API is used in NotifySuccess request template + OfferAPI for OrderCustomizedPizzaReferenceSpecial" - ] -) - -startCustomizeFlow = utterances( - [ - "I want to customize a special" - ] -) - -confirmCustomizedSpecial = utterances( - [ - "sounds good", - "perfect", - "go ahead", - "sure", - "yeah", - "ok", - "yep" - ] -) - -specifyQty = utterances( - [ - "{qty} please", - "{qty}", - "give me {qty}", - "I will take {qty}", - "I want {qty}" - ] -) - -customizePizzaReferenceSpecial = utterances( - [ - "let's customize the {name}", - "I want to customize the {name}" - ] -) - -specifyTwoToppings = utterances( - [ - "no, make it {first_topping} and {second_topping}", - "no, {first_topping} and {second_topping}", - "actually make that {first_topping} and {second_topping}", - "change that to {first_topping} and {second_topping}", - "{first_topping} and {second_topping}", - "add {first_topping} and {second_topping}", - "I want {first_topping} and {second_topping}" - ] -) - -Yes = utterances( - [ - "Correct", - "Uh huh", - "Right", - "Yep", - "Yes" - ] -) - -inquireAboutFeedingSize = utterances( - [ - "is a {size} enough for four adults", - "how many people can a {size} feed", - "how many people can {size} pizza feed?" - ] -) - -tested = utterances( - [ - "launch skill" - ] -) - -startTwoToppingPizzaOrder = utterances( - [ - "order a two topping pizza", - "I want a two topping pizza" - ] -) - -specifyToppings = utterances( - [ - "{toppingsList}", - "I'd like {toppingsList}", - "give me {toppingsList}", - "we like {toppingsList}", - "The kids want {toppingsList}" - ] -) - -startPizzaOrder = utterances( - [ - "build my own pizza", - "I need my own custom pizza", - "Add one more order", - "I want another pizza", - "build another pizza", - "create another pizza", - "build a pizza", - "place an order for a pizza", - "add another pizza to my order", - "add another custom pizza to my order", - "create a custom pizza", - "start my pizza order", - "order me a custom pizza", - "order a pizza" - ] -) - -specifySize = utterances( - [ - "change it to {size}", - "make that a {size}", - "change that to a {size} pizza", - "{size}", - "I need a {size} pizza" - ] -) - -specifyCrust = utterances( - [ - "{crust}", - "I need {crust}" - ] -) - -specifyCheese = utterances( - [ - "{cheese}", - "I need {cheese}", - "Please add {cheese}" - ] -) - -confirmPizzaOrder = utterances( - [ - "yes", - "yup", - "go ahead", - "perfect" - ] -) diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/conversations/welcomeAPI.acdl b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/conversations/welcomeAPI.acdl deleted file mode 100644 index bf1baa2f..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/conversations/welcomeAPI.acdl +++ /dev/null @@ -1,34 +0,0 @@ -namespace welcomeAPi - -import com.amazon.alexa.ask.conversations.Invoke -import com.amazon.alexa.ask.conversations.Notify -import com.amazon.alexa.ask.conversations.expect -import com.amazon.alexa.ask.conversations.response -import com.amazon.alexa.schema.Nothing -import com.amazon.ask.types.builtins.AMAZON.NUMBER -import com.weatherbot.apis.welcomeApi -import com.weatherbot.utteracesets.welcome -import prompts.welcome_apla_custom - -type welcomeApiPayloads { - NUMBER result -} - -dialog Nothing complex() { - sample { - expect( - Invoke, - welcome - ) - resultDam = welcomeApi() - response( - welcome_apla_custom, - Notify { - actionName = welcomeApi - }, - nothing, - nothing, - nothing - ) - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/interactionModels/custom/en-US.json b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/interactionModels/custom/en-US.json deleted file mode 100644 index 6a03344f..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/interactionModels/custom/en-US.json +++ /dev/null @@ -1,564 +0,0 @@ -{ - "interactionModel": { - "languageModel": { - "invocationName": "model feedback test skill five", - "intents": [ - { - "name": "AMAZON.CancelIntent", - "samples": [] - }, - { - "name": "AMAZON.HelpIntent", - "samples": [] - }, - { - "name": "AMAZON.StopIntent", - "samples": [] - }, - { - "name": "NoDialog", - "samples": [ - "show me the wonders" - ] - }, - { - "name": "test", - "samples": [ - "nanum rowdy dhann" - ] - }, - { - "name": "SkillToColtrane", - "samples": [ - "switch to coltrane", - "hit coltrane", - "make coltrane DM" - ] - }, - { - "name": "AMAZON.NavigateHomeIntent", - "samples": [] - }, - { - "name": "AMAZON.FallbackIntent", - "samples": [] - } - ], - "types": [ - { - "values": [ - { - "name": { - "value": "satheesh" - } - }, - { - "name": { - "value": "raman" - } - } - ], - "name": "request_city_apl_displaya" - }, - { - "values": [ - { - "name": { - "value": "satheesh" - } - }, - { - "name": { - "value": "raman" - } - } - ], - "name": "complexNames" - }, - { - "values": [ - { - "name": { - "value": "scorpion" - } - }, - { - "name": { - "value": "aeries" - } - }, - { - "name": { - "value": "virgo" - } - }, - { - "name": { - "value": "cancer" - } - } - ], - "name": "signs" - }, - { - "values": [ - { - "name": { - "value": "almonds" - } - }, - { - "name": { - "value": "bread" - } - }, - { - "name": { - "value": "egg" - } - }, - { - "name": { - "value": "sauce" - } - }, - { - "name": { - "value": "jam" - } - }, - { - "name": { - "value": "cheese" - } - } - ], - "name": "Mix" - }, - { - "values": [ - { - "name": { - "value": "small" - } - }, - { - "name": { - "value": "medium" - } - }, - { - "name": { - "value": "large" - } - }, - { - "name": { - "value": "extra large" - } - } - ], - "name": "size" - }, - { - "values": [ - { - "name": { - "value": "guindy" - } - }, - { - "name": { - "value": "paris" - } - }, - { - "name": { - "value": "anna nagar" - } - }, - { - "name": { - "value": "ramapuram" - } - } - ], - "name": "pickUpFrom" - }, - { - "values": [ - { - "name": { - "value": "dummy value for api response literal property" - } - } - ], - "name": "StringLiteral" - }, - { - "values": [ - { - "name": { - "value": "deep dish" - } - }, - { - "name": { - "value": "regular" - } - }, - { - "name": { - "value": "hand made" - } - }, - { - "name": { - "value": "gluten free" - } - }, - { - "name": { - "value": "thin crust" - } - }, - { - "name": { - "value": "brooklyn style" - } - } - ], - "name": "crust" - }, - { - "values": [ - { - "name": { - "value": "none", - "synonyms": [ - "no cheese", - "dont add cheese", - "nope", - "no" - ] - } - }, - { - "name": { - "value": "light", - "synonyms": [ - "light cheese" - ] - } - }, - { - "name": { - "value": "normal", - "synonyms": [ - "Normal cheese" - ] - } - }, - { - "name": { - "value": "extra", - "synonyms": [ - "Extra cheese" - ] - } - }, - { - "name": { - "value": "double", - "synonyms": [ - "Double cheese" - ] - } - } - ], - "name": "cheese" - }, - { - "values": [ - { - "name": { - "value": "cheese", - "synonyms": [ - "cheeses" - ] - } - }, - { - "name": { - "value": "crust", - "synonyms": [ - "crusts" - ] - } - }, - { - "name": { - "value": "size", - "synonyms": [ - "sizes" - ] - } - } - ], - "name": "option" - }, - { - "values": [ - { - "name": { - "value": "two medium, two topping" - } - }, - { - "name": { - "value": "three cheese delight" - } - }, - { - "name": { - "value": "pepperoni party" - } - }, - { - "name": { - "value": "meat lovers" - } - }, - { - "name": { - "value": "veggie supreme" - } - }, - { - "name": { - "value": "kitchen sink" - } - } - ], - "name": "specialPizzaName" - }, - { - "values": [ - { - "name": { - "value": "onion", - "synonyms": [ - "onions" - ] - } - }, - { - "name": { - "value": "banana peppers", - "synonyms": [ - "banana pepper" - ] - } - }, - { - "name": { - "value": "olives", - "synonyms": [ - "black olives" - ] - } - }, - { - "name": { - "value": "mushrooms", - "synonyms": [ - "mushroom" - ] - } - }, - { - "name": { - "value": "pineapple" - } - }, - { - "name": { - "value": "spinach", - "synonyms": [ - "spinach" - ] - } - } - ], - "name": "toppings" - }, - { - "values": [ - { - "name": { - "value": "failure" - } - }, - { - "name": { - "value": "failed" - } - }, - { - "name": { - "value": "success" - } - } - ], - "name": "orderStatus" - }, - { - "values": [ - { - "name": { - "value": "san diego" - } - }, - { - "name": { - "value": "los angeles" - } - }, - { - "name": { - "value": "denver" - } - }, - { - "name": { - "value": "paris" - } - }, - { - "name": { - "value": "seattle" - } - }, - { - "name": { - "value": "portland" - } - }, - { - "name": { - "value": "ramapuram" - } - }, - { - "name": { - "value": "chennai" - } - } - ], - "name": "city_name_one" - }, - { - "values": [ - { - "name": { - "value": "denver" - } - }, - { - "name": { - "value": "sydney" - } - }, - { - "name": { - "value": "portland" - } - }, - { - "name": { - "value": "new york" - } - }, - { - "name": { - "value": "visakhapatnam" - } - }, - { - "name": { - "value": "bangalore" - } - }, - { - "name": { - "value": "mumbai" - } - }, - { - "name": { - "value": "seattle" - } - }, - { - "name": { - "value": "chennai" - } - } - ], - "name": "customCity" - }, - { - "values": [ - { - "name": { - "value": "denver" - } - }, - { - "name": { - "value": "sydney" - } - }, - { - "name": { - "value": "portland" - } - }, - { - "name": { - "value": "new york" - } - }, - { - "name": { - "value": "visakhapatnam" - } - }, - { - "name": { - "value": "bangalore" - } - }, - { - "name": { - "value": "mumbai" - } - }, - { - "name": { - "value": "seattle" - } - }, - { - "name": { - "value": "chennai" - } - } - ], - "name": "city_name_two" - } - ] - } - }, - "version": "4" -} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/display/confirm_city_apl_display/document.json b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/display/confirm_city_apl_display/document.json deleted file mode 100644 index 741e1a5f..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/display/confirm_city_apl_display/document.json +++ /dev/null @@ -1,358 +0,0 @@ -{ - "type": "APL", - "version": "1.1", - "settings": {}, - "theme": "dark", - "import": [ - { - "name": "alexa-layouts", - "version": "1.0.0" - } - ], - "resources": [ - { - "description": "Stock color for the light theme", - "colors": { - "colorTextPrimary": "#151920" - } - }, - { - "description": "Stock color for the dark theme", - "when": "${viewport.theme == 'dark'}", - "colors": { - "colorTextPrimary": "#f0f1ef" - } - }, - { - "description": "Standard font sizes", - "dimensions": { - "textSizeBody": 48, - "textSizePrimary": 27, - "textSizeSecondary": 23, - "textSizeDetails": 20, - "textSizeSecondaryHint": 25 - } - }, - { - "description": "Common spacing values", - "dimensions": { - "spacingThin": 6, - "spacingSmall": 12, - "spacingMedium": 24, - "spacingLarge": 48, - "spacingExtraLarge": 72 - } - }, - { - "description": "Common margins and padding", - "dimensions": { - "marginTop": 40, - "marginLeft": 60, - "marginRight": 60, - "marginBottom": 40 - } - } - ], - "styles": { - "textStyleBase": { - "description": "Base font description; set color", - "values": [ - { - "color": "@colorTextPrimary" - } - ] - }, - "textStyleBase0": { - "description": "Thin version of basic font", - "extend": "textStyleBase", - "values": { - "fontWeight": "100" - } - }, - "textStyleBase1": { - "description": "Light version of basic font", - "extend": "textStyleBase", - "values": { - "fontWeight": "300" - } - }, - "textStyleBase2": { - "description": "Regular version of basic font", - "extend": "textStyleBase", - "values": { - "fontWeight": "500" - } - }, - "mixinBody": { - "values": { - "fontSize": "@textSizeBody" - } - }, - "mixinPrimary": { - "values": { - "fontSize": "@textSizePrimary" - } - }, - "mixinDetails": { - "values": { - "fontSize": "@textSizeDetails" - } - }, - "mixinSecondary": { - "values": { - "fontSize": "@textSizeSecondary" - } - }, - "textStylePrimary": { - "extend": [ - "textStyleBase1", - "mixinPrimary" - ] - }, - "textStyleSecondary": { - "extend": [ - "textStyleBase0", - "mixinSecondary" - ] - }, - "textStyleBody": { - "extend": [ - "textStyleBase1", - "mixinBody" - ] - }, - "textStyleSecondaryHint": { - "values": { - "fontFamily": "Bookerly", - "fontStyle": "italic", - "fontSize": "@textSizeSecondaryHint", - "color": "@colorTextPrimary" - } - }, - "textStyleDetails": { - "extend": [ - "textStyleBase2", - "mixinDetails" - ] - } - }, - "onMount": [], - "graphics": {}, - "commands": {}, - "layouts": { - "ListTemplate1": { - "parameters": [ - "backgroundImage", - "title", - "logo", - "hintText", - "listData" - ], - "item": [ - { - "type": "Container", - "width": "100vw", - "height": "100vh", - "direction": "column", - "items": [ - { - "type": "Image", - "source": "${backgroundImage}", - "scale": "best-fill", - "width": "100vw", - "height": "100vh", - "position": "absolute" - }, - { - "type": "AlexaHeader", - "headerTitle": "${title}", - "headerAttributionImage": "${logo}" - }, - { - "type": "Sequence", - "grow": 1, - "height": "80vh", - "scrollDirection": "vertical", - "paddingLeft": "@marginLeft", - "paddingRight": "@marginRight", - "data": "${listData}", - "numbered": true, - "items": [ - { - "type": "VerticalListItem", - "image": "${data.image.sources[0].url}", - "primaryText": "${data.textContent.primaryText.text}", - "secondaryText": "${data.textContent.secondaryText.text}", - "tertiaryText": "${data.textContent.tertiaryText.text}" - } - ] - } - ] - } - ] - }, - "VerticalListItem": { - "parameters": [ - "primaryText", - "secondaryText", - "tertiaryText", - "image" - ], - "item": [ - { - "when": "${viewport.shape == 'round'}", - "type": "Container", - "direction": "row", - "height": 200, - "width": 500, - "alignItems": "center", - "items": [ - { - "type": "Text", - "text": "${ordinal}", - "paddingBottom": "20dp", - "color": "white", - "spacing": "5dp" - }, - { - "type": "Image", - "when": "${image}", - "source": "${image}", - "height": 150, - "width": 150, - "spacing": 15, - "scale": "best-fit", - "align": "top" - }, - { - "type": "Container", - "direction": "column", - "spacing": 25, - "items": [ - { - "type": "Text", - "text": "${primaryText}", - "style": "textStyleDetail", - "grow": 1, - "shrink": 1, - "fontWeight": "300", - "maxLines": 1 - }, - { - "type": "Text", - "text": "${secondaryText}", - "style": "textStyleCaption", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - }, - { - "type": "Text", - "text": "${tertiaryText}", - "style": "textStyleDetails", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - } - ] - } - ] - }, - { - "type": "Container", - "direction": "row", - "height": 125, - "width": 800, - "alignItems": "center", - "items": [ - { - "type": "Text", - "text": "${ordinal}", - "paddingBottom": "20dp", - "color": "white", - "spacing": "5dp" - }, - { - "type": "Image", - "when": "${image}", - "source": "${image}", - "height": 100, - "width": 100, - "align": "top", - "spacing": 50, - "scale": "best-fit" - }, - { - "type": "Container", - "spacing": 30, - "direction": "column", - "items": [ - { - "type": "Text", - "text": "${primaryText}", - "style": "textStyleBody", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - }, - { - "type": "Text", - "text": "${secondaryText}", - "style": "textStyleDetails", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - } - ] - }, - { - "type": "Text", - "text": "${tertiaryText}", - "style": "textStyleBody", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "textAlign": "right", - "maxLines": 1 - } - ] - } - ] - } - }, - "mainTemplate": { - "parameters": [ - "payload" - ], - "item": [ - { - "type": "Container", - "id": "BookCabSimpleDialogAPL", - "items": [ - { - "type": "TouchWrapper", - "onPress": { - "type": "SendEvent", - "arguments": [ - "delegateToColtraneOld" - ] - }, - "item": { - "type": "Text", - "id": "BookCabSimpleDialogAPL", - "paddingTop": "100", - "paddingLeft": "100", - "color": "green", - "size": 50, - "text": "which city ?" - } - } - ] - } - ] - } -} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/display/confirm_date_apl_display/document.json b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/display/confirm_date_apl_display/document.json deleted file mode 100644 index 9ff71e5c..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/display/confirm_date_apl_display/document.json +++ /dev/null @@ -1,358 +0,0 @@ -{ - "type": "APL", - "version": "1.1", - "settings": {}, - "theme": "dark", - "import": [ - { - "name": "alexa-layouts", - "version": "1.0.0" - } - ], - "resources": [ - { - "description": "Stock color for the light theme", - "colors": { - "colorTextPrimary": "#151920" - } - }, - { - "description": "Stock color for the dark theme", - "when": "${viewport.theme == 'dark'}", - "colors": { - "colorTextPrimary": "#f0f1ef" - } - }, - { - "description": "Standard font sizes", - "dimensions": { - "textSizeBody": 48, - "textSizePrimary": 27, - "textSizeSecondary": 23, - "textSizeDetails": 20, - "textSizeSecondaryHint": 25 - } - }, - { - "description": "Common spacing values", - "dimensions": { - "spacingThin": 6, - "spacingSmall": 12, - "spacingMedium": 24, - "spacingLarge": 48, - "spacingExtraLarge": 72 - } - }, - { - "description": "Common margins and padding", - "dimensions": { - "marginTop": 40, - "marginLeft": 60, - "marginRight": 60, - "marginBottom": 40 - } - } - ], - "styles": { - "textStyleBase": { - "description": "Base font description; set color", - "values": [ - { - "color": "@colorTextPrimary" - } - ] - }, - "textStyleBase0": { - "description": "Thin version of basic font", - "extend": "textStyleBase", - "values": { - "fontWeight": "100" - } - }, - "textStyleBase1": { - "description": "Light version of basic font", - "extend": "textStyleBase", - "values": { - "fontWeight": "300" - } - }, - "textStyleBase2": { - "description": "Regular version of basic font", - "extend": "textStyleBase", - "values": { - "fontWeight": "500" - } - }, - "mixinBody": { - "values": { - "fontSize": "@textSizeBody" - } - }, - "mixinPrimary": { - "values": { - "fontSize": "@textSizePrimary" - } - }, - "mixinDetails": { - "values": { - "fontSize": "@textSizeDetails" - } - }, - "mixinSecondary": { - "values": { - "fontSize": "@textSizeSecondary" - } - }, - "textStylePrimary": { - "extend": [ - "textStyleBase1", - "mixinPrimary" - ] - }, - "textStyleSecondary": { - "extend": [ - "textStyleBase0", - "mixinSecondary" - ] - }, - "textStyleBody": { - "extend": [ - "textStyleBase1", - "mixinBody" - ] - }, - "textStyleSecondaryHint": { - "values": { - "fontFamily": "Bookerly", - "fontStyle": "italic", - "fontSize": "@textSizeSecondaryHint", - "color": "@colorTextPrimary" - } - }, - "textStyleDetails": { - "extend": [ - "textStyleBase2", - "mixinDetails" - ] - } - }, - "onMount": [], - "graphics": {}, - "commands": {}, - "layouts": { - "ListTemplate1": { - "parameters": [ - "backgroundImage", - "title", - "logo", - "hintText", - "listData" - ], - "item": [ - { - "type": "Container", - "width": "100vw", - "height": "100vh", - "direction": "column", - "items": [ - { - "type": "Image", - "source": "${backgroundImage}", - "scale": "best-fill", - "width": "100vw", - "height": "100vh", - "position": "absolute" - }, - { - "type": "AlexaHeader", - "headerTitle": "${title}", - "headerAttributionImage": "${logo}" - }, - { - "type": "Sequence", - "grow": 1, - "height": "80vh", - "scrollDirection": "vertical", - "paddingLeft": "@marginLeft", - "paddingRight": "@marginRight", - "data": "${listData}", - "numbered": true, - "items": [ - { - "type": "VerticalListItem", - "image": "${data.image.sources[0].url}", - "primaryText": "${data.textContent.primaryText.text}", - "secondaryText": "${data.textContent.secondaryText.text}", - "tertiaryText": "${data.textContent.tertiaryText.text}" - } - ] - } - ] - } - ] - }, - "VerticalListItem": { - "parameters": [ - "primaryText", - "secondaryText", - "tertiaryText", - "image" - ], - "item": [ - { - "when": "${viewport.shape == 'round'}", - "type": "Container", - "direction": "row", - "height": 200, - "width": 500, - "alignItems": "center", - "items": [ - { - "type": "Text", - "text": "${ordinal}", - "paddingBottom": "20dp", - "color": "white", - "spacing": "5dp" - }, - { - "type": "Image", - "when": "${image}", - "source": "${image}", - "height": 150, - "width": 150, - "spacing": 15, - "scale": "best-fit", - "align": "top" - }, - { - "type": "Container", - "direction": "column", - "spacing": 25, - "items": [ - { - "type": "Text", - "text": "${primaryText}", - "style": "textStyleDetail", - "grow": 1, - "shrink": 1, - "fontWeight": "300", - "maxLines": 1 - }, - { - "type": "Text", - "text": "${secondaryText}", - "style": "textStyleCaption", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - }, - { - "type": "Text", - "text": "${tertiaryText}", - "style": "textStyleDetails", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - } - ] - } - ] - }, - { - "type": "Container", - "direction": "row", - "height": 125, - "width": 800, - "alignItems": "center", - "items": [ - { - "type": "Text", - "text": "${ordinal}", - "paddingBottom": "20dp", - "color": "white", - "spacing": "5dp" - }, - { - "type": "Image", - "when": "${image}", - "source": "${image}", - "height": 100, - "width": 100, - "align": "top", - "spacing": 50, - "scale": "best-fit" - }, - { - "type": "Container", - "spacing": 30, - "direction": "column", - "items": [ - { - "type": "Text", - "text": "${primaryText}", - "style": "textStyleBody", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - }, - { - "type": "Text", - "text": "${secondaryText}", - "style": "textStyleDetails", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - } - ] - }, - { - "type": "Text", - "text": "${tertiaryText}", - "style": "textStyleBody", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "textAlign": "right", - "maxLines": 1 - } - ] - } - ] - } - }, - "mainTemplate": { - "parameters": [ - "payload" - ], - "item": [ - { - "type": "Container", - "id": "BookCabSimpleDialogAPL", - "items": [ - { - "type": "TouchWrapper", - "onPress": { - "type": "SendEvent", - "arguments": [ - "delegateToColtraneOld" - ] - }, - "item": { - "type": "Text", - "id": "BookCabSimpleDialogAPL", - "paddingTop": "100", - "paddingLeft": "100", - "color": "green", - "size": 50, - "text": "which date ?" - } - } - ] - } - ] - } - } \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/display/confirm_weather_apla_display/document.json b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/display/confirm_weather_apla_display/document.json deleted file mode 100644 index 1974945a..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/display/confirm_weather_apla_display/document.json +++ /dev/null @@ -1,412 +0,0 @@ -{ - "type": "APL", - "version": "1.1", - "settings": {}, - "theme": "dark", - "import": [ - { - "name": "alexa-layouts", - "version": "1.0.0" - } - ], - "resources": [ - { - "description": "Stock color for the light theme", - "colors": { - "colorTextPrimary": "#151920" - } - }, - { - "description": "Stock color for the dark theme", - "when": "${viewport.theme == 'dark'}", - "colors": { - "colorTextPrimary": "#f0f1ef" - } - }, - { - "description": "Standard font sizes", - "dimensions": { - "textSizeBody": 48, - "textSizePrimary": 27, - "textSizeSecondary": 23, - "textSizeDetails": 20, - "textSizeSecondaryHint": 25 - } - }, - { - "description": "Common spacing values", - "dimensions": { - "spacingThin": 6, - "spacingSmall": 12, - "spacingMedium": 24, - "spacingLarge": 48, - "spacingExtraLarge": 72 - } - }, - { - "description": "Common margins and padding", - "dimensions": { - "marginTop": 40, - "marginLeft": 60, - "marginRight": 60, - "marginBottom": 40 - } - } - ], - "styles": { - "textStyleBase": { - "description": "Base font description; set color", - "values": [ - { - "color": "@colorTextPrimary" - } - ] - }, - "textStyleBase0": { - "description": "Thin version of basic font", - "extend": "textStyleBase", - "values": { - "fontWeight": "100" - } - }, - "textStyleBase1": { - "description": "Light version of basic font", - "extend": "textStyleBase", - "values": { - "fontWeight": "300" - } - }, - "textStyleBase2": { - "description": "Regular version of basic font", - "extend": "textStyleBase", - "values": { - "fontWeight": "500" - } - }, - "mixinBody": { - "values": { - "fontSize": "@textSizeBody" - } - }, - "mixinPrimary": { - "values": { - "fontSize": "@textSizePrimary" - } - }, - "mixinDetails": { - "values": { - "fontSize": "@textSizeDetails" - } - }, - "mixinSecondary": { - "values": { - "fontSize": "@textSizeSecondary" - } - }, - "textStylePrimary": { - "extend": [ - "textStyleBase1", - "mixinPrimary" - ] - }, - "textStyleSecondary": { - "extend": [ - "textStyleBase0", - "mixinSecondary" - ] - }, - "textStyleBody": { - "extend": [ - "textStyleBase1", - "mixinBody" - ] - }, - "textStyleSecondaryHint": { - "values": { - "fontFamily": "Bookerly", - "fontStyle": "italic", - "fontSize": "@textSizeSecondaryHint", - "color": "@colorTextPrimary" - } - }, - "textStyleDetails": { - "extend": [ - "textStyleBase2", - "mixinDetails" - ] - } - }, - "onMount": [], - "graphics": {}, - "commands": {}, - "layouts": { - "ListTemplate1": { - "parameters": [ - "backgroundImage", - "title", - "logo", - "hintText", - "listData" - ], - "item": [ - { - "type": "Container", - "width": "100vw", - "height": "100vh", - "direction": "column", - "items": [ - { - "type": "Image", - "source": "${backgroundImage}", - "scale": "best-fill", - "width": "100vw", - "height": "100vh", - "position": "absolute" - }, - { - "type": "AlexaHeader", - "headerTitle": "${title}", - "headerAttributionImage": "${logo}" - }, - { - "type": "Sequence", - "grow": 1, - "height": "80vh", - "scrollDirection": "vertical", - "paddingLeft": "@marginLeft", - "paddingRight": "@marginRight", - "data": "${listData}", - "numbered": true, - "items": [ - { - "type": "VerticalListItem", - "image": "${data.image.sources[0].url}", - "primaryText": "${data.textContent.primaryText.text}", - "secondaryText": "${data.textContent.secondaryText.text}", - "tertiaryText": "${data.textContent.tertiaryText.text}" - } - ] - } - ] - } - ] - }, - "VerticalListItem": { - "parameters": [ - "primaryText", - "secondaryText", - "tertiaryText", - "image" - ], - "item": [ - { - "when": "${viewport.shape == 'round'}", - "type": "Container", - "direction": "row", - "height": 200, - "width": 500, - "alignItems": "center", - "items": [ - { - "type": "Text", - "text": "${ordinal}", - "paddingBottom": "20dp", - "color": "white", - "spacing": "5dp" - }, - { - "type": "Image", - "when": "${image}", - "source": "${image}", - "height": 150, - "width": 150, - "spacing": 15, - "scale": "best-fit", - "align": "top" - }, - { - "type": "Container", - "direction": "column", - "spacing": 25, - "items": [ - { - "type": "Text", - "text": "${primaryText}", - "style": "textStyleDetail", - "grow": 1, - "shrink": 1, - "fontWeight": "300", - "maxLines": 1 - }, - { - "type": "Text", - "text": "${secondaryText}", - "style": "textStyleCaption", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - }, - { - "type": "Text", - "text": "${tertiaryText}", - "style": "textStyleDetails", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - } - ] - } - ] - }, - { - "type": "Container", - "direction": "row", - "height": 125, - "width": 800, - "alignItems": "center", - "items": [ - { - "type": "Text", - "text": "${ordinal}", - "paddingBottom": "20dp", - "color": "white", - "spacing": "5dp" - }, - { - "type": "Image", - "when": "${image}", - "source": "${image}", - "height": 100, - "width": 100, - "align": "top", - "spacing": 50, - "scale": "best-fit" - }, - { - "type": "Container", - "spacing": 30, - "direction": "column", - "items": [ - { - "type": "Text", - "text": "${primaryText}", - "style": "textStyleBody", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - }, - { - "type": "Text", - "text": "${secondaryText}", - "style": "textStyleDetails", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - } - ] - }, - { - "type": "Text", - "text": "${tertiaryText}", - "style": "textStyleBody", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "textAlign": "right", - "maxLines": 1 - } - ] - } - ] - } - }, - "mainTemplate": { - "parameters": [ - "payload" - ], - "item": [ - { - "type": "Container", - "id": "BookCabSimpleDialogAPL", - "items": [ - { - "type": "TouchWrapper", - "onPress": { - "type": "SendEvent", - "arguments": [ - "delegateToSkillNew" - ] - }, - "item": { - "type": "Text", - "id": "BookCabSimpleDialogAPL", - "paddingTop": "100", - "paddingLeft": "100", - "color": "green", - "size": 50, - "text": "delegateToSkillNew" - } - }, - { - "type": "TouchWrapper", - "onPress": { - "type": "SendEvent", - "arguments": [ - "delegateToSkillOld" - ] - }, - "item": { - "type": "Text", - "id": "BookCabSimpleDialogAPL", - "paddingTop": "100", - "paddingLeft": "100", - "color": "green", - "size": 50, - "text": "delegateToSkillOld" - } - }, - { - "type": "TouchWrapper", - "onPress": { - "type": "SendEvent", - "arguments": [ - "delegateToColtraneNew" - ] - }, - "item": { - "type": "Text", - "id": "BookCabSimpleDialogAPL", - "paddingTop": "100", - "paddingLeft": "100", - "color": "green", - "size": 50, - "text": "delegateToColtraneNew" - } - }, - { - "type": "TouchWrapper", - "onPress": { - "type": "SendEvent", - "arguments": [ - "delegateToColtraneOld" - ] - }, - "item": { - "type": "Text", - "id": "BookCabSimpleDialogAPL", - "paddingTop": "100", - "paddingLeft": "100", - "color": "green", - "size": 50, - "text": "delegateToColtraneOld" - } - } - ] - } - ] - } -} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/display/request_city_apl_display/document.json b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/display/request_city_apl_display/document.json deleted file mode 100644 index 741e1a5f..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/display/request_city_apl_display/document.json +++ /dev/null @@ -1,358 +0,0 @@ -{ - "type": "APL", - "version": "1.1", - "settings": {}, - "theme": "dark", - "import": [ - { - "name": "alexa-layouts", - "version": "1.0.0" - } - ], - "resources": [ - { - "description": "Stock color for the light theme", - "colors": { - "colorTextPrimary": "#151920" - } - }, - { - "description": "Stock color for the dark theme", - "when": "${viewport.theme == 'dark'}", - "colors": { - "colorTextPrimary": "#f0f1ef" - } - }, - { - "description": "Standard font sizes", - "dimensions": { - "textSizeBody": 48, - "textSizePrimary": 27, - "textSizeSecondary": 23, - "textSizeDetails": 20, - "textSizeSecondaryHint": 25 - } - }, - { - "description": "Common spacing values", - "dimensions": { - "spacingThin": 6, - "spacingSmall": 12, - "spacingMedium": 24, - "spacingLarge": 48, - "spacingExtraLarge": 72 - } - }, - { - "description": "Common margins and padding", - "dimensions": { - "marginTop": 40, - "marginLeft": 60, - "marginRight": 60, - "marginBottom": 40 - } - } - ], - "styles": { - "textStyleBase": { - "description": "Base font description; set color", - "values": [ - { - "color": "@colorTextPrimary" - } - ] - }, - "textStyleBase0": { - "description": "Thin version of basic font", - "extend": "textStyleBase", - "values": { - "fontWeight": "100" - } - }, - "textStyleBase1": { - "description": "Light version of basic font", - "extend": "textStyleBase", - "values": { - "fontWeight": "300" - } - }, - "textStyleBase2": { - "description": "Regular version of basic font", - "extend": "textStyleBase", - "values": { - "fontWeight": "500" - } - }, - "mixinBody": { - "values": { - "fontSize": "@textSizeBody" - } - }, - "mixinPrimary": { - "values": { - "fontSize": "@textSizePrimary" - } - }, - "mixinDetails": { - "values": { - "fontSize": "@textSizeDetails" - } - }, - "mixinSecondary": { - "values": { - "fontSize": "@textSizeSecondary" - } - }, - "textStylePrimary": { - "extend": [ - "textStyleBase1", - "mixinPrimary" - ] - }, - "textStyleSecondary": { - "extend": [ - "textStyleBase0", - "mixinSecondary" - ] - }, - "textStyleBody": { - "extend": [ - "textStyleBase1", - "mixinBody" - ] - }, - "textStyleSecondaryHint": { - "values": { - "fontFamily": "Bookerly", - "fontStyle": "italic", - "fontSize": "@textSizeSecondaryHint", - "color": "@colorTextPrimary" - } - }, - "textStyleDetails": { - "extend": [ - "textStyleBase2", - "mixinDetails" - ] - } - }, - "onMount": [], - "graphics": {}, - "commands": {}, - "layouts": { - "ListTemplate1": { - "parameters": [ - "backgroundImage", - "title", - "logo", - "hintText", - "listData" - ], - "item": [ - { - "type": "Container", - "width": "100vw", - "height": "100vh", - "direction": "column", - "items": [ - { - "type": "Image", - "source": "${backgroundImage}", - "scale": "best-fill", - "width": "100vw", - "height": "100vh", - "position": "absolute" - }, - { - "type": "AlexaHeader", - "headerTitle": "${title}", - "headerAttributionImage": "${logo}" - }, - { - "type": "Sequence", - "grow": 1, - "height": "80vh", - "scrollDirection": "vertical", - "paddingLeft": "@marginLeft", - "paddingRight": "@marginRight", - "data": "${listData}", - "numbered": true, - "items": [ - { - "type": "VerticalListItem", - "image": "${data.image.sources[0].url}", - "primaryText": "${data.textContent.primaryText.text}", - "secondaryText": "${data.textContent.secondaryText.text}", - "tertiaryText": "${data.textContent.tertiaryText.text}" - } - ] - } - ] - } - ] - }, - "VerticalListItem": { - "parameters": [ - "primaryText", - "secondaryText", - "tertiaryText", - "image" - ], - "item": [ - { - "when": "${viewport.shape == 'round'}", - "type": "Container", - "direction": "row", - "height": 200, - "width": 500, - "alignItems": "center", - "items": [ - { - "type": "Text", - "text": "${ordinal}", - "paddingBottom": "20dp", - "color": "white", - "spacing": "5dp" - }, - { - "type": "Image", - "when": "${image}", - "source": "${image}", - "height": 150, - "width": 150, - "spacing": 15, - "scale": "best-fit", - "align": "top" - }, - { - "type": "Container", - "direction": "column", - "spacing": 25, - "items": [ - { - "type": "Text", - "text": "${primaryText}", - "style": "textStyleDetail", - "grow": 1, - "shrink": 1, - "fontWeight": "300", - "maxLines": 1 - }, - { - "type": "Text", - "text": "${secondaryText}", - "style": "textStyleCaption", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - }, - { - "type": "Text", - "text": "${tertiaryText}", - "style": "textStyleDetails", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - } - ] - } - ] - }, - { - "type": "Container", - "direction": "row", - "height": 125, - "width": 800, - "alignItems": "center", - "items": [ - { - "type": "Text", - "text": "${ordinal}", - "paddingBottom": "20dp", - "color": "white", - "spacing": "5dp" - }, - { - "type": "Image", - "when": "${image}", - "source": "${image}", - "height": 100, - "width": 100, - "align": "top", - "spacing": 50, - "scale": "best-fit" - }, - { - "type": "Container", - "spacing": 30, - "direction": "column", - "items": [ - { - "type": "Text", - "text": "${primaryText}", - "style": "textStyleBody", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - }, - { - "type": "Text", - "text": "${secondaryText}", - "style": "textStyleDetails", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - } - ] - }, - { - "type": "Text", - "text": "${tertiaryText}", - "style": "textStyleBody", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "textAlign": "right", - "maxLines": 1 - } - ] - } - ] - } - }, - "mainTemplate": { - "parameters": [ - "payload" - ], - "item": [ - { - "type": "Container", - "id": "BookCabSimpleDialogAPL", - "items": [ - { - "type": "TouchWrapper", - "onPress": { - "type": "SendEvent", - "arguments": [ - "delegateToColtraneOld" - ] - }, - "item": { - "type": "Text", - "id": "BookCabSimpleDialogAPL", - "paddingTop": "100", - "paddingLeft": "100", - "color": "green", - "size": 50, - "text": "which city ?" - } - } - ] - } - ] - } -} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/display/request_date_apl_display/document.json b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/display/request_date_apl_display/document.json deleted file mode 100644 index 9ff71e5c..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/display/request_date_apl_display/document.json +++ /dev/null @@ -1,358 +0,0 @@ -{ - "type": "APL", - "version": "1.1", - "settings": {}, - "theme": "dark", - "import": [ - { - "name": "alexa-layouts", - "version": "1.0.0" - } - ], - "resources": [ - { - "description": "Stock color for the light theme", - "colors": { - "colorTextPrimary": "#151920" - } - }, - { - "description": "Stock color for the dark theme", - "when": "${viewport.theme == 'dark'}", - "colors": { - "colorTextPrimary": "#f0f1ef" - } - }, - { - "description": "Standard font sizes", - "dimensions": { - "textSizeBody": 48, - "textSizePrimary": 27, - "textSizeSecondary": 23, - "textSizeDetails": 20, - "textSizeSecondaryHint": 25 - } - }, - { - "description": "Common spacing values", - "dimensions": { - "spacingThin": 6, - "spacingSmall": 12, - "spacingMedium": 24, - "spacingLarge": 48, - "spacingExtraLarge": 72 - } - }, - { - "description": "Common margins and padding", - "dimensions": { - "marginTop": 40, - "marginLeft": 60, - "marginRight": 60, - "marginBottom": 40 - } - } - ], - "styles": { - "textStyleBase": { - "description": "Base font description; set color", - "values": [ - { - "color": "@colorTextPrimary" - } - ] - }, - "textStyleBase0": { - "description": "Thin version of basic font", - "extend": "textStyleBase", - "values": { - "fontWeight": "100" - } - }, - "textStyleBase1": { - "description": "Light version of basic font", - "extend": "textStyleBase", - "values": { - "fontWeight": "300" - } - }, - "textStyleBase2": { - "description": "Regular version of basic font", - "extend": "textStyleBase", - "values": { - "fontWeight": "500" - } - }, - "mixinBody": { - "values": { - "fontSize": "@textSizeBody" - } - }, - "mixinPrimary": { - "values": { - "fontSize": "@textSizePrimary" - } - }, - "mixinDetails": { - "values": { - "fontSize": "@textSizeDetails" - } - }, - "mixinSecondary": { - "values": { - "fontSize": "@textSizeSecondary" - } - }, - "textStylePrimary": { - "extend": [ - "textStyleBase1", - "mixinPrimary" - ] - }, - "textStyleSecondary": { - "extend": [ - "textStyleBase0", - "mixinSecondary" - ] - }, - "textStyleBody": { - "extend": [ - "textStyleBase1", - "mixinBody" - ] - }, - "textStyleSecondaryHint": { - "values": { - "fontFamily": "Bookerly", - "fontStyle": "italic", - "fontSize": "@textSizeSecondaryHint", - "color": "@colorTextPrimary" - } - }, - "textStyleDetails": { - "extend": [ - "textStyleBase2", - "mixinDetails" - ] - } - }, - "onMount": [], - "graphics": {}, - "commands": {}, - "layouts": { - "ListTemplate1": { - "parameters": [ - "backgroundImage", - "title", - "logo", - "hintText", - "listData" - ], - "item": [ - { - "type": "Container", - "width": "100vw", - "height": "100vh", - "direction": "column", - "items": [ - { - "type": "Image", - "source": "${backgroundImage}", - "scale": "best-fill", - "width": "100vw", - "height": "100vh", - "position": "absolute" - }, - { - "type": "AlexaHeader", - "headerTitle": "${title}", - "headerAttributionImage": "${logo}" - }, - { - "type": "Sequence", - "grow": 1, - "height": "80vh", - "scrollDirection": "vertical", - "paddingLeft": "@marginLeft", - "paddingRight": "@marginRight", - "data": "${listData}", - "numbered": true, - "items": [ - { - "type": "VerticalListItem", - "image": "${data.image.sources[0].url}", - "primaryText": "${data.textContent.primaryText.text}", - "secondaryText": "${data.textContent.secondaryText.text}", - "tertiaryText": "${data.textContent.tertiaryText.text}" - } - ] - } - ] - } - ] - }, - "VerticalListItem": { - "parameters": [ - "primaryText", - "secondaryText", - "tertiaryText", - "image" - ], - "item": [ - { - "when": "${viewport.shape == 'round'}", - "type": "Container", - "direction": "row", - "height": 200, - "width": 500, - "alignItems": "center", - "items": [ - { - "type": "Text", - "text": "${ordinal}", - "paddingBottom": "20dp", - "color": "white", - "spacing": "5dp" - }, - { - "type": "Image", - "when": "${image}", - "source": "${image}", - "height": 150, - "width": 150, - "spacing": 15, - "scale": "best-fit", - "align": "top" - }, - { - "type": "Container", - "direction": "column", - "spacing": 25, - "items": [ - { - "type": "Text", - "text": "${primaryText}", - "style": "textStyleDetail", - "grow": 1, - "shrink": 1, - "fontWeight": "300", - "maxLines": 1 - }, - { - "type": "Text", - "text": "${secondaryText}", - "style": "textStyleCaption", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - }, - { - "type": "Text", - "text": "${tertiaryText}", - "style": "textStyleDetails", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - } - ] - } - ] - }, - { - "type": "Container", - "direction": "row", - "height": 125, - "width": 800, - "alignItems": "center", - "items": [ - { - "type": "Text", - "text": "${ordinal}", - "paddingBottom": "20dp", - "color": "white", - "spacing": "5dp" - }, - { - "type": "Image", - "when": "${image}", - "source": "${image}", - "height": 100, - "width": 100, - "align": "top", - "spacing": 50, - "scale": "best-fit" - }, - { - "type": "Container", - "spacing": 30, - "direction": "column", - "items": [ - { - "type": "Text", - "text": "${primaryText}", - "style": "textStyleBody", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - }, - { - "type": "Text", - "text": "${secondaryText}", - "style": "textStyleDetails", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - } - ] - }, - { - "type": "Text", - "text": "${tertiaryText}", - "style": "textStyleBody", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "textAlign": "right", - "maxLines": 1 - } - ] - } - ] - } - }, - "mainTemplate": { - "parameters": [ - "payload" - ], - "item": [ - { - "type": "Container", - "id": "BookCabSimpleDialogAPL", - "items": [ - { - "type": "TouchWrapper", - "onPress": { - "type": "SendEvent", - "arguments": [ - "delegateToColtraneOld" - ] - }, - "item": { - "type": "Text", - "id": "BookCabSimpleDialogAPL", - "paddingTop": "100", - "paddingLeft": "100", - "color": "green", - "size": 50, - "text": "which date ?" - } - } - ] - } - ] - } - } \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/display/weather_success_apl_display/document.json b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/display/weather_success_apl_display/document.json deleted file mode 100644 index 1974945a..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/display/weather_success_apl_display/document.json +++ /dev/null @@ -1,412 +0,0 @@ -{ - "type": "APL", - "version": "1.1", - "settings": {}, - "theme": "dark", - "import": [ - { - "name": "alexa-layouts", - "version": "1.0.0" - } - ], - "resources": [ - { - "description": "Stock color for the light theme", - "colors": { - "colorTextPrimary": "#151920" - } - }, - { - "description": "Stock color for the dark theme", - "when": "${viewport.theme == 'dark'}", - "colors": { - "colorTextPrimary": "#f0f1ef" - } - }, - { - "description": "Standard font sizes", - "dimensions": { - "textSizeBody": 48, - "textSizePrimary": 27, - "textSizeSecondary": 23, - "textSizeDetails": 20, - "textSizeSecondaryHint": 25 - } - }, - { - "description": "Common spacing values", - "dimensions": { - "spacingThin": 6, - "spacingSmall": 12, - "spacingMedium": 24, - "spacingLarge": 48, - "spacingExtraLarge": 72 - } - }, - { - "description": "Common margins and padding", - "dimensions": { - "marginTop": 40, - "marginLeft": 60, - "marginRight": 60, - "marginBottom": 40 - } - } - ], - "styles": { - "textStyleBase": { - "description": "Base font description; set color", - "values": [ - { - "color": "@colorTextPrimary" - } - ] - }, - "textStyleBase0": { - "description": "Thin version of basic font", - "extend": "textStyleBase", - "values": { - "fontWeight": "100" - } - }, - "textStyleBase1": { - "description": "Light version of basic font", - "extend": "textStyleBase", - "values": { - "fontWeight": "300" - } - }, - "textStyleBase2": { - "description": "Regular version of basic font", - "extend": "textStyleBase", - "values": { - "fontWeight": "500" - } - }, - "mixinBody": { - "values": { - "fontSize": "@textSizeBody" - } - }, - "mixinPrimary": { - "values": { - "fontSize": "@textSizePrimary" - } - }, - "mixinDetails": { - "values": { - "fontSize": "@textSizeDetails" - } - }, - "mixinSecondary": { - "values": { - "fontSize": "@textSizeSecondary" - } - }, - "textStylePrimary": { - "extend": [ - "textStyleBase1", - "mixinPrimary" - ] - }, - "textStyleSecondary": { - "extend": [ - "textStyleBase0", - "mixinSecondary" - ] - }, - "textStyleBody": { - "extend": [ - "textStyleBase1", - "mixinBody" - ] - }, - "textStyleSecondaryHint": { - "values": { - "fontFamily": "Bookerly", - "fontStyle": "italic", - "fontSize": "@textSizeSecondaryHint", - "color": "@colorTextPrimary" - } - }, - "textStyleDetails": { - "extend": [ - "textStyleBase2", - "mixinDetails" - ] - } - }, - "onMount": [], - "graphics": {}, - "commands": {}, - "layouts": { - "ListTemplate1": { - "parameters": [ - "backgroundImage", - "title", - "logo", - "hintText", - "listData" - ], - "item": [ - { - "type": "Container", - "width": "100vw", - "height": "100vh", - "direction": "column", - "items": [ - { - "type": "Image", - "source": "${backgroundImage}", - "scale": "best-fill", - "width": "100vw", - "height": "100vh", - "position": "absolute" - }, - { - "type": "AlexaHeader", - "headerTitle": "${title}", - "headerAttributionImage": "${logo}" - }, - { - "type": "Sequence", - "grow": 1, - "height": "80vh", - "scrollDirection": "vertical", - "paddingLeft": "@marginLeft", - "paddingRight": "@marginRight", - "data": "${listData}", - "numbered": true, - "items": [ - { - "type": "VerticalListItem", - "image": "${data.image.sources[0].url}", - "primaryText": "${data.textContent.primaryText.text}", - "secondaryText": "${data.textContent.secondaryText.text}", - "tertiaryText": "${data.textContent.tertiaryText.text}" - } - ] - } - ] - } - ] - }, - "VerticalListItem": { - "parameters": [ - "primaryText", - "secondaryText", - "tertiaryText", - "image" - ], - "item": [ - { - "when": "${viewport.shape == 'round'}", - "type": "Container", - "direction": "row", - "height": 200, - "width": 500, - "alignItems": "center", - "items": [ - { - "type": "Text", - "text": "${ordinal}", - "paddingBottom": "20dp", - "color": "white", - "spacing": "5dp" - }, - { - "type": "Image", - "when": "${image}", - "source": "${image}", - "height": 150, - "width": 150, - "spacing": 15, - "scale": "best-fit", - "align": "top" - }, - { - "type": "Container", - "direction": "column", - "spacing": 25, - "items": [ - { - "type": "Text", - "text": "${primaryText}", - "style": "textStyleDetail", - "grow": 1, - "shrink": 1, - "fontWeight": "300", - "maxLines": 1 - }, - { - "type": "Text", - "text": "${secondaryText}", - "style": "textStyleCaption", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - }, - { - "type": "Text", - "text": "${tertiaryText}", - "style": "textStyleDetails", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - } - ] - } - ] - }, - { - "type": "Container", - "direction": "row", - "height": 125, - "width": 800, - "alignItems": "center", - "items": [ - { - "type": "Text", - "text": "${ordinal}", - "paddingBottom": "20dp", - "color": "white", - "spacing": "5dp" - }, - { - "type": "Image", - "when": "${image}", - "source": "${image}", - "height": 100, - "width": 100, - "align": "top", - "spacing": 50, - "scale": "best-fit" - }, - { - "type": "Container", - "spacing": 30, - "direction": "column", - "items": [ - { - "type": "Text", - "text": "${primaryText}", - "style": "textStyleBody", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - }, - { - "type": "Text", - "text": "${secondaryText}", - "style": "textStyleDetails", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - } - ] - }, - { - "type": "Text", - "text": "${tertiaryText}", - "style": "textStyleBody", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "textAlign": "right", - "maxLines": 1 - } - ] - } - ] - } - }, - "mainTemplate": { - "parameters": [ - "payload" - ], - "item": [ - { - "type": "Container", - "id": "BookCabSimpleDialogAPL", - "items": [ - { - "type": "TouchWrapper", - "onPress": { - "type": "SendEvent", - "arguments": [ - "delegateToSkillNew" - ] - }, - "item": { - "type": "Text", - "id": "BookCabSimpleDialogAPL", - "paddingTop": "100", - "paddingLeft": "100", - "color": "green", - "size": 50, - "text": "delegateToSkillNew" - } - }, - { - "type": "TouchWrapper", - "onPress": { - "type": "SendEvent", - "arguments": [ - "delegateToSkillOld" - ] - }, - "item": { - "type": "Text", - "id": "BookCabSimpleDialogAPL", - "paddingTop": "100", - "paddingLeft": "100", - "color": "green", - "size": 50, - "text": "delegateToSkillOld" - } - }, - { - "type": "TouchWrapper", - "onPress": { - "type": "SendEvent", - "arguments": [ - "delegateToColtraneNew" - ] - }, - "item": { - "type": "Text", - "id": "BookCabSimpleDialogAPL", - "paddingTop": "100", - "paddingLeft": "100", - "color": "green", - "size": 50, - "text": "delegateToColtraneNew" - } - }, - { - "type": "TouchWrapper", - "onPress": { - "type": "SendEvent", - "arguments": [ - "delegateToColtraneOld" - ] - }, - "item": { - "type": "Text", - "id": "BookCabSimpleDialogAPL", - "paddingTop": "100", - "paddingLeft": "100", - "color": "green", - "size": 50, - "text": "delegateToColtraneOld" - } - } - ] - } - ] - } -} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/AlexaConversationsBye/document.json b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/AlexaConversationsBye/document.json deleted file mode 100644 index bde5ee56..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/AlexaConversationsBye/document.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": [ - "payload" - ], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "Bye.", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/AlexaConversationsNotifyFailure/document.json b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/AlexaConversationsNotifyFailure/document.json deleted file mode 100644 index c31fe279..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/AlexaConversationsNotifyFailure/document.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": [ - "payload" - ], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "Sorry, there was an error in the request.", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/AlexaConversationsOutOfDomain/document.json b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/AlexaConversationsOutOfDomain/document.json deleted file mode 100644 index 3796d4d5..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/AlexaConversationsOutOfDomain/document.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": [ - "payload" - ], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "Sorry, I don't understand.", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/AlexaConversationsProvideHelp/document.json b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/AlexaConversationsProvideHelp/document.json deleted file mode 100644 index 13b27c11..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/AlexaConversationsProvideHelp/document.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": [ - "payload" - ], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "I can give you the weather report. Just say \"what's the weather\" to start.", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/AlexaConversationsRequestMore/document.json b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/AlexaConversationsRequestMore/document.json deleted file mode 100644 index fb3e56ae..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/AlexaConversationsRequestMore/document.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": [ - "payload" - ], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "What do you want to do.", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/AlexaConversationsThankYou/document.json b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/AlexaConversationsThankYou/document.json deleted file mode 100644 index 2112f02e..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/AlexaConversationsThankYou/document.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": [ - "payload" - ], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "Thank you.", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/AlexaConversationsWelcome/document.json b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/AlexaConversationsWelcome/document.json deleted file mode 100644 index 0c8e2588..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/AlexaConversationsWelcome/document.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": [ - "payload" - ], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "Welcome to the weatherOct16", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/AlexaConversationsYouAreWelcome/document.json b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/AlexaConversationsYouAreWelcome/document.json deleted file mode 100644 index 7ade07ba..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/AlexaConversationsYouAreWelcome/document.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": [ - "payload" - ], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "You are welcome.", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/SuccessGiveMeTodaySpecialsEvent_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/SuccessGiveMeTodaySpecialsEvent_apla/document.json deleted file mode 100644 index f0b3055d..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/SuccessGiveMeTodaySpecialsEvent_apla/document.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "type": "APLA", - "version": "0.8", - "mainTemplate": { - "parameters": [ - "payload" - ], - "item": { - "type": "Selector", - "strategy": "randomItem", - "description": "Change 'type' above to try different Selector Component Types like Sequencer", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "today's special are ${payload.result.length} items , all items are ${payload.result}, first item is ${payload.result[0]}", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/SuccessGiveMeTodaySpecialsEvent_apla_failure/document.json b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/SuccessGiveMeTodaySpecialsEvent_apla_failure/document.json deleted file mode 100644 index 50468557..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/SuccessGiveMeTodaySpecialsEvent_apla_failure/document.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "type": "APLA", - "version": "0.8", - "mainTemplate": { - "parameters": [ - "payload" - ], - "item": { - "type": "Selector", - "strategy": "randomItem", - "description": "Change 'type' above to try different Selector Component Types like Sequencer", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "Failure : today's special are ${payload.result.length} items , all items are ${payload.result}, first item is ${payload.result[0]}", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/askForCrustPrompts/datasources/default.json b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/askForCrustPrompts/datasources/default.json deleted file mode 100644 index 9e26dfee..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/askForCrustPrompts/datasources/default.json +++ /dev/null @@ -1 +0,0 @@ -{} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/askForCrustPrompts/document.json b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/askForCrustPrompts/document.json deleted file mode 100644 index 3aec75b6..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/askForCrustPrompts/document.json +++ /dev/null @@ -1 +0,0 @@ -{"type":"APLA","version":"0.8","mainTemplate":{"parameters":["payload"],"item":{"type":"Selector","strategy":"randomItem","description":"Change 'type' above to try different Selector Component Types like Sequencer","items":[{"type":"Speech","contentType":"text","content":"On what kind of crust, we have thin, deep dish, regular and brooklyn style","description":"Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that"},{"type":"Speech","contentType":"text","content":"Ok, we have thin, deep dish, regular and brooklyn style, what would you like","description":"Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that"}]}}} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/askForSizePrompts/datasources/default.json b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/askForSizePrompts/datasources/default.json deleted file mode 100644 index 9e26dfee..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/askForSizePrompts/datasources/default.json +++ /dev/null @@ -1 +0,0 @@ -{} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/askForSizePrompts/document.json b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/askForSizePrompts/document.json deleted file mode 100644 index 87a88ee9..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/askForSizePrompts/document.json +++ /dev/null @@ -1 +0,0 @@ -{"type":"APLA","version":"0.8","mainTemplate":{"parameters":["payload"],"item":{"type":"Selector","strategy":"randomItem","description":"Change 'type' above to try different Selector Component Types like Sequencer","items":[{"type":"Speech","contentType":"text","content":"What size? We have small, medium, large and extra large","description":"Prompt for size"},{"type":"Speech","contentType":"text","content":"Ok. We have small to extra large pizzas. What size would you like? ","description":"Prompt for size"}]}}} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/askForToppingOnePrompt/datasources/default.json b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/askForToppingOnePrompt/datasources/default.json deleted file mode 100644 index 9e26dfee..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/askForToppingOnePrompt/datasources/default.json +++ /dev/null @@ -1 +0,0 @@ -{} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/askForToppingOnePrompt/document.json b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/askForToppingOnePrompt/document.json deleted file mode 100644 index 36ec7f0c..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/askForToppingOnePrompt/document.json +++ /dev/null @@ -1 +0,0 @@ -{"type":"APLA","version":"0.8","mainTemplate":{"parameters":["payload"],"item":{"type":"Selector","strategy":"randomItem","description":"Change 'type' above to try different Selector Component Types like Sequencer","items":[{"type":"Speech","contentType":"text","content":"What would you like for the 1st topping?","description":"Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that"}]}}} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/askForToppingTwoPrompt/datasources/default.json b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/askForToppingTwoPrompt/datasources/default.json deleted file mode 100644 index 9e26dfee..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/askForToppingTwoPrompt/datasources/default.json +++ /dev/null @@ -1 +0,0 @@ -{} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/askForToppingTwoPrompt/document.json b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/askForToppingTwoPrompt/document.json deleted file mode 100644 index e12851f4..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/askForToppingTwoPrompt/document.json +++ /dev/null @@ -1 +0,0 @@ -{"type":"APLA","version":"0.8","mainTemplate":{"parameters":["payload"],"item":{"type":"Selector","strategy":"randomItem","description":"Change 'type' above to try different Selector Component Types like Sequencer","items":[{"type":"Speech","contentType":"text","content":"What about the 2nd topping?","description":"Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that"}]}}} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/askForToppingsPrompts/datasources/default.json b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/askForToppingsPrompts/datasources/default.json deleted file mode 100644 index 9e26dfee..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/askForToppingsPrompts/datasources/default.json +++ /dev/null @@ -1 +0,0 @@ -{} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/askForToppingsPrompts/document.json b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/askForToppingsPrompts/document.json deleted file mode 100644 index ae44b6ef..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/askForToppingsPrompts/document.json +++ /dev/null @@ -1 +0,0 @@ -{"type":"APLA","version":"0.8","mainTemplate":{"parameters":["payload"],"item":{"type":"Selector","strategy":"randomItem","description":"Change 'type' above to try different Selector Component Types like Sequencer","items":[{"type":"Speech","contentType":"text","content":"What would you like on your pizza?","description":"Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that"}]}}} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/askForTwoToppingsPrompts/datasources/default.json b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/askForTwoToppingsPrompts/datasources/default.json deleted file mode 100644 index 9e26dfee..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/askForTwoToppingsPrompts/datasources/default.json +++ /dev/null @@ -1 +0,0 @@ -{} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/askForTwoToppingsPrompts/document.json b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/askForTwoToppingsPrompts/document.json deleted file mode 100644 index 24be5926..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/askForTwoToppingsPrompts/document.json +++ /dev/null @@ -1 +0,0 @@ -{"type":"APLA","version":"0.8","mainTemplate":{"parameters":["payload"],"item":{"type":"Selector","strategy":"randomItem","description":"Change 'type' above to try different Selector Component Types like Sequencer","items":[{"type":"Speech","contentType":"text","content":"Ok, what two toppings would you like?","description":"Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that"}]}}} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/askForTwoToppingsPrompts_copy/datasources/default.json b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/askForTwoToppingsPrompts_copy/datasources/default.json deleted file mode 100644 index 9e26dfee..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/askForTwoToppingsPrompts_copy/datasources/default.json +++ /dev/null @@ -1 +0,0 @@ -{} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/askForTwoToppingsPrompts_copy/document.json b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/askForTwoToppingsPrompts_copy/document.json deleted file mode 100644 index 24be5926..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/askForTwoToppingsPrompts_copy/document.json +++ /dev/null @@ -1 +0,0 @@ -{"type":"APLA","version":"0.8","mainTemplate":{"parameters":["payload"],"item":{"type":"Selector","strategy":"randomItem","description":"Change 'type' above to try different Selector Component Types like Sequencer","items":[{"type":"Speech","contentType":"text","content":"Ok, what two toppings would you like?","description":"Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that"}]}}} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/confirmAction_complexNames_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/confirmAction_complexNames_apla/document.json deleted file mode 100644 index f9962e57..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/confirmAction_complexNames_apla/document.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": [ - "payload" - ], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [{ - "when": "${payload.sign!= null}", - "type": "Speech", - "contentType": "text", - "content": "confirm Action your cool name ${payload.name} and ${payload.sign}? ", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - }, - { - "when": "${payload.sign == null}", - "type": "Speech", - "contentType": "text", - "content": "confirm Action your cool name ${payload.name}? ", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/confirmArgs_complexNames_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/confirmArgs_complexNames_apla/document.json deleted file mode 100644 index cfe959ca..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/confirmArgs_complexNames_apla/document.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": [ - "payload" - ], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "confirm args your cool name ${payload.name} and ${payload.sign}? ", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/confirmSizePrompt/datasources/default.json b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/confirmSizePrompt/datasources/default.json deleted file mode 100644 index 4bb69fc3..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/confirmSizePrompt/datasources/default.json +++ /dev/null @@ -1 +0,0 @@ -{"size":"extra large"} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/confirmSizePrompt/document.json b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/confirmSizePrompt/document.json deleted file mode 100644 index 052151e9..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/confirmSizePrompt/document.json +++ /dev/null @@ -1 +0,0 @@ -{"type":"APLA","version":"0.8","mainTemplate":{"parameters":["payload"],"item":{"type":"Sequencer","description":"Change 'type' above to try different Selector Component Types like Sequencer","items":[{"type":"Speech","contentType":"text","content":"You wanted "},{"type":"Speech","when":"${payload.size == 'small' || payload.size == 'large' || payload.size == 'medium'}","content":"a ${payload.size} pizza, is that correct?"},{"type":"Speech","when":"${payload.size == 'extra large'}","content":"an ${payload.size} pizza, is that correct?"}]}}} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/confirmTwoToppingOrderPrompt/datasources/default.json b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/confirmTwoToppingOrderPrompt/datasources/default.json deleted file mode 100644 index 9e26dfee..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/confirmTwoToppingOrderPrompt/datasources/default.json +++ /dev/null @@ -1 +0,0 @@ -{} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/confirmTwoToppingOrderPrompt/document.json b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/confirmTwoToppingOrderPrompt/document.json deleted file mode 100644 index e17b3f78..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/confirmTwoToppingOrderPrompt/document.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "type": "APLA", - "version": "0.8", - "mainTemplate": { - "parameters": [ - "payload" - ], - "item": { - "type": "Selector", - "strategy": "randomItem", - "description": "Change 'type' above to try different Selector Component Types like Sequencer", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "Ok, that's a ${payload.first_topping} and ${payload.second_topping} on ${payload.crust} crust. Is that correct?", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/confirmTwoToppingOrderPromptcopy/datasources/default.json b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/confirmTwoToppingOrderPromptcopy/datasources/default.json deleted file mode 100644 index 9e26dfee..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/confirmTwoToppingOrderPromptcopy/datasources/default.json +++ /dev/null @@ -1 +0,0 @@ -{} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/confirmTwoToppingOrderPromptcopy/document.json b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/confirmTwoToppingOrderPromptcopy/document.json deleted file mode 100644 index 330ec5b7..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/confirmTwoToppingOrderPromptcopy/document.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "type": "APLA", - "version": "0.8", - "mainTemplate": { - "parameters": [ - "payload" - ], - "item": { - "type": "Selector", - "strategy": "randomItem", - "description": "Change 'type' above to try different Selector Component Types like Sequencer", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "Ok, that's a ${payload.size} ${payload.first_topping} and ${payload.second_topping} on ${payload.crust} crust. Is that correct?", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/confirmTwoToppingsPrompt/datasources/default.json b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/confirmTwoToppingsPrompt/datasources/default.json deleted file mode 100644 index 9e26dfee..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/confirmTwoToppingsPrompt/datasources/default.json +++ /dev/null @@ -1 +0,0 @@ -{} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/confirmTwoToppingsPrompt/document.json b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/confirmTwoToppingsPrompt/document.json deleted file mode 100644 index d3c1e04b..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/confirmTwoToppingsPrompt/document.json +++ /dev/null @@ -1 +0,0 @@ -{"type":"APLA","version":"0.8","mainTemplate":{"parameters":["payload"],"item":{"type":"Selector","strategy":"randomItem","description":"Change 'type' above to try different Selector Component Types like Sequencer","items":[{"type":"Speech","contentType":"text","content":"Just to confirm, you want ${payload.first_topping} and ${payload.second_topping}","description":"Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that"}]}}} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/confirm_color_for_fruit_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/confirm_color_for_fruit_apla/document.json deleted file mode 100644 index 835d7a8e..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/confirm_color_for_fruit_apla/document.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": [ - "payload" - ], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "confirm color is ${payload.colorName} ? ", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/confirm_fruitName_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/confirm_fruitName_apla/document.json deleted file mode 100644 index 42d63adc..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/confirm_fruitName_apla/document.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": [ - "payload" - ], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "confirm fruit ${payload.fruitName} ? ", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/confirm_main_addon_list_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/confirm_main_addon_list_apla/document.json deleted file mode 100644 index 9b877ce9..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/confirm_main_addon_list_apla/document.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": [ - "payload" - ], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "confirm ${payload.foodName} with ${payload.addOn} ? ", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/confirm_weather_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/confirm_weather_apla/document.json deleted file mode 100644 index 66ea6d2a..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/confirm_weather_apla/document.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": [ - "payload" - ], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "Confirm weather forecast for ${payload.cityName} ${payload.date}?", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/confirm_weather_city_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/confirm_weather_city_apla/document.json deleted file mode 100644 index fb9c3629..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/confirm_weather_city_apla/document.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": [ - "payload" - ], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "Confirm weather for ${payload.cityName}?", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/confirm_weather_date_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/confirm_weather_date_apla/document.json deleted file mode 100644 index 58b5a797..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/confirm_weather_date_apla/document.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": [ - "payload" - ], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "Confirm weather for ${payload.date}?", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/no_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/no_apla/document.json deleted file mode 100644 index 76610fcc..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/no_apla/document.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": [ - "payload" - ], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "I'm sorry you didn't like it", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/nothing2_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/nothing2_apla/document.json deleted file mode 100644 index 98f7ebef..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/nothing2_apla/document.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": [ - "payload" - ], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "The number you gave us was not 3.", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/nothing_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/nothing_apla/document.json deleted file mode 100644 index 5272f2a9..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/nothing_apla/document.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": [ - "payload" - ], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "The number you gave us was 3.", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/numericfeedback_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/numericfeedback_apla/document.json deleted file mode 100644 index 5278049b..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/numericfeedback_apla/document.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": [ - "payload" - ], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [{ - "type": "Speech", - "contentType": "text", - "content": "Your random number was ${payload.num}. How did we do? Please give this interaction a rating between 1-5, where 5 is the highest rating", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - }] - } - } -} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/rating_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/rating_apla/document.json deleted file mode 100644 index 7d50a649..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/rating_apla/document.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": [ - "payload" - ], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "rating please?", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/requestArgs_request_fruitName_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/requestArgs_request_fruitName_apla/document.json deleted file mode 100644 index a27a7d1e..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/requestArgs_request_fruitName_apla/document.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": [ - "payload" - ], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "tell me the fruit name ?", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - }, - { - "type": "Speech", - "contentType": "text", - "content": "random slection tell me the fruit name ?", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/requestFromBookFlight_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/requestFromBookFlight_apla/document.json deleted file mode 100644 index ca9378f4..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/requestFromBookFlight_apla/document.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "type": "APLA", - "version": "0.8", - "mainTemplate": { - "parameters": [ - "payload" - ], - "item": { - "type": "Selector", - "strategy": "randomItem", - "description": "Change 'type' above to try different Selector Component Types like Sequencer", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "from where?", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/requestPickUpFromBookCab_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/requestPickUpFromBookCab_apla/document.json deleted file mode 100644 index 78e43701..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/requestPickUpFromBookCab_apla/document.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "type": "APLA", - "version": "0.8", - "mainTemplate": { - "parameters": [ - "payload" - ], - "item": { - "type": "Selector", - "strategy": "randomItem", - "description": "Change 'type' above to try different Selector Component Types like Sequencer", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "request PickUp From BookCab apla, from where ?", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/requestToBookFlight_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/requestToBookFlight_apla/document.json deleted file mode 100644 index 487721a3..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/requestToBookFlight_apla/document.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "type": "APLA", - "version": "0.8", - "mainTemplate": { - "parameters": [ - "payload" - ], - "item": { - "type": "Selector", - "strategy": "randomItem", - "description": "Change 'type' above to try different Selector Component Types like Sequencer", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "to where ?", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/request_city_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/request_city_apla/document.json deleted file mode 100644 index 65c28562..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/request_city_apla/document.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": [ - "payload" - ], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "Which city?", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/request_city_cityName_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/request_city_cityName_apla/document.json deleted file mode 100644 index 5381b24e..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/request_city_cityName_apla/document.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": [ - "payload" - ], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "Which city?", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - }, - { - "type": "Speech", - "contentType": "text", - "content": "random selector Which city?", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/request_city_cityName_date_AMAZON_DATE_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/request_city_cityName_date_AMAZON_DATE_apla/document.json deleted file mode 100644 index f685b93e..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/request_city_cityName_date_AMAZON_DATE_apla/document.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": [ - "payload" - ], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "Which city and for which date?", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/request_colorName_multiple_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/request_colorName_multiple_apla/document.json deleted file mode 100644 index 62911ca4..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/request_colorName_multiple_apla/document.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": [ - "payload" - ], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "which color?", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/request_date_AMAZON_DATE_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/request_date_AMAZON_DATE_apla/document.json deleted file mode 100644 index 3beebe7b..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/request_date_AMAZON_DATE_apla/document.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": [ - "payload" - ], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "Which date?", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/request_date_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/request_date_apla/document.json deleted file mode 100644 index 3beebe7b..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/request_date_apla/document.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": [ - "payload" - ], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "Which date?", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/request_listAddOns_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/request_listAddOns_apla/document.json deleted file mode 100644 index a27b70ba..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/request_listAddOns_apla/document.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": [ - "payload" - ], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "what are the add ons?", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/request_mainFoodName_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/request_mainFoodName_apla/document.json deleted file mode 100644 index 5e18709e..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/request_mainFoodName_apla/document.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": [ - "payload" - ], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "What is the main food name?", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/request_name_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/request_name_apla/document.json deleted file mode 100644 index 8afc80bf..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/request_name_apla/document.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": [ - "payload" - ], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "SSML", - "content": "what is your cool name?", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/request_sign_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/request_sign_apla/document.json deleted file mode 100644 index dc0099fd..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/request_sign_apla/document.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": [ - "payload" - ], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "SSML", - "content": "which sign", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/requestdropToBookCab_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/requestdropToBookCab_apla/document.json deleted file mode 100644 index 487721a3..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/requestdropToBookCab_apla/document.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "type": "APLA", - "version": "0.8", - "mainTemplate": { - "parameters": [ - "payload" - ], - "item": { - "type": "Selector", - "strategy": "randomItem", - "description": "Change 'type' above to try different Selector Component Types like Sequencer", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "to where ?", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/secondEarthAPI_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/secondEarthAPI_apla/document.json deleted file mode 100644 index be1095b2..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/secondEarthAPI_apla/document.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": [ - "payload" - ], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "success delegating", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/seq_offer_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/seq_offer_apla/document.json deleted file mode 100644 index 44b8510b..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/seq_offer_apla/document.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": [ - "payload" - ], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "sequence offer , lets find fav color by sign and name?", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/successBookCabAPI_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/successBookCabAPI_apla/document.json deleted file mode 100644 index bdeb2660..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/successBookCabAPI_apla/document.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "type": "APLA", - "version": "0.8", - "mainTemplate": { - "parameters": [ - "payload" - ], - "item": { - "type": "Selector", - "strategy": "randomItem", - "description": "Change 'type' above to try different Selector Component Types like Sequencer", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "Booked cab is ${payload.result.orderStatus}", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/successBookFlightAPI_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/successBookFlightAPI_apla/document.json deleted file mode 100644 index c4b2ea1e..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/successBookFlightAPI_apla/document.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "type": "APLA", - "version": "0.8", - "mainTemplate": { - "parameters": [ - "payload" - ], - "item": { - "type": "Selector", - "strategy": "randomItem", - "description": "Change 'type' above to try different Selector Component Types like Sequencer", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "booked flight is ${payload.resultTwo.orderStatus} from ${payload.resultTwo.source} to ${payload.resultTwo.destination}, do you need cab to airport ?", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/success_cookingAPI_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/success_cookingAPI_apla/document.json deleted file mode 100644 index 2214532f..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/success_cookingAPI_apla/document.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": [ - "payload" - ], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "we have ${payload.status.orderStatus}", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/success_favColorSign_Name_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/success_favColorSign_Name_apla/document.json deleted file mode 100644 index 310bdb8a..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/success_favColorSign_Name_apla/document.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": [ - "payload" - ], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "Fav color of ${payload.result.name}, is ${payload.result.color}", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - - ] - } - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/success_fruitPriceAPI_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/success_fruitPriceAPI_apla/document.json deleted file mode 100644 index b4a7272b..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/success_fruitPriceAPI_apla/document.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": [ - "payload" - ], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "price of an ${payload.result.fruitName} is ${payload.result.price} bucks ", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/twoToppingOrderSuccessPrompt/datasources/default.json b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/twoToppingOrderSuccessPrompt/datasources/default.json deleted file mode 100644 index 9e26dfee..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/twoToppingOrderSuccessPrompt/datasources/default.json +++ /dev/null @@ -1 +0,0 @@ -{} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/twoToppingOrderSuccessPrompt/document.json b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/twoToppingOrderSuccessPrompt/document.json deleted file mode 100644 index 6b0c5ce7..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/twoToppingOrderSuccessPrompt/document.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "type": "APLA", - "version": "0.8", - "mainTemplate": { - "parameters": [ - "payload" - ], - "item": { - "type": "Selector", - "strategy": "randomItem", - "description": "Change 'type' above to try different Selector Component Types like Sequencer", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "${payload.speech}", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/weather_success_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/weather_success_apla/document.json deleted file mode 100644 index 1d7b7405..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/weather_success_apla/document.json +++ /dev/null @@ -1,29 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": [ - "payload" - ], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "when": "${payload.weatherResult.cityName != null && payload.weatherResult.highTemp < 3 && payload.weatherResult.lowTemp > 0}", - "type": "Speech", - "contentType": "text", - "content": "Offer In ${payload.weatherResult.cityName}, it's a high of ${payload.weatherResult.highTemp} degrees and a low of ${payload.weatherResult.lowTemp} degrees.", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - }, - { - "when": "${payload.weatherResult.cityName != null && payload.weatherResult.highTemp == null && payload.weatherResult.lowTemp == null}", - "type": "Speech", - "contentType": "text", - "content": "Alternate In ${payload.weatherResult.cityName}, it's a high of ${payload.weatherResult.highTemp} degrees and a low of ${payload.weatherResult.lowTemp} degrees.", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/welcome_apla_custom/document.json b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/welcome_apla_custom/document.json deleted file mode 100644 index 7447b614..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/response/prompts/welcome_apla_custom/document.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": [ - "payload" - ], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "Hi Satheesh , you have visited ${payload.result}", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/skill.json b/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/skill.json deleted file mode 100644 index 9b59923c..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-5/skill-package/skill.json +++ /dev/null @@ -1,96 +0,0 @@ -{ - "manifest": { - "apis": { - "custom": { - "dialogManagement": { - "dialogManagers": [ - { - "type": "AMAZON.Conversations" - } - ], - "sessionStartDelegationStrategy": { - "target": "AMAZON.Conversations" - } - }, - "endpoint": { - "uri": "arn:aws:lambda:us-west-2:267006587462:function:ramansatTestFunction" - }, - "interfaces": [ - { - "supportedViewports": [ - { - "maxHeight": 480, - "maxWidth": 480, - "minHeight": 480, - "minWidth": 480, - "mode": "HUB", - "shape": "ROUND" - }, - { - "maxHeight": 600, - "maxWidth": 1024, - "minHeight": 600, - "minWidth": 1024, - "mode": "HUB", - "shape": "RECTANGLE" - }, - { - "maxHeight": 800, - "maxWidth": 1280, - "minHeight": 800, - "minWidth": 1280, - "mode": "HUB", - "shape": "RECTANGLE" - }, - { - "maxHeight": 540, - "maxWidth": 960, - "minHeight": 540, - "minWidth": 960, - "mode": "TV", - "shape": "RECTANGLE" - } - ], - "type": "ALEXA_PRESENTATION_APL" - } - ], - "regions": { - "NA": { - "endpoint": { - "uri": "arn:aws:lambda:us-west-2:267006587462:function:ramansatTestFunction" - } - }, - "EU": { - "endpoint": { - "uri": "arn:aws:lambda:us-west-2:267006587462:function:ramansatTestFunction" - } - }, - "FE": { - "endpoint": { - "uri": "arn:aws:lambda:us-west-2:267006587462:function:ramansatTestFunction" - } - } - } - } - }, - "manifestVersion": "1.0", - "publishingInformation": { - "category": "KNOWLEDGE_AND_TRIVIA", - "distributionCountries": [], - "isAvailableWorldwide": true, - "locales": { - "en-US": { - "description": "Sample Full Description", - "examplePhrases": [ - "Alexa open hello world", - "hello", - "help" - ], - "name": "engineering test skill two_five", - "summary": "Sample Short Description" - } - }, - "testingInstructions": "Sample Testing Instructions." - } - } -} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-6/.ask/ask-states.json b/test/unit/fixture/dialog-evaluate/test-project-6/.ask/ask-states.json deleted file mode 100644 index 4c00bb5e..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-6/.ask/ask-states.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "askcliStatesVersion": "2020-03-31", - "profiles": { - "default": { - "skillId": "amzn1.ask.skill.e63c21c3-bc74-4503-bbe1-fabad41816bc" - } - } -} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-6/ask-resources.json b/test/unit/fixture/dialog-evaluate/test-project-6/ask-resources.json deleted file mode 100644 index be9cb8d1..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-6/ask-resources.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "askcliResourcesVersion": "2020-03-31", - "profiles": { - "default": { - "skillMetadata": { - "src": "./skill-package" - } - } - } -} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/conversations/ALexaPrize.acdl b/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/conversations/ALexaPrize.acdl deleted file mode 100644 index 3083986a..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/conversations/ALexaPrize.acdl +++ /dev/null @@ -1,213 +0,0 @@ -namespace com.alexaprize - -import com.amazon.alexa.ask.conversations.Affirm -import com.amazon.alexa.ask.conversations.Deny -import com.amazon.alexa.ask.conversations.Invoke -import com.amazon.alexa.ask.conversations.Notify -import com.amazon.alexa.ask.conversations.Offer -import com.amazon.alexa.ask.conversations.expect -import com.amazon.alexa.ask.conversations.response -import com.amazon.alexa.ask.conversations.utterances -import com.amazon.alexa.schema.Boolean -import com.amazon.alexa.schema.Nothing -import com.amazon.alexa.schema.String -import com.amazon.ask.types.builtins.AMAZON.NUMBER -import prompts.alexa_prize_preconditions_apla -import slotTypes.TopicType - -type ConversationDetails { - optional TopicType Topic -} - -letsChatEvent = utterances( - [ - "let's chat", - "i want to chat", - "chat", - "talk", - "let's chat about {Topic}", - "i want to talk about {Topic}", - "can we talk about {Topic}" - ] -) - -affirmEvent = utterances( - [ - "yes", - "yup", - "yeah", - "sure", - "alright" - ] -) - -denyEvent = utterances( - [ - "no", - "nope", - "not really", - "not", - "naah" - ] -) - -type AlexaPrizePreconditions { - NUMBER isLocaleSupported - NUMBER isDeviceSupported - NUMBER isFalseWake - NUMBER isSocialBotAvailable - NUMBER isAlexaPrizeEnabled - NUMBER isTopicBanned - String handoffPromptOverride -} - -type AlexaPrizePreconditionsPayload { - AlexaPrizePreconditions result -} - -type HandoffResults { - String handoffPromptOverride -} - -type HandoffResultsPayload { - HandoffResults result -} - -action AlexaPrizePreconditions checkPreconditionsAndHandoff(TopicType Topic = nothing) - -action HandoffResults intentConfirmedHandoff() - -action HandoffResults intentDeniedHandoff() - -dialog Nothing AlexaPrizeDialog() { - sample { - preconditionsResult = checkPrecondition() - isHandoffPossible = (((preconditionsResult.isDeviceSupported == 1 && preconditionsResult.isLocaleSupported == 1) && preconditionsResult.isSocialBotAvailable == 1) && preconditionsResult.isAlexaPrizeEnabled == 1) - if (isHandoffPossible) { - isConfirmationNeeded = (preconditionsResult.isFalseWake == 1 || preconditionsResult.isTopicBanned == 1) - responses( - isConfirmationNeeded = isConfirmationNeeded, - preconditionsResult = preconditionsResult - ) - } else { - response( - alexa_prize_preconditions_apla, - Notify { - actionName = checkPreconditionsAndHandoff, - success = false - }, - nothing, - AlexaPrizePreconditionsPayload { - result = preconditionsResult - }, - nothing - ) - } - } -} - -dialog AlexaPrizePreconditions checkPrecondition() { - sample { - chatRequest = expect( - Invoke, - letsChatEvent - ) - checkPreconditionsAndHandoff( - chatRequest.Topic - ) - } - sample { - expect( - Invoke, - letsChatEvent - ) - preconditionsResult = checkPreconditionsAndHandoff() - } -} - -dialog Nothing responses(Boolean isConfirmationNeeded, AlexaPrizePreconditions preconditionsResult) { - sample { - if (isConfirmationNeeded) { - handoffResult( - preconditionsResult = preconditionsResult - ) - } else { - response( - alexa_prize_preconditions_apla, - Notify { - actionName = checkPreconditionsAndHandoff - }, - nothing, - AlexaPrizePreconditionsPayload { - result = preconditionsResult - }, - nothing - ) - } - } -} - -dialog Nothing handoffResult(AlexaPrizePreconditions preconditionsResult) { - sample { - response( - alexa_prize_preconditions_apla, - Notify { - actionName = checkPreconditionsAndHandoff - }, - Offer { - actionName = intentConfirmedHandoff - }, - AlexaPrizePreconditionsPayload { - result = preconditionsResult - }, - nothing - ) - expect( - Affirm, - affirmEvent - ) - handoffResults = intentConfirmedHandoff() - response( - alexa_prize_preconditions_apla, - Notify { - actionName = intentConfirmedHandoff - }, - nothing, - HandoffResultsPayload { - result = handoffResults - }, - nothing - ) - } - sample { - response( - alexa_prize_preconditions_apla, - Notify { - actionName = checkPreconditionsAndHandoff - }, - Offer { - actionName = intentDeniedHandoff - }, - AlexaPrizePreconditionsPayload { - result = preconditionsResult - }, - nothing - ) - expect( - Deny, - denyEvent - ) - handoffResults = intentDeniedHandoff() - response( - alexa_prize_preconditions_apla, - Notify { - actionName = intentDeniedHandoff - }, - nothing, - HandoffResultsPayload { - result = handoffResults - }, - nothing - ) - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/conversations/Dialog_NonDeployable.acdl b/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/conversations/Dialog_NonDeployable.acdl deleted file mode 100644 index 346dd841..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/conversations/Dialog_NonDeployable.acdl +++ /dev/null @@ -1,90 +0,0 @@ -namespace dialogs_non_deployable - -import apis.getEmployeeDetails -import com.amazon.alexa.ask.conversations.Inform -import com.amazon.alexa.ask.conversations.Request -import com.amazon.alexa.ask.conversations.expect -import com.amazon.alexa.ask.conversations.response -import com.amazon.ask.types.builtins.AMAZON.DATE -import com.amazon.ask.types.builtins.AMAZON.NUMBER -import prompts.request_dob_getDate_apla -import prompts.request_getEmploeeID_apla -import prompts.request_name_apla -import slotTypes.complexNames -import types.complexResult -import utteracesets.informComplexNameEvent -import utteracesets.informDOBEvent -import utteracesets.informEmployeeIDEvent - -dialog complexNames getName() { - sample { - response( - request_name_apla, - Request { - arguments = [ - getEmployeeDetails.arguments.name1 - ] - }, - nothing, - nothing, - nothing - ) - complexNamesReturn = expect( - Inform, - informComplexNameEvent - ) - complexNamesReturn.name - } -} - -dialog NUMBER getEmploeeID() { - sample { - response( - request_getEmploeeID_apla, - Request { - arguments = [ - getEmployeeDetails.arguments.emplyee1id - ] - }, - nothing, - nothing, - nothing - ) - empID = expect( - Inform, - informEmployeeIDEvent - ) - empID.emplyee1id - } -} - -dialog DATE getDate() { - sample { - response( - request_dob_getDate_apla, - Request { - arguments = [ - getEmployeeDetails.arguments.a_dateOfBirth - ] - }, - nothing, - nothing, - nothing - ) - dobEvent = expect( - Inform, - informDOBEvent - ) - dobEvent.a_dateOfBirth - } -} - -dialog complexResult a_getEmployeeDetails(complexNames name1, NUMBER emplyee1id, DATE a_dateOfBirth) { - sample { - complexResultEvent = getEmployeeDetails( - name1, - emplyee1id, - a_dateOfBirth - ) - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/conversations/Dialogs_reusableDialogsUsage_NonDeployableDialogs.acdl b/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/conversations/Dialogs_reusableDialogsUsage_NonDeployableDialogs.acdl deleted file mode 100644 index cdcf0553..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/conversations/Dialogs_reusableDialogsUsage_NonDeployableDialogs.acdl +++ /dev/null @@ -1,47 +0,0 @@ -namespace reusableDialogs.NonDeployableDialogs - -import apis.getEmployeeDetails -import com.amazon.alexa.ask.conversations.Invoke -import com.amazon.alexa.ask.conversations.Notify -import com.amazon.alexa.ask.conversations.expect -import com.amazon.alexa.ask.conversations.response -import com.amazon.alexa.schema.Nothing -import dialogs_non_deployable.a_getEmployeeDetails -import dialogs_non_deployable.getDate -import dialogs_non_deployable.getEmploeeID -import dialogs_non_deployable.getName -import prompts.getEmployeePosition_success_apla -import types.complexResult -import utteracesets.who_are_you - -type PayLoadresult { - complexResult result -} - -dialog Nothing dilaog_getEmployeePosition() { - sample { - expect( - Invoke, - who_are_you - ) - complexNamesEvent = getName() - NUMBEREvent = getEmploeeID() - DATEEvent = getDate() - resultOne = a_getEmployeeDetails( - name1 = complexNamesEvent, - emplyee1id = NUMBEREvent, - a_dateOfBirth = DATEEvent - ) - response( - getEmployeePosition_success_apla, - Notify { - actionName = getEmployeeDetails - }, - nothing, - PayLoadresult { - result = resultOne - }, - nothing - ) - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/conversations/Weather.acdl b/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/conversations/Weather.acdl deleted file mode 100644 index 6b9b9935..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/conversations/Weather.acdl +++ /dev/null @@ -1,139 +0,0 @@ -namespace com.weatherbot - -import com.amazon.alexa.ask.conversations.Invoke -import com.amazon.alexa.ask.conversations.Notify -import com.amazon.alexa.ask.conversations.RequestArguments -import com.amazon.alexa.ask.conversations.ensure -import com.amazon.alexa.ask.conversations.expect -import com.amazon.alexa.ask.conversations.response -import com.amazon.alexa.ask.conversations.utterances -import com.amazon.alexa.schema.Nothing -import com.amazon.alexa.schema.Thing -import com.amazon.ask.types.builtins.AMAZON.DATE -import com.amazon.ask.types.builtins.AMAZON.NUMBER -import com.amazon.ask.types.builtins.AMAZON.US_CITY -import prompts.request_city_apla -import prompts.request_date_apla -import prompts.weather_apla -import slotTypes.myCustomCities - -type CityAndDate { - optional myCustomCities cityNameChanged - optional US_CITY cityName - optional DATE date -} - -getWeatherEvent = utterances( - [ - "What's the weather {date} in {cityNameChanged}", - "What's the weather {date} in {cityName}", - "what is the weather {date}", - "how is weather" - ] -) - -type WeatherResult { - optional myCustomCities cityNameChanged - optional US_CITY cityName - NUMBER highTemp - NUMBER lowTemp -} - -type ResponsePayload { - WeatherResult weatherResult -} - -action WeatherResult getWeather(DATE date, US_CITY cityName = nothing, myCustomCities cityNameChanged = nothing) - -dialog Nothing Weather() { - sample { - weatherRequest = expect( - Invoke, - getWeatherEvent - ) - ensure( - RequestArguments { - arguments = [ - getWeather.arguments.cityNameChanged - ], - response = request_city_apla - }, - RequestArguments { - arguments = [ - getWeather.arguments.cityName - ], - response = request_city_apla - }, - RequestArguments { - arguments = [ - getWeather.arguments.date - ], - response = request_date_apla - } - ) - weatherResult = getWeather( - weatherRequest.date, - weatherRequest.cityName, - nothing - ) - response( - weather_apla, - Notify { - actionName = getWeather - }, - nothing, - ResponsePayload { - weatherResult = weatherResult - }, - nothing - ) - } - sample { - weatherRequest = expect( - Invoke, - getWeatherEvent - ) - ensure( - RequestArguments { - arguments = [ - getWeather.arguments.cityNameChanged - ], - response = request_city_apla - }, - RequestArguments { - arguments = [ - getWeather.arguments.cityName - ], - response = request_city_apla - }, - RequestArguments { - arguments = [ - getWeather.arguments.date - ], - response = request_date_apla - } - ) - weatherResult = getWeather( - weatherRequest.date, - nothing, - weatherRequest.cityNameChanged - ) - response( - weather_apla, - Notify { - actionName = getWeather - }, - nothing, - ResponsePayload { - weatherResult = weatherResult - }, - nothing - ) - } -} - -dialog Nothing ComplexTest() { - sample { - Weather() - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/conversations/apisNamepaceLambda.acdl b/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/conversations/apisNamepaceLambda.acdl deleted file mode 100644 index 553a40c5..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/conversations/apisNamepaceLambda.acdl +++ /dev/null @@ -1,22 +0,0 @@ -namespace com.weatherbot.apis - -import com.amazon.ask.types.builtins.AMAZON.Food -import com.amazon.ask.types.builtins.AMAZON.NUMBER -import slotTypes.myColors - -type result { - Food fruitName - NUMBER price -} - -type payloadgetFruitPriceEvent { - result result -} - -action result fruitNameAPI(Food fruitName) - -action resultthree colorFruitName(myColors colorName) - -type resultthree { - Food fruitName -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/conversations/apis_mine.acdl b/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/conversations/apis_mine.acdl deleted file mode 100644 index 072d682e..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/conversations/apis_mine.acdl +++ /dev/null @@ -1,15 +0,0 @@ -namespace apis - -import com.amazon.alexa.schema.Nothing -import com.amazon.ask.types.builtins.AMAZON.DATE -import com.amazon.ask.types.builtins.AMAZON.NUMBER -import slotTypes.complexNames -import slotTypes.signs -import types.complexResult -import types.result_one - -action Nothing secondEarthAPI() - -action result_one favColorSign_Name(complexNames name, signs sign = nothing) - -action complexResult getEmployeeDetails(complexNames name1, NUMBER emplyee1id, DATE a_dateOfBirth = nothing) diff --git a/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/conversations/conversation_empty.acdl b/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/conversations/conversation_empty.acdl deleted file mode 100644 index 361e9d9b..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/conversations/conversation_empty.acdl +++ /dev/null @@ -1,115 +0,0 @@ -namespace com.numberbot - -import com.amazon.alexa.ask.conversations.APLA -import com.amazon.alexa.ask.conversations.Action -import com.amazon.alexa.ask.conversations.Bye -import com.amazon.alexa.ask.conversations.Invoke -import com.amazon.alexa.ask.conversations.Notify -import com.amazon.alexa.ask.conversations.Offer -import com.amazon.alexa.ask.conversations.RequestArguments -import com.amazon.alexa.ask.conversations.ensure -import com.amazon.alexa.ask.conversations.expect -import com.amazon.alexa.ask.conversations.response -import com.amazon.alexa.ask.conversations.utterances -import com.amazon.alexa.schema.Nothing -import com.amazon.alexa.schema.Number -import com.amazon.alexa.schema.Thing -import com.amazon.ask.types.builtins.AMAZON.NUMBER -import prompts.AlexaConversationsBye -import prompts.numericfeedback_apla -import prompts.rating_apla - -type NumPayload { - Number num -} - -type RatingRequest { - NUMBER rating -} - -InformRatingEvent = utterances( - [ - "my score is {rating}", - "that was a {rating} conversation", - "i rate you a {rating}", - "{rating}" - ] -) - -getStart = utterances( - [ - "give me a number please" - ] -) - -action Nothing saveRating(Number rating) - -action Number getNumber() - -dialog Nothing GetFeedback(APLA feedback_prompt, Number num, Action notifyAction) { - sample { - response( - feedback_prompt, - Notify { - actionName = notifyAction, - success = true - }, - Offer { - actionName = saveRating, - arguments = [ - saveRating.arguments.rating - ] - }, - NumPayload { - num = num - }, - nothing - ) - myRating = expect( - Invoke, - InformRatingEvent - ) - ensure( - RequestArguments { - arguments = [ - saveRating.arguments.rating - ], - response = rating_apla - } - ) - saveRating( - myRating.rating - ) - } -} - -dialog Number levelOne() { - sample { - expect( - Invoke, - getStart - ) - num = getNumber() - } -} - -dialog Nothing MainDialog() { - sample { - num = levelOne() - GetFeedback( - feedback_prompt = numericfeedback_apla, - num = num, - notifyAction = getNumber - ) - response( - AlexaConversationsBye, - Notify { - actionName = saveRating, - success = true - }, - Bye {}, - nothing, - nothing - ) - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/conversations/soaDialog.acdl b/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/conversations/soaDialog.acdl deleted file mode 100644 index d44e9477..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/conversations/soaDialog.acdl +++ /dev/null @@ -1,89 +0,0 @@ -namespace soaACDl - -import com.amazon.alexa.ask.conversations.Inform -import com.amazon.alexa.ask.conversations.Invoke -import com.amazon.alexa.ask.conversations.Notify -import com.amazon.alexa.ask.conversations.Request -import com.amazon.alexa.ask.conversations.expect -import com.amazon.alexa.ask.conversations.response -import com.amazon.alexa.ask.conversations.utterances -import com.amazon.alexa.schema.Nothing -import com.weatherbot.apis.colorFruitName -import com.weatherbot.apis.resultthree -import prompts.request_colorName_multiple_apla -import prompts.success_colorFruitAPI_apla -import slotTypes.myColors - -type payloadMultipleDialogEvent { - resultthree result -} - -MultipleDialogEvent = utterances( - [ - "i want to buy a fruit" - ] -) - -affirmMultipleColorEvent = utterances( - [ - "do it" - ] -) - -type colorNameShell { - myColors colorName -} - -type payloadsOAConfirmArgs { - myColors colorName -} - -type colorEvent0 { - myColors colorName -} - -informColorMultipleEvent = utterances( - [ - "{colorName}", - "color is {colorName}", - "color {colorName}" - ] -) - -dialog Nothing testMe() { - sample { - expect( - Invoke, - MultipleDialogEvent - ) - response( - request_colorName_multiple_apla, - Request { - arguments = [ - colorFruitName.arguments.colorName - ] - }, - nothing, - nothing, - nothing - ) - colorEvent = expect( - Inform, - informColorMultipleEvent - ) - resultEvent = colorFruitName( - colorEvent.colorName - ) - response( - success_colorFruitAPI_apla, - Notify { - actionName = colorFruitName - }, - nothing, - payloadMultipleDialogEvent { - result = resultEvent - }, - nothing - ) - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/conversations/types_mine.acdl b/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/conversations/types_mine.acdl deleted file mode 100644 index 3cc656d2..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/conversations/types_mine.acdl +++ /dev/null @@ -1,43 +0,0 @@ -namespace types - -import com.amazon.ask.types.builtins.AMAZON.Color -import com.amazon.ask.types.builtins.AMAZON.DATE -import com.amazon.ask.types.builtins.AMAZON.Food -import com.amazon.ask.types.builtins.AMAZON.NUMBER -import slotTypes.complexNames -import slotTypes.myColors -import slotTypes.position -import slotTypes.signs - -type result_one { - Color colorName - complexNames name - signs sign -} - -type complexResult { - complexNames name1 - DATE a_dateOfBirth - NUMBER emplyee1id - position position -} - -type nameShell { - complexNames name -} - -type dobshell { - DATE a_dateOfBirth -} - -type employeeIDshell { - NUMBER emplyee1id -} - -type fruitNameShell { - Food fruitName -} - -type colorEvent0 { - myColors colorName -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/conversations/utteracesets_mine.acdl b/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/conversations/utteracesets_mine.acdl deleted file mode 100644 index 99c73e00..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/conversations/utteracesets_mine.acdl +++ /dev/null @@ -1,82 +0,0 @@ -namespace utteracesets - -import com.amazon.alexa.ask.conversations.utterances -import types.dobshell -import types.employeeIDshell -import types.fruitNameShell -import types.nameShell - -getFruitPriceEvent = utterances( - [ - "what is the price of the fruit", - "what is the price of fruit" - ] -) - -affirmFruitAPIEvent = utterances( - [ - "yeah" - ] -) - -informfruitNameEvent = utterances( - [ - "{fruitName}", - "fruit name is {fruitName}", - "fruit is {fruitName}" - ] -) - -delegateToSkill = utterances( - [ - "get me to paradise", - "take me to paradise" - ] -) - -getFavColorEvent = utterances( - [ - "what is my favourite color", - "tell my favourite color" - ] -) - -affirmFavColorEvent = utterances( - [ - "correct" - ] -) - -who_are_you = utterances( - [ - "who are you", - "who is that", - "find his designation" - ] -) - -informComplexNameEvent = utterances( - [ - "{name}", - "name is {name}", - "i am {name}" - ] -) - -informDOBEvent = utterances( - [ - "date of birth is {a_dateOfBirth}", - "birth date is {a_dateOfBirth}" - ] -) - -informEmployeeIDEvent = utterances( - [ - "employee i.d. is {emplyee1id}", - "employee identification is {emplyee1id}", - "identification is {emplyee1id}", - "employee id is {emplyee1id}", - "i.d. is {emplyee1id}", - "id is {emplyee1id}" - ] -) diff --git a/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/interactionModels/custom/en-US.json b/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/interactionModels/custom/en-US.json deleted file mode 100644 index be0e8aff..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/interactionModels/custom/en-US.json +++ /dev/null @@ -1,923 +0,0 @@ -{ - "interactionModel": { - "languageModel": { - "invocationName": "model feedback test skill four", - "intents": [ - { - "name": "AMAZON.CancelIntent", - "samples": [] - }, - { - "name": "AMAZON.HelpIntent", - "samples": [] - }, - { - "name": "AMAZON.StopIntent", - "samples": [] - }, - { - "name": "GetWeatherIntent", - "samples": [ - "what is the weather", - "how is the weather", - "tell me the weather" - ] - }, - { - "name": "AMAZON.NavigateHomeIntent", - "samples": [] - }, - { - "name": "AMAZON.FallbackIntent", - "samples": [] - } - ], - "types": [ - { - "values": [ - { - "id": "movies", - "name": { - "value": "movies", - "synonyms": [] - } - }, - { - "id": "politics", - "name": { - "value": "politics", - "synonyms": [] - } - }, - { - "id": "sports", - "name": { - "value": "sports", - "synonyms": [] - } - }, - { - "id": "hobbies", - "name": { - "value": "hobbies", - "synonyms": [] - } - }, - { - "id": "astronomy", - "name": { - "value": "astronomy", - "synonyms": [] - } - }, - { - "id": "physics", - "name": { - "value": "physics", - "synonyms": [] - } - }, - { - "id": "los_angeles_dodgers", - "name": { - "value": "los angeles dodgers" - } - }, - { - "id": "president_emmanuel_macron", - "name": { - "value": "president emmanuel macron" - } - }, - { - "id": "emmanuel_macron", - "name": { - "value": "emmanuel macron" - } - }, - { - "id": "tax_cuts", - "name": { - "value": "tax cuts" - } - }, - { - "id": "middle_class", - "name": { - "value": "middle class" - } - }, - { - "id": "inequality_divide", - "name": { - "value": "inequality divide" - } - }, - { - "id": "wealth_inequality", - "name": { - "value": "wealth inequality" - } - }, - { - "id": "n._p._r.", - "name": { - "value": "n. p. r." - } - }, - { - "id": "president_trump", - "name": { - "value": "president trump" - } - }, - { - "id": "fox", - "name": { - "value": "fox" - } - }, - { - "id": "police_officers", - "name": { - "value": "police officers" - } - }, - { - "id": "jerome_hall", - "name": { - "value": "jerome hall" - } - }, - { - "id": "diversity_training_program", - "name": { - "value": "diversity training program" - } - }, - { - "id": "read_preble", - "name": { - "value": "read preble" - } - }, - { - "id": "christopher_preble", - "name": { - "value": "christopher preble" - } - }, - { - "id": "pacific_rim", - "name": { - "value": "pacific rim" - } - }, - { - "id": "washington_nationals", - "name": { - "value": "washington nationals" - } - }, - { - "id": "michael_cohen", - "name": { - "value": "michael cohen" - } - }, - { - "id": "john_wall", - "name": { - "value": "john wall" - } - }, - { - "id": "united_states", - "name": { - "value": "united states" - } - }, - { - "id": "washington_wizards", - "name": { - "value": "washington wizards" - } - }, - { - "id": "bryce_harper", - "name": { - "value": "bryce harper" - } - }, - { - "id": "capitals_playoff_hockey_capitals", - "name": { - "value": "capitals playoff hockey capitals" - } - }, - { - "id": "james_b._comey", - "name": { - "value": "james b. comey" - } - }, - { - "id": "mike_pompeo", - "name": { - "value": "mike pompeo" - } - }, - { - "id": "tom_toles", - "name": { - "value": "tom toles" - } - }, - { - "id": "white_house", - "name": { - "value": "white house" - } - }, - { - "id": "manny_machado", - "name": { - "value": "manny machado" - } - }, - { - "id": "national_league_east", - "name": { - "value": "national league east" - } - }, - { - "id": "otto_porter_jr._now", - "name": { - "value": "otto porter jr. now" - } - }, - { - "id": "hillary_clinton", - "name": { - "value": "hillary clinton" - } - }, - { - "id": "trea_turner", - "name": { - "value": "trea turner" - } - }, - { - "id": "max_scherzer", - "name": { - "value": "max scherzer" - } - }, - { - "id": "donald_trump", - "name": { - "value": "donald trump" - } - }, - { - "id": "bryce_harper_nationals", - "name": { - "value": "bryce harper nationals" - } - }, - { - "id": "michael_a._taylor", - "name": { - "value": "michael a. taylor" - } - }, - { - "id": "news_media", - "name": { - "value": "news media" - } - }, - { - "id": "conservative_political_action_conference", - "name": { - "value": "conservative political action conference" - } - }, - { - "id": "mainstream_media", - "name": { - "value": "mainstream media" - } - }, - { - "id": "baltimore_orioles", - "name": { - "value": "baltimore orioles" - } - }, - { - "id": "sean_hannity", - "name": { - "value": "sean hannity" - } - }, - { - "id": "privilege", - "name": { - "value": "privilege" - } - }, - { - "id": "sarah_hart", - "name": { - "value": "sarah hart" - } - }, - { - "id": "matt_kemp", - "name": { - "value": "matt kemp" - } - }, - { - "id": "stephen_strasburg", - "name": { - "value": "stephen strasburg" - } - }, - { - "id": "police_misconduct", - "name": { - "value": "police misconduct" - } - }, - { - "id": "sarah_huckabee_sanders", - "name": { - "value": "sarah huckabee sanders" - } - }, - { - "id": "washington_wizards_april", - "name": { - "value": "washington wizards april" - } - }, - { - "id": "environmental_protection_agency_administrator_scott_pruitt", - "name": { - "value": "environmental protection agency administrator scott pruitt" - } - }, - { - "id": "dodger_stadium", - "name": { - "value": "dodger stadium" - } - }, - { - "id": "environmental_protection_agency", - "name": { - "value": "environmental protection agency" - } - }, - { - "id": "barbara_bush", - "name": { - "value": "barbara bush" - } - }, - { - "id": "lewis_\"scooter\"_libby", - "name": { - "value": "lewis \"scooter\" libby" - } - }, - { - "id": "lewis_scooter_libby", - "name": { - "value": "lewis scooter libby" - } - }, - { - "id": "game_3._lowry", - "name": { - "value": "game 3. lowry" - } - }, - { - "id": "columbus_blue_jackets", - "name": { - "value": "columbus blue jackets" - } - }, - { - "id": "john_tortorella", - "name": { - "value": "john tortorella" - } - }, - { - "id": "george_w._bush", - "name": { - "value": "george w. bush" - } - }, - { - "id": "george_h.w._bush", - "name": { - "value": "george h.w. bush" - } - }, - { - "id": "jarrett_hurd", - "name": { - "value": "jarrett hurd" - } - }, - { - "id": "said_fred_hurd_sr.", - "name": { - "value": "said fred hurd sr." - } - }, - { - "id": "fred_hurd_sr.", - "name": { - "value": "fred hurd sr." - } - }, - { - "id": "san_antonio", - "name": { - "value": "san antonio" - } - }, - { - "id": "san_antonio_spurs", - "name": { - "value": "san antonio spurs" - } - }, - { - "id": "gregg_popovich", - "name": { - "value": "gregg popovich" - } - }, - { - "id": "kawhi_leonard", - "name": { - "value": "kawhi leonard" - } - }, - { - "id": "tim_bontemps_seth_jones", - "name": { - "value": "tim bontemps seth jones" - } - }, - { - "id": "consumer_sentiment_index", - "name": { - "value": "consumer sentiment index" - } - }, - { - "id": "pew_research_center", - "name": { - "value": "pew research center" - } - }, - { - "id": "conference_board_consumer_confidence_survey", - "name": { - "value": "conference board consumer confidence survey" - } - }, - { - "id": "speech_rights", - "name": { - "value": "speech rights" - } - }, - { - "id": "first_amendment", - "name": { - "value": "first amendment" - } - }, - { - "id": "golden_state", - "name": { - "value": "golden state" - } - }, - { - "id": "north_korea", - "name": { - "value": "north korea" - } - }, - { - "id": "woman_pilot", - "name": { - "value": "woman pilot" - } - }, - { - "id": "airline_pilot_population", - "name": { - "value": "airline pilot population" - } - }, - { - "id": "air_transport_pilot", - "name": { - "value": "air transport pilot" - } - }, - { - "id": "southwest_airlines", - "name": { - "value": "southwest airlines" - } - }, - { - "id": "democratic_national_committee", - "name": { - "value": "democratic national committee" - } - }, - { - "id": "senate_foreign_relations_committee", - "name": { - "value": "senate foreign relations committee" - } - }, - { - "id": "cia_director_mike_pompeo", - "name": { - "value": "cia director mike pompeo" - } - }, - { - "id": "playoff_overtime_games", - "name": { - "value": "playoff overtime games" - } - }, - { - "id": "lord_jesus", - "name": { - "value": "lord jesus" - } - }, - { - "id": "lgbtq_community", - "name": { - "value": "lgbtq community" - } - }, - { - "id": "health_and_human_services_department", - "name": { - "value": "health and human services department" - } - }, - { - "id": "group_prayer", - "name": { - "value": "group prayer" - } - }, - { - "id": "princess_charlotte_elizabeth_diana", - "name": { - "value": "princess charlotte elizabeth diana" - } - }, - { - "id": "term_war_economy", - "name": { - "value": "term war economy" - } - }, - { - "id": "melissa_kirk", - "name": { - "value": "melissa kirk" - } - }, - { - "id": "captain_america", - "name": { - "value": "captain america" - } - }, - { - "id": "draft_position", - "name": { - "value": "draft position" - } - }, - { - "id": "elysee_mbem-bosse", - "name": { - "value": "elysee mbem-bosse" - } - }, - { - "id": "water_crisis", - "name": { - "value": "water crisis" - } - }, - { - "id": "nationals_pitchers", - "name": { - "value": "nationals pitchers" - } - }, - { - "id": "sen._jennifer_t._wexton", - "name": { - "value": "sen. jennifer t. wexton" - } - }, - { - "id": "interest_rates", - "name": { - "value": "interest rates" - } - }, - { - "id": "town_crier", - "name": { - "value": "town crier" - } - }, - { - "id": "nancy_goes_millennial", - "name": { - "value": "nancy goes millennial" - } - }, - { - "id": "steve_rogers", - "name": { - "value": "steve rogers" - } - }, - { - "id": "game_3._lebron_james", - "name": { - "value": "game 3. lebron james" - } - }, - { - "id": "anthony_rendon", - "name": { - "value": "anthony rendon" - } - }, - { - "id": "buckingham_palace", - "name": { - "value": "buckingham palace" - } - }, - { - "id": "travis_reinking_suspected", - "name": { - "value": "travis reinking suspected" - } - }, - { - "id": "detroit_free_press", - "name": { - "value": "detroit free press" - } - }, - { - "id": "national_rifle_association", - "name": { - "value": "national rifle association" - } - }, - { - "id": "ed_harris", - "name": { - "value": "ed harris" - } - }, - { - "id": "overtime_playoff_games", - "name": { - "value": "overtime playoff games" - } - }, - { - "id": "republican_sen._bob_corker", - "name": { - "value": "republican sen. bob corker" - } - }, - { - "id": "electricity_sector_reforms", - "name": { - "value": "electricity sector reforms" - } - }, - { - "id": "baltimore_manager_buck_showalter", - "name": { - "value": "baltimore manager buck showalter" - } - }, - { - "id": "sen._joe_manchin_iii", - "name": { - "value": "sen. joe manchin iii" - } - }, - { - "id": "car_seat_belts", - "name": { - "value": "car seat belts" - } - }, - { - "id": "andrews_mcmeel.", - "name": { - "value": "andrews mcmeel." - } - }, - { - "id": "north_africa_program", - "name": { - "value": "north africa program" - } - }, - { - "id": "state_prosecutor_lobby", - "name": { - "value": "state prosecutor lobby" - } - }, - { - "id": "cape_town", - "name": { - "value": "cape town" - } - }, - { - "id": "data_privacy_law", - "name": { - "value": "data privacy law" - } - }, - { - "id": "president_trump_down", - "name": { - "value": "president trump down" - } - }, - { - "id": "christian_kirk", - "name": { - "value": "christian kirk" - } - }, - { - "id": "mitch_mcconnell", - "name": { - "value": "mitch mcconnell" - } - }, - { - "id": "federal_reserve", - "name": { - "value": "federal reserve" - } - } - ], - "name": "TopicType" - }, - { - "values": [ - { - "name": { - "value": "cancer" - } - }, - { - "name": { - "value": "scorpio" - } - }, - { - "name": { - "value": "scorpion" - } - } - ], - "name": "signs" - }, - { - "values": [ - { - "name": { - "value": "satheesh" - } - }, - { - "name": { - "value": "raman" - } - }, - { - "name": { - "value": "yadhu" - } - } - ], - "name": "complexNames" - }, - { - "values": [ - { - "name": { - "value": "tester" - } - }, - { - "name": { - "value": "engineer" - } - }, - { - "name": { - "value": "manager" - } - } - ], - "name": "position" - }, - { - "values": [ - { - "name": { - "value": "blue" - } - }, - { - "name": { - "value": "red" - } - }, - { - "name": { - "value": "rocket" - } - } - ], - "name": "myColors" - }, - { - "values": [ - { - "name": { - "value": "flower city" - } - }, - { - "name": { - "value": "temple city" - } - }, - { - "name": { - "value": "ramapuram" - } - }, - { - "name": { - "value": "guindy" - } - }, - { - "name": { - "value": "porur" - } - } - ], - "name": "myCustomCities" - } - ] - } - }, - "version": "9" -} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/display/confirm_city_apl_display/document.json b/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/display/confirm_city_apl_display/document.json deleted file mode 100644 index 741e1a5f..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/display/confirm_city_apl_display/document.json +++ /dev/null @@ -1,358 +0,0 @@ -{ - "type": "APL", - "version": "1.1", - "settings": {}, - "theme": "dark", - "import": [ - { - "name": "alexa-layouts", - "version": "1.0.0" - } - ], - "resources": [ - { - "description": "Stock color for the light theme", - "colors": { - "colorTextPrimary": "#151920" - } - }, - { - "description": "Stock color for the dark theme", - "when": "${viewport.theme == 'dark'}", - "colors": { - "colorTextPrimary": "#f0f1ef" - } - }, - { - "description": "Standard font sizes", - "dimensions": { - "textSizeBody": 48, - "textSizePrimary": 27, - "textSizeSecondary": 23, - "textSizeDetails": 20, - "textSizeSecondaryHint": 25 - } - }, - { - "description": "Common spacing values", - "dimensions": { - "spacingThin": 6, - "spacingSmall": 12, - "spacingMedium": 24, - "spacingLarge": 48, - "spacingExtraLarge": 72 - } - }, - { - "description": "Common margins and padding", - "dimensions": { - "marginTop": 40, - "marginLeft": 60, - "marginRight": 60, - "marginBottom": 40 - } - } - ], - "styles": { - "textStyleBase": { - "description": "Base font description; set color", - "values": [ - { - "color": "@colorTextPrimary" - } - ] - }, - "textStyleBase0": { - "description": "Thin version of basic font", - "extend": "textStyleBase", - "values": { - "fontWeight": "100" - } - }, - "textStyleBase1": { - "description": "Light version of basic font", - "extend": "textStyleBase", - "values": { - "fontWeight": "300" - } - }, - "textStyleBase2": { - "description": "Regular version of basic font", - "extend": "textStyleBase", - "values": { - "fontWeight": "500" - } - }, - "mixinBody": { - "values": { - "fontSize": "@textSizeBody" - } - }, - "mixinPrimary": { - "values": { - "fontSize": "@textSizePrimary" - } - }, - "mixinDetails": { - "values": { - "fontSize": "@textSizeDetails" - } - }, - "mixinSecondary": { - "values": { - "fontSize": "@textSizeSecondary" - } - }, - "textStylePrimary": { - "extend": [ - "textStyleBase1", - "mixinPrimary" - ] - }, - "textStyleSecondary": { - "extend": [ - "textStyleBase0", - "mixinSecondary" - ] - }, - "textStyleBody": { - "extend": [ - "textStyleBase1", - "mixinBody" - ] - }, - "textStyleSecondaryHint": { - "values": { - "fontFamily": "Bookerly", - "fontStyle": "italic", - "fontSize": "@textSizeSecondaryHint", - "color": "@colorTextPrimary" - } - }, - "textStyleDetails": { - "extend": [ - "textStyleBase2", - "mixinDetails" - ] - } - }, - "onMount": [], - "graphics": {}, - "commands": {}, - "layouts": { - "ListTemplate1": { - "parameters": [ - "backgroundImage", - "title", - "logo", - "hintText", - "listData" - ], - "item": [ - { - "type": "Container", - "width": "100vw", - "height": "100vh", - "direction": "column", - "items": [ - { - "type": "Image", - "source": "${backgroundImage}", - "scale": "best-fill", - "width": "100vw", - "height": "100vh", - "position": "absolute" - }, - { - "type": "AlexaHeader", - "headerTitle": "${title}", - "headerAttributionImage": "${logo}" - }, - { - "type": "Sequence", - "grow": 1, - "height": "80vh", - "scrollDirection": "vertical", - "paddingLeft": "@marginLeft", - "paddingRight": "@marginRight", - "data": "${listData}", - "numbered": true, - "items": [ - { - "type": "VerticalListItem", - "image": "${data.image.sources[0].url}", - "primaryText": "${data.textContent.primaryText.text}", - "secondaryText": "${data.textContent.secondaryText.text}", - "tertiaryText": "${data.textContent.tertiaryText.text}" - } - ] - } - ] - } - ] - }, - "VerticalListItem": { - "parameters": [ - "primaryText", - "secondaryText", - "tertiaryText", - "image" - ], - "item": [ - { - "when": "${viewport.shape == 'round'}", - "type": "Container", - "direction": "row", - "height": 200, - "width": 500, - "alignItems": "center", - "items": [ - { - "type": "Text", - "text": "${ordinal}", - "paddingBottom": "20dp", - "color": "white", - "spacing": "5dp" - }, - { - "type": "Image", - "when": "${image}", - "source": "${image}", - "height": 150, - "width": 150, - "spacing": 15, - "scale": "best-fit", - "align": "top" - }, - { - "type": "Container", - "direction": "column", - "spacing": 25, - "items": [ - { - "type": "Text", - "text": "${primaryText}", - "style": "textStyleDetail", - "grow": 1, - "shrink": 1, - "fontWeight": "300", - "maxLines": 1 - }, - { - "type": "Text", - "text": "${secondaryText}", - "style": "textStyleCaption", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - }, - { - "type": "Text", - "text": "${tertiaryText}", - "style": "textStyleDetails", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - } - ] - } - ] - }, - { - "type": "Container", - "direction": "row", - "height": 125, - "width": 800, - "alignItems": "center", - "items": [ - { - "type": "Text", - "text": "${ordinal}", - "paddingBottom": "20dp", - "color": "white", - "spacing": "5dp" - }, - { - "type": "Image", - "when": "${image}", - "source": "${image}", - "height": 100, - "width": 100, - "align": "top", - "spacing": 50, - "scale": "best-fit" - }, - { - "type": "Container", - "spacing": 30, - "direction": "column", - "items": [ - { - "type": "Text", - "text": "${primaryText}", - "style": "textStyleBody", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - }, - { - "type": "Text", - "text": "${secondaryText}", - "style": "textStyleDetails", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - } - ] - }, - { - "type": "Text", - "text": "${tertiaryText}", - "style": "textStyleBody", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "textAlign": "right", - "maxLines": 1 - } - ] - } - ] - } - }, - "mainTemplate": { - "parameters": [ - "payload" - ], - "item": [ - { - "type": "Container", - "id": "BookCabSimpleDialogAPL", - "items": [ - { - "type": "TouchWrapper", - "onPress": { - "type": "SendEvent", - "arguments": [ - "delegateToColtraneOld" - ] - }, - "item": { - "type": "Text", - "id": "BookCabSimpleDialogAPL", - "paddingTop": "100", - "paddingLeft": "100", - "color": "green", - "size": 50, - "text": "which city ?" - } - } - ] - } - ] - } -} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/display/confirm_date_apl_display/document.json b/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/display/confirm_date_apl_display/document.json deleted file mode 100644 index 9ff71e5c..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/display/confirm_date_apl_display/document.json +++ /dev/null @@ -1,358 +0,0 @@ -{ - "type": "APL", - "version": "1.1", - "settings": {}, - "theme": "dark", - "import": [ - { - "name": "alexa-layouts", - "version": "1.0.0" - } - ], - "resources": [ - { - "description": "Stock color for the light theme", - "colors": { - "colorTextPrimary": "#151920" - } - }, - { - "description": "Stock color for the dark theme", - "when": "${viewport.theme == 'dark'}", - "colors": { - "colorTextPrimary": "#f0f1ef" - } - }, - { - "description": "Standard font sizes", - "dimensions": { - "textSizeBody": 48, - "textSizePrimary": 27, - "textSizeSecondary": 23, - "textSizeDetails": 20, - "textSizeSecondaryHint": 25 - } - }, - { - "description": "Common spacing values", - "dimensions": { - "spacingThin": 6, - "spacingSmall": 12, - "spacingMedium": 24, - "spacingLarge": 48, - "spacingExtraLarge": 72 - } - }, - { - "description": "Common margins and padding", - "dimensions": { - "marginTop": 40, - "marginLeft": 60, - "marginRight": 60, - "marginBottom": 40 - } - } - ], - "styles": { - "textStyleBase": { - "description": "Base font description; set color", - "values": [ - { - "color": "@colorTextPrimary" - } - ] - }, - "textStyleBase0": { - "description": "Thin version of basic font", - "extend": "textStyleBase", - "values": { - "fontWeight": "100" - } - }, - "textStyleBase1": { - "description": "Light version of basic font", - "extend": "textStyleBase", - "values": { - "fontWeight": "300" - } - }, - "textStyleBase2": { - "description": "Regular version of basic font", - "extend": "textStyleBase", - "values": { - "fontWeight": "500" - } - }, - "mixinBody": { - "values": { - "fontSize": "@textSizeBody" - } - }, - "mixinPrimary": { - "values": { - "fontSize": "@textSizePrimary" - } - }, - "mixinDetails": { - "values": { - "fontSize": "@textSizeDetails" - } - }, - "mixinSecondary": { - "values": { - "fontSize": "@textSizeSecondary" - } - }, - "textStylePrimary": { - "extend": [ - "textStyleBase1", - "mixinPrimary" - ] - }, - "textStyleSecondary": { - "extend": [ - "textStyleBase0", - "mixinSecondary" - ] - }, - "textStyleBody": { - "extend": [ - "textStyleBase1", - "mixinBody" - ] - }, - "textStyleSecondaryHint": { - "values": { - "fontFamily": "Bookerly", - "fontStyle": "italic", - "fontSize": "@textSizeSecondaryHint", - "color": "@colorTextPrimary" - } - }, - "textStyleDetails": { - "extend": [ - "textStyleBase2", - "mixinDetails" - ] - } - }, - "onMount": [], - "graphics": {}, - "commands": {}, - "layouts": { - "ListTemplate1": { - "parameters": [ - "backgroundImage", - "title", - "logo", - "hintText", - "listData" - ], - "item": [ - { - "type": "Container", - "width": "100vw", - "height": "100vh", - "direction": "column", - "items": [ - { - "type": "Image", - "source": "${backgroundImage}", - "scale": "best-fill", - "width": "100vw", - "height": "100vh", - "position": "absolute" - }, - { - "type": "AlexaHeader", - "headerTitle": "${title}", - "headerAttributionImage": "${logo}" - }, - { - "type": "Sequence", - "grow": 1, - "height": "80vh", - "scrollDirection": "vertical", - "paddingLeft": "@marginLeft", - "paddingRight": "@marginRight", - "data": "${listData}", - "numbered": true, - "items": [ - { - "type": "VerticalListItem", - "image": "${data.image.sources[0].url}", - "primaryText": "${data.textContent.primaryText.text}", - "secondaryText": "${data.textContent.secondaryText.text}", - "tertiaryText": "${data.textContent.tertiaryText.text}" - } - ] - } - ] - } - ] - }, - "VerticalListItem": { - "parameters": [ - "primaryText", - "secondaryText", - "tertiaryText", - "image" - ], - "item": [ - { - "when": "${viewport.shape == 'round'}", - "type": "Container", - "direction": "row", - "height": 200, - "width": 500, - "alignItems": "center", - "items": [ - { - "type": "Text", - "text": "${ordinal}", - "paddingBottom": "20dp", - "color": "white", - "spacing": "5dp" - }, - { - "type": "Image", - "when": "${image}", - "source": "${image}", - "height": 150, - "width": 150, - "spacing": 15, - "scale": "best-fit", - "align": "top" - }, - { - "type": "Container", - "direction": "column", - "spacing": 25, - "items": [ - { - "type": "Text", - "text": "${primaryText}", - "style": "textStyleDetail", - "grow": 1, - "shrink": 1, - "fontWeight": "300", - "maxLines": 1 - }, - { - "type": "Text", - "text": "${secondaryText}", - "style": "textStyleCaption", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - }, - { - "type": "Text", - "text": "${tertiaryText}", - "style": "textStyleDetails", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - } - ] - } - ] - }, - { - "type": "Container", - "direction": "row", - "height": 125, - "width": 800, - "alignItems": "center", - "items": [ - { - "type": "Text", - "text": "${ordinal}", - "paddingBottom": "20dp", - "color": "white", - "spacing": "5dp" - }, - { - "type": "Image", - "when": "${image}", - "source": "${image}", - "height": 100, - "width": 100, - "align": "top", - "spacing": 50, - "scale": "best-fit" - }, - { - "type": "Container", - "spacing": 30, - "direction": "column", - "items": [ - { - "type": "Text", - "text": "${primaryText}", - "style": "textStyleBody", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - }, - { - "type": "Text", - "text": "${secondaryText}", - "style": "textStyleDetails", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - } - ] - }, - { - "type": "Text", - "text": "${tertiaryText}", - "style": "textStyleBody", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "textAlign": "right", - "maxLines": 1 - } - ] - } - ] - } - }, - "mainTemplate": { - "parameters": [ - "payload" - ], - "item": [ - { - "type": "Container", - "id": "BookCabSimpleDialogAPL", - "items": [ - { - "type": "TouchWrapper", - "onPress": { - "type": "SendEvent", - "arguments": [ - "delegateToColtraneOld" - ] - }, - "item": { - "type": "Text", - "id": "BookCabSimpleDialogAPL", - "paddingTop": "100", - "paddingLeft": "100", - "color": "green", - "size": 50, - "text": "which date ?" - } - } - ] - } - ] - } - } \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/display/confirm_weather_apla_display/document.json b/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/display/confirm_weather_apla_display/document.json deleted file mode 100644 index 1974945a..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/display/confirm_weather_apla_display/document.json +++ /dev/null @@ -1,412 +0,0 @@ -{ - "type": "APL", - "version": "1.1", - "settings": {}, - "theme": "dark", - "import": [ - { - "name": "alexa-layouts", - "version": "1.0.0" - } - ], - "resources": [ - { - "description": "Stock color for the light theme", - "colors": { - "colorTextPrimary": "#151920" - } - }, - { - "description": "Stock color for the dark theme", - "when": "${viewport.theme == 'dark'}", - "colors": { - "colorTextPrimary": "#f0f1ef" - } - }, - { - "description": "Standard font sizes", - "dimensions": { - "textSizeBody": 48, - "textSizePrimary": 27, - "textSizeSecondary": 23, - "textSizeDetails": 20, - "textSizeSecondaryHint": 25 - } - }, - { - "description": "Common spacing values", - "dimensions": { - "spacingThin": 6, - "spacingSmall": 12, - "spacingMedium": 24, - "spacingLarge": 48, - "spacingExtraLarge": 72 - } - }, - { - "description": "Common margins and padding", - "dimensions": { - "marginTop": 40, - "marginLeft": 60, - "marginRight": 60, - "marginBottom": 40 - } - } - ], - "styles": { - "textStyleBase": { - "description": "Base font description; set color", - "values": [ - { - "color": "@colorTextPrimary" - } - ] - }, - "textStyleBase0": { - "description": "Thin version of basic font", - "extend": "textStyleBase", - "values": { - "fontWeight": "100" - } - }, - "textStyleBase1": { - "description": "Light version of basic font", - "extend": "textStyleBase", - "values": { - "fontWeight": "300" - } - }, - "textStyleBase2": { - "description": "Regular version of basic font", - "extend": "textStyleBase", - "values": { - "fontWeight": "500" - } - }, - "mixinBody": { - "values": { - "fontSize": "@textSizeBody" - } - }, - "mixinPrimary": { - "values": { - "fontSize": "@textSizePrimary" - } - }, - "mixinDetails": { - "values": { - "fontSize": "@textSizeDetails" - } - }, - "mixinSecondary": { - "values": { - "fontSize": "@textSizeSecondary" - } - }, - "textStylePrimary": { - "extend": [ - "textStyleBase1", - "mixinPrimary" - ] - }, - "textStyleSecondary": { - "extend": [ - "textStyleBase0", - "mixinSecondary" - ] - }, - "textStyleBody": { - "extend": [ - "textStyleBase1", - "mixinBody" - ] - }, - "textStyleSecondaryHint": { - "values": { - "fontFamily": "Bookerly", - "fontStyle": "italic", - "fontSize": "@textSizeSecondaryHint", - "color": "@colorTextPrimary" - } - }, - "textStyleDetails": { - "extend": [ - "textStyleBase2", - "mixinDetails" - ] - } - }, - "onMount": [], - "graphics": {}, - "commands": {}, - "layouts": { - "ListTemplate1": { - "parameters": [ - "backgroundImage", - "title", - "logo", - "hintText", - "listData" - ], - "item": [ - { - "type": "Container", - "width": "100vw", - "height": "100vh", - "direction": "column", - "items": [ - { - "type": "Image", - "source": "${backgroundImage}", - "scale": "best-fill", - "width": "100vw", - "height": "100vh", - "position": "absolute" - }, - { - "type": "AlexaHeader", - "headerTitle": "${title}", - "headerAttributionImage": "${logo}" - }, - { - "type": "Sequence", - "grow": 1, - "height": "80vh", - "scrollDirection": "vertical", - "paddingLeft": "@marginLeft", - "paddingRight": "@marginRight", - "data": "${listData}", - "numbered": true, - "items": [ - { - "type": "VerticalListItem", - "image": "${data.image.sources[0].url}", - "primaryText": "${data.textContent.primaryText.text}", - "secondaryText": "${data.textContent.secondaryText.text}", - "tertiaryText": "${data.textContent.tertiaryText.text}" - } - ] - } - ] - } - ] - }, - "VerticalListItem": { - "parameters": [ - "primaryText", - "secondaryText", - "tertiaryText", - "image" - ], - "item": [ - { - "when": "${viewport.shape == 'round'}", - "type": "Container", - "direction": "row", - "height": 200, - "width": 500, - "alignItems": "center", - "items": [ - { - "type": "Text", - "text": "${ordinal}", - "paddingBottom": "20dp", - "color": "white", - "spacing": "5dp" - }, - { - "type": "Image", - "when": "${image}", - "source": "${image}", - "height": 150, - "width": 150, - "spacing": 15, - "scale": "best-fit", - "align": "top" - }, - { - "type": "Container", - "direction": "column", - "spacing": 25, - "items": [ - { - "type": "Text", - "text": "${primaryText}", - "style": "textStyleDetail", - "grow": 1, - "shrink": 1, - "fontWeight": "300", - "maxLines": 1 - }, - { - "type": "Text", - "text": "${secondaryText}", - "style": "textStyleCaption", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - }, - { - "type": "Text", - "text": "${tertiaryText}", - "style": "textStyleDetails", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - } - ] - } - ] - }, - { - "type": "Container", - "direction": "row", - "height": 125, - "width": 800, - "alignItems": "center", - "items": [ - { - "type": "Text", - "text": "${ordinal}", - "paddingBottom": "20dp", - "color": "white", - "spacing": "5dp" - }, - { - "type": "Image", - "when": "${image}", - "source": "${image}", - "height": 100, - "width": 100, - "align": "top", - "spacing": 50, - "scale": "best-fit" - }, - { - "type": "Container", - "spacing": 30, - "direction": "column", - "items": [ - { - "type": "Text", - "text": "${primaryText}", - "style": "textStyleBody", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - }, - { - "type": "Text", - "text": "${secondaryText}", - "style": "textStyleDetails", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - } - ] - }, - { - "type": "Text", - "text": "${tertiaryText}", - "style": "textStyleBody", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "textAlign": "right", - "maxLines": 1 - } - ] - } - ] - } - }, - "mainTemplate": { - "parameters": [ - "payload" - ], - "item": [ - { - "type": "Container", - "id": "BookCabSimpleDialogAPL", - "items": [ - { - "type": "TouchWrapper", - "onPress": { - "type": "SendEvent", - "arguments": [ - "delegateToSkillNew" - ] - }, - "item": { - "type": "Text", - "id": "BookCabSimpleDialogAPL", - "paddingTop": "100", - "paddingLeft": "100", - "color": "green", - "size": 50, - "text": "delegateToSkillNew" - } - }, - { - "type": "TouchWrapper", - "onPress": { - "type": "SendEvent", - "arguments": [ - "delegateToSkillOld" - ] - }, - "item": { - "type": "Text", - "id": "BookCabSimpleDialogAPL", - "paddingTop": "100", - "paddingLeft": "100", - "color": "green", - "size": 50, - "text": "delegateToSkillOld" - } - }, - { - "type": "TouchWrapper", - "onPress": { - "type": "SendEvent", - "arguments": [ - "delegateToColtraneNew" - ] - }, - "item": { - "type": "Text", - "id": "BookCabSimpleDialogAPL", - "paddingTop": "100", - "paddingLeft": "100", - "color": "green", - "size": 50, - "text": "delegateToColtraneNew" - } - }, - { - "type": "TouchWrapper", - "onPress": { - "type": "SendEvent", - "arguments": [ - "delegateToColtraneOld" - ] - }, - "item": { - "type": "Text", - "id": "BookCabSimpleDialogAPL", - "paddingTop": "100", - "paddingLeft": "100", - "color": "green", - "size": 50, - "text": "delegateToColtraneOld" - } - } - ] - } - ] - } -} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/display/request_city_apl_display/document.json b/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/display/request_city_apl_display/document.json deleted file mode 100644 index 741e1a5f..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/display/request_city_apl_display/document.json +++ /dev/null @@ -1,358 +0,0 @@ -{ - "type": "APL", - "version": "1.1", - "settings": {}, - "theme": "dark", - "import": [ - { - "name": "alexa-layouts", - "version": "1.0.0" - } - ], - "resources": [ - { - "description": "Stock color for the light theme", - "colors": { - "colorTextPrimary": "#151920" - } - }, - { - "description": "Stock color for the dark theme", - "when": "${viewport.theme == 'dark'}", - "colors": { - "colorTextPrimary": "#f0f1ef" - } - }, - { - "description": "Standard font sizes", - "dimensions": { - "textSizeBody": 48, - "textSizePrimary": 27, - "textSizeSecondary": 23, - "textSizeDetails": 20, - "textSizeSecondaryHint": 25 - } - }, - { - "description": "Common spacing values", - "dimensions": { - "spacingThin": 6, - "spacingSmall": 12, - "spacingMedium": 24, - "spacingLarge": 48, - "spacingExtraLarge": 72 - } - }, - { - "description": "Common margins and padding", - "dimensions": { - "marginTop": 40, - "marginLeft": 60, - "marginRight": 60, - "marginBottom": 40 - } - } - ], - "styles": { - "textStyleBase": { - "description": "Base font description; set color", - "values": [ - { - "color": "@colorTextPrimary" - } - ] - }, - "textStyleBase0": { - "description": "Thin version of basic font", - "extend": "textStyleBase", - "values": { - "fontWeight": "100" - } - }, - "textStyleBase1": { - "description": "Light version of basic font", - "extend": "textStyleBase", - "values": { - "fontWeight": "300" - } - }, - "textStyleBase2": { - "description": "Regular version of basic font", - "extend": "textStyleBase", - "values": { - "fontWeight": "500" - } - }, - "mixinBody": { - "values": { - "fontSize": "@textSizeBody" - } - }, - "mixinPrimary": { - "values": { - "fontSize": "@textSizePrimary" - } - }, - "mixinDetails": { - "values": { - "fontSize": "@textSizeDetails" - } - }, - "mixinSecondary": { - "values": { - "fontSize": "@textSizeSecondary" - } - }, - "textStylePrimary": { - "extend": [ - "textStyleBase1", - "mixinPrimary" - ] - }, - "textStyleSecondary": { - "extend": [ - "textStyleBase0", - "mixinSecondary" - ] - }, - "textStyleBody": { - "extend": [ - "textStyleBase1", - "mixinBody" - ] - }, - "textStyleSecondaryHint": { - "values": { - "fontFamily": "Bookerly", - "fontStyle": "italic", - "fontSize": "@textSizeSecondaryHint", - "color": "@colorTextPrimary" - } - }, - "textStyleDetails": { - "extend": [ - "textStyleBase2", - "mixinDetails" - ] - } - }, - "onMount": [], - "graphics": {}, - "commands": {}, - "layouts": { - "ListTemplate1": { - "parameters": [ - "backgroundImage", - "title", - "logo", - "hintText", - "listData" - ], - "item": [ - { - "type": "Container", - "width": "100vw", - "height": "100vh", - "direction": "column", - "items": [ - { - "type": "Image", - "source": "${backgroundImage}", - "scale": "best-fill", - "width": "100vw", - "height": "100vh", - "position": "absolute" - }, - { - "type": "AlexaHeader", - "headerTitle": "${title}", - "headerAttributionImage": "${logo}" - }, - { - "type": "Sequence", - "grow": 1, - "height": "80vh", - "scrollDirection": "vertical", - "paddingLeft": "@marginLeft", - "paddingRight": "@marginRight", - "data": "${listData}", - "numbered": true, - "items": [ - { - "type": "VerticalListItem", - "image": "${data.image.sources[0].url}", - "primaryText": "${data.textContent.primaryText.text}", - "secondaryText": "${data.textContent.secondaryText.text}", - "tertiaryText": "${data.textContent.tertiaryText.text}" - } - ] - } - ] - } - ] - }, - "VerticalListItem": { - "parameters": [ - "primaryText", - "secondaryText", - "tertiaryText", - "image" - ], - "item": [ - { - "when": "${viewport.shape == 'round'}", - "type": "Container", - "direction": "row", - "height": 200, - "width": 500, - "alignItems": "center", - "items": [ - { - "type": "Text", - "text": "${ordinal}", - "paddingBottom": "20dp", - "color": "white", - "spacing": "5dp" - }, - { - "type": "Image", - "when": "${image}", - "source": "${image}", - "height": 150, - "width": 150, - "spacing": 15, - "scale": "best-fit", - "align": "top" - }, - { - "type": "Container", - "direction": "column", - "spacing": 25, - "items": [ - { - "type": "Text", - "text": "${primaryText}", - "style": "textStyleDetail", - "grow": 1, - "shrink": 1, - "fontWeight": "300", - "maxLines": 1 - }, - { - "type": "Text", - "text": "${secondaryText}", - "style": "textStyleCaption", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - }, - { - "type": "Text", - "text": "${tertiaryText}", - "style": "textStyleDetails", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - } - ] - } - ] - }, - { - "type": "Container", - "direction": "row", - "height": 125, - "width": 800, - "alignItems": "center", - "items": [ - { - "type": "Text", - "text": "${ordinal}", - "paddingBottom": "20dp", - "color": "white", - "spacing": "5dp" - }, - { - "type": "Image", - "when": "${image}", - "source": "${image}", - "height": 100, - "width": 100, - "align": "top", - "spacing": 50, - "scale": "best-fit" - }, - { - "type": "Container", - "spacing": 30, - "direction": "column", - "items": [ - { - "type": "Text", - "text": "${primaryText}", - "style": "textStyleBody", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - }, - { - "type": "Text", - "text": "${secondaryText}", - "style": "textStyleDetails", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - } - ] - }, - { - "type": "Text", - "text": "${tertiaryText}", - "style": "textStyleBody", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "textAlign": "right", - "maxLines": 1 - } - ] - } - ] - } - }, - "mainTemplate": { - "parameters": [ - "payload" - ], - "item": [ - { - "type": "Container", - "id": "BookCabSimpleDialogAPL", - "items": [ - { - "type": "TouchWrapper", - "onPress": { - "type": "SendEvent", - "arguments": [ - "delegateToColtraneOld" - ] - }, - "item": { - "type": "Text", - "id": "BookCabSimpleDialogAPL", - "paddingTop": "100", - "paddingLeft": "100", - "color": "green", - "size": 50, - "text": "which city ?" - } - } - ] - } - ] - } -} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/display/request_date_apl_display/document.json b/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/display/request_date_apl_display/document.json deleted file mode 100644 index 9ff71e5c..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/display/request_date_apl_display/document.json +++ /dev/null @@ -1,358 +0,0 @@ -{ - "type": "APL", - "version": "1.1", - "settings": {}, - "theme": "dark", - "import": [ - { - "name": "alexa-layouts", - "version": "1.0.0" - } - ], - "resources": [ - { - "description": "Stock color for the light theme", - "colors": { - "colorTextPrimary": "#151920" - } - }, - { - "description": "Stock color for the dark theme", - "when": "${viewport.theme == 'dark'}", - "colors": { - "colorTextPrimary": "#f0f1ef" - } - }, - { - "description": "Standard font sizes", - "dimensions": { - "textSizeBody": 48, - "textSizePrimary": 27, - "textSizeSecondary": 23, - "textSizeDetails": 20, - "textSizeSecondaryHint": 25 - } - }, - { - "description": "Common spacing values", - "dimensions": { - "spacingThin": 6, - "spacingSmall": 12, - "spacingMedium": 24, - "spacingLarge": 48, - "spacingExtraLarge": 72 - } - }, - { - "description": "Common margins and padding", - "dimensions": { - "marginTop": 40, - "marginLeft": 60, - "marginRight": 60, - "marginBottom": 40 - } - } - ], - "styles": { - "textStyleBase": { - "description": "Base font description; set color", - "values": [ - { - "color": "@colorTextPrimary" - } - ] - }, - "textStyleBase0": { - "description": "Thin version of basic font", - "extend": "textStyleBase", - "values": { - "fontWeight": "100" - } - }, - "textStyleBase1": { - "description": "Light version of basic font", - "extend": "textStyleBase", - "values": { - "fontWeight": "300" - } - }, - "textStyleBase2": { - "description": "Regular version of basic font", - "extend": "textStyleBase", - "values": { - "fontWeight": "500" - } - }, - "mixinBody": { - "values": { - "fontSize": "@textSizeBody" - } - }, - "mixinPrimary": { - "values": { - "fontSize": "@textSizePrimary" - } - }, - "mixinDetails": { - "values": { - "fontSize": "@textSizeDetails" - } - }, - "mixinSecondary": { - "values": { - "fontSize": "@textSizeSecondary" - } - }, - "textStylePrimary": { - "extend": [ - "textStyleBase1", - "mixinPrimary" - ] - }, - "textStyleSecondary": { - "extend": [ - "textStyleBase0", - "mixinSecondary" - ] - }, - "textStyleBody": { - "extend": [ - "textStyleBase1", - "mixinBody" - ] - }, - "textStyleSecondaryHint": { - "values": { - "fontFamily": "Bookerly", - "fontStyle": "italic", - "fontSize": "@textSizeSecondaryHint", - "color": "@colorTextPrimary" - } - }, - "textStyleDetails": { - "extend": [ - "textStyleBase2", - "mixinDetails" - ] - } - }, - "onMount": [], - "graphics": {}, - "commands": {}, - "layouts": { - "ListTemplate1": { - "parameters": [ - "backgroundImage", - "title", - "logo", - "hintText", - "listData" - ], - "item": [ - { - "type": "Container", - "width": "100vw", - "height": "100vh", - "direction": "column", - "items": [ - { - "type": "Image", - "source": "${backgroundImage}", - "scale": "best-fill", - "width": "100vw", - "height": "100vh", - "position": "absolute" - }, - { - "type": "AlexaHeader", - "headerTitle": "${title}", - "headerAttributionImage": "${logo}" - }, - { - "type": "Sequence", - "grow": 1, - "height": "80vh", - "scrollDirection": "vertical", - "paddingLeft": "@marginLeft", - "paddingRight": "@marginRight", - "data": "${listData}", - "numbered": true, - "items": [ - { - "type": "VerticalListItem", - "image": "${data.image.sources[0].url}", - "primaryText": "${data.textContent.primaryText.text}", - "secondaryText": "${data.textContent.secondaryText.text}", - "tertiaryText": "${data.textContent.tertiaryText.text}" - } - ] - } - ] - } - ] - }, - "VerticalListItem": { - "parameters": [ - "primaryText", - "secondaryText", - "tertiaryText", - "image" - ], - "item": [ - { - "when": "${viewport.shape == 'round'}", - "type": "Container", - "direction": "row", - "height": 200, - "width": 500, - "alignItems": "center", - "items": [ - { - "type": "Text", - "text": "${ordinal}", - "paddingBottom": "20dp", - "color": "white", - "spacing": "5dp" - }, - { - "type": "Image", - "when": "${image}", - "source": "${image}", - "height": 150, - "width": 150, - "spacing": 15, - "scale": "best-fit", - "align": "top" - }, - { - "type": "Container", - "direction": "column", - "spacing": 25, - "items": [ - { - "type": "Text", - "text": "${primaryText}", - "style": "textStyleDetail", - "grow": 1, - "shrink": 1, - "fontWeight": "300", - "maxLines": 1 - }, - { - "type": "Text", - "text": "${secondaryText}", - "style": "textStyleCaption", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - }, - { - "type": "Text", - "text": "${tertiaryText}", - "style": "textStyleDetails", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - } - ] - } - ] - }, - { - "type": "Container", - "direction": "row", - "height": 125, - "width": 800, - "alignItems": "center", - "items": [ - { - "type": "Text", - "text": "${ordinal}", - "paddingBottom": "20dp", - "color": "white", - "spacing": "5dp" - }, - { - "type": "Image", - "when": "${image}", - "source": "${image}", - "height": 100, - "width": 100, - "align": "top", - "spacing": 50, - "scale": "best-fit" - }, - { - "type": "Container", - "spacing": 30, - "direction": "column", - "items": [ - { - "type": "Text", - "text": "${primaryText}", - "style": "textStyleBody", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - }, - { - "type": "Text", - "text": "${secondaryText}", - "style": "textStyleDetails", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - } - ] - }, - { - "type": "Text", - "text": "${tertiaryText}", - "style": "textStyleBody", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "textAlign": "right", - "maxLines": 1 - } - ] - } - ] - } - }, - "mainTemplate": { - "parameters": [ - "payload" - ], - "item": [ - { - "type": "Container", - "id": "BookCabSimpleDialogAPL", - "items": [ - { - "type": "TouchWrapper", - "onPress": { - "type": "SendEvent", - "arguments": [ - "delegateToColtraneOld" - ] - }, - "item": { - "type": "Text", - "id": "BookCabSimpleDialogAPL", - "paddingTop": "100", - "paddingLeft": "100", - "color": "green", - "size": 50, - "text": "which date ?" - } - } - ] - } - ] - } - } \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/display/weather_success_apl_display/document.json b/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/display/weather_success_apl_display/document.json deleted file mode 100644 index 1974945a..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/display/weather_success_apl_display/document.json +++ /dev/null @@ -1,412 +0,0 @@ -{ - "type": "APL", - "version": "1.1", - "settings": {}, - "theme": "dark", - "import": [ - { - "name": "alexa-layouts", - "version": "1.0.0" - } - ], - "resources": [ - { - "description": "Stock color for the light theme", - "colors": { - "colorTextPrimary": "#151920" - } - }, - { - "description": "Stock color for the dark theme", - "when": "${viewport.theme == 'dark'}", - "colors": { - "colorTextPrimary": "#f0f1ef" - } - }, - { - "description": "Standard font sizes", - "dimensions": { - "textSizeBody": 48, - "textSizePrimary": 27, - "textSizeSecondary": 23, - "textSizeDetails": 20, - "textSizeSecondaryHint": 25 - } - }, - { - "description": "Common spacing values", - "dimensions": { - "spacingThin": 6, - "spacingSmall": 12, - "spacingMedium": 24, - "spacingLarge": 48, - "spacingExtraLarge": 72 - } - }, - { - "description": "Common margins and padding", - "dimensions": { - "marginTop": 40, - "marginLeft": 60, - "marginRight": 60, - "marginBottom": 40 - } - } - ], - "styles": { - "textStyleBase": { - "description": "Base font description; set color", - "values": [ - { - "color": "@colorTextPrimary" - } - ] - }, - "textStyleBase0": { - "description": "Thin version of basic font", - "extend": "textStyleBase", - "values": { - "fontWeight": "100" - } - }, - "textStyleBase1": { - "description": "Light version of basic font", - "extend": "textStyleBase", - "values": { - "fontWeight": "300" - } - }, - "textStyleBase2": { - "description": "Regular version of basic font", - "extend": "textStyleBase", - "values": { - "fontWeight": "500" - } - }, - "mixinBody": { - "values": { - "fontSize": "@textSizeBody" - } - }, - "mixinPrimary": { - "values": { - "fontSize": "@textSizePrimary" - } - }, - "mixinDetails": { - "values": { - "fontSize": "@textSizeDetails" - } - }, - "mixinSecondary": { - "values": { - "fontSize": "@textSizeSecondary" - } - }, - "textStylePrimary": { - "extend": [ - "textStyleBase1", - "mixinPrimary" - ] - }, - "textStyleSecondary": { - "extend": [ - "textStyleBase0", - "mixinSecondary" - ] - }, - "textStyleBody": { - "extend": [ - "textStyleBase1", - "mixinBody" - ] - }, - "textStyleSecondaryHint": { - "values": { - "fontFamily": "Bookerly", - "fontStyle": "italic", - "fontSize": "@textSizeSecondaryHint", - "color": "@colorTextPrimary" - } - }, - "textStyleDetails": { - "extend": [ - "textStyleBase2", - "mixinDetails" - ] - } - }, - "onMount": [], - "graphics": {}, - "commands": {}, - "layouts": { - "ListTemplate1": { - "parameters": [ - "backgroundImage", - "title", - "logo", - "hintText", - "listData" - ], - "item": [ - { - "type": "Container", - "width": "100vw", - "height": "100vh", - "direction": "column", - "items": [ - { - "type": "Image", - "source": "${backgroundImage}", - "scale": "best-fill", - "width": "100vw", - "height": "100vh", - "position": "absolute" - }, - { - "type": "AlexaHeader", - "headerTitle": "${title}", - "headerAttributionImage": "${logo}" - }, - { - "type": "Sequence", - "grow": 1, - "height": "80vh", - "scrollDirection": "vertical", - "paddingLeft": "@marginLeft", - "paddingRight": "@marginRight", - "data": "${listData}", - "numbered": true, - "items": [ - { - "type": "VerticalListItem", - "image": "${data.image.sources[0].url}", - "primaryText": "${data.textContent.primaryText.text}", - "secondaryText": "${data.textContent.secondaryText.text}", - "tertiaryText": "${data.textContent.tertiaryText.text}" - } - ] - } - ] - } - ] - }, - "VerticalListItem": { - "parameters": [ - "primaryText", - "secondaryText", - "tertiaryText", - "image" - ], - "item": [ - { - "when": "${viewport.shape == 'round'}", - "type": "Container", - "direction": "row", - "height": 200, - "width": 500, - "alignItems": "center", - "items": [ - { - "type": "Text", - "text": "${ordinal}", - "paddingBottom": "20dp", - "color": "white", - "spacing": "5dp" - }, - { - "type": "Image", - "when": "${image}", - "source": "${image}", - "height": 150, - "width": 150, - "spacing": 15, - "scale": "best-fit", - "align": "top" - }, - { - "type": "Container", - "direction": "column", - "spacing": 25, - "items": [ - { - "type": "Text", - "text": "${primaryText}", - "style": "textStyleDetail", - "grow": 1, - "shrink": 1, - "fontWeight": "300", - "maxLines": 1 - }, - { - "type": "Text", - "text": "${secondaryText}", - "style": "textStyleCaption", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - }, - { - "type": "Text", - "text": "${tertiaryText}", - "style": "textStyleDetails", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - } - ] - } - ] - }, - { - "type": "Container", - "direction": "row", - "height": 125, - "width": 800, - "alignItems": "center", - "items": [ - { - "type": "Text", - "text": "${ordinal}", - "paddingBottom": "20dp", - "color": "white", - "spacing": "5dp" - }, - { - "type": "Image", - "when": "${image}", - "source": "${image}", - "height": 100, - "width": 100, - "align": "top", - "spacing": 50, - "scale": "best-fit" - }, - { - "type": "Container", - "spacing": 30, - "direction": "column", - "items": [ - { - "type": "Text", - "text": "${primaryText}", - "style": "textStyleBody", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - }, - { - "type": "Text", - "text": "${secondaryText}", - "style": "textStyleDetails", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - } - ] - }, - { - "type": "Text", - "text": "${tertiaryText}", - "style": "textStyleBody", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "textAlign": "right", - "maxLines": 1 - } - ] - } - ] - } - }, - "mainTemplate": { - "parameters": [ - "payload" - ], - "item": [ - { - "type": "Container", - "id": "BookCabSimpleDialogAPL", - "items": [ - { - "type": "TouchWrapper", - "onPress": { - "type": "SendEvent", - "arguments": [ - "delegateToSkillNew" - ] - }, - "item": { - "type": "Text", - "id": "BookCabSimpleDialogAPL", - "paddingTop": "100", - "paddingLeft": "100", - "color": "green", - "size": 50, - "text": "delegateToSkillNew" - } - }, - { - "type": "TouchWrapper", - "onPress": { - "type": "SendEvent", - "arguments": [ - "delegateToSkillOld" - ] - }, - "item": { - "type": "Text", - "id": "BookCabSimpleDialogAPL", - "paddingTop": "100", - "paddingLeft": "100", - "color": "green", - "size": 50, - "text": "delegateToSkillOld" - } - }, - { - "type": "TouchWrapper", - "onPress": { - "type": "SendEvent", - "arguments": [ - "delegateToColtraneNew" - ] - }, - "item": { - "type": "Text", - "id": "BookCabSimpleDialogAPL", - "paddingTop": "100", - "paddingLeft": "100", - "color": "green", - "size": 50, - "text": "delegateToColtraneNew" - } - }, - { - "type": "TouchWrapper", - "onPress": { - "type": "SendEvent", - "arguments": [ - "delegateToColtraneOld" - ] - }, - "item": { - "type": "Text", - "id": "BookCabSimpleDialogAPL", - "paddingTop": "100", - "paddingLeft": "100", - "color": "green", - "size": 50, - "text": "delegateToColtraneOld" - } - } - ] - } - ] - } -} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/AlexaConversationsBye/document.json b/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/AlexaConversationsBye/document.json deleted file mode 100644 index bde5ee56..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/AlexaConversationsBye/document.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": [ - "payload" - ], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "Bye.", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/AlexaConversationsNotifyFailure/document.json b/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/AlexaConversationsNotifyFailure/document.json deleted file mode 100644 index c31fe279..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/AlexaConversationsNotifyFailure/document.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": [ - "payload" - ], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "Sorry, there was an error in the request.", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/AlexaConversationsOutOfDomain/document.json b/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/AlexaConversationsOutOfDomain/document.json deleted file mode 100644 index 3796d4d5..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/AlexaConversationsOutOfDomain/document.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": [ - "payload" - ], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "Sorry, I don't understand.", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/AlexaConversationsProvideHelp/document.json b/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/AlexaConversationsProvideHelp/document.json deleted file mode 100644 index 13b27c11..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/AlexaConversationsProvideHelp/document.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": [ - "payload" - ], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "I can give you the weather report. Just say \"what's the weather\" to start.", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/AlexaConversationsRequestMore/document.json b/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/AlexaConversationsRequestMore/document.json deleted file mode 100644 index fb3e56ae..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/AlexaConversationsRequestMore/document.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": [ - "payload" - ], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "What do you want to do.", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/AlexaConversationsThankYou/document.json b/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/AlexaConversationsThankYou/document.json deleted file mode 100644 index 2112f02e..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/AlexaConversationsThankYou/document.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": [ - "payload" - ], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "Thank you.", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/AlexaConversationsWelcome/document.json b/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/AlexaConversationsWelcome/document.json deleted file mode 100644 index aeacaae2..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/AlexaConversationsWelcome/document.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": [ - "payload" - ], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "Welcome to the weather bot, I can give you the weather report. Just say \"what's the weather\" to start.", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/AlexaConversationsYouAreWelcome/document.json b/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/AlexaConversationsYouAreWelcome/document.json deleted file mode 100644 index 7ade07ba..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/AlexaConversationsYouAreWelcome/document.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": [ - "payload" - ], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "You are welcome.", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/alexa_prize_preconditions_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/alexa_prize_preconditions_apla/document.json deleted file mode 100644 index e50c4e94..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/alexa_prize_preconditions_apla/document.json +++ /dev/null @@ -1,91 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": [ - "payload" - ], - "item": { - "type": "Selector", - "description": "Selects the speech response to render when device/locale is not supported", - "items": [ - { - "when": "${payload.result.isDeviceSupported == 0}", - "type": "Speech", - "contentType": "text", - "content": "Sorry, Alexa Prize is not available on this device.", - "description": "" - }, - { - "when": "${payload.result.isLocaleSupported == 0}", - "type": "Speech", - "contentType": "text", - "content": "Sorry, Alexa Prize is not available in your locale.", - "description": "" - }, - { - "when": "${payload.result.isSocialBotAvailable == 0}", - "type": "Speech", - "contentType": "text", - "content": "Right now the Alexa Prize socialbots are busy. Please try again soon and help the university students in their competition to advance conversational A I.", - "description": "" - }, - { - "when": "${payload.result.isAlexaPrizeEnabled == 0}", - "type": "Speech", - "contentType": "text", - "content": "Alexa Prize is currently disabled for this account. Please visit the skill store in the Alexa App to re-enable it.", - "description": "" - }, - { - "when": "${payload.result.isTopicBanned == 1}", - "type": "Speech", - "contentType": "text", - "content": "I’d rather not talk about that, but there’s lots of other things to chat about. Do you still wanna chat?", - "description": "The topic that user wants to talk about is banned, ask if they still want to chat about something else" - }, - { - "when": "${payload.result.isFalseWake == 1}", - "type": "Speech", - "contentType": "text", - "content": "Would you like to chat with an Alexa Prize socialbot?", - "description": "" - }, - { - "when": "${payload.result.handoffPromptOverride == 'HandOffConversationForFilming'}", - "type": "Speech", - "contentType": "text", - "content": "Welcome to the Finals of the Alexa Prize Socialbot Grand Challenge 3, a university competition to advance AI. I’ll get you a socialbot now.", - "description": "" - }, - { - "when": "${payload.result.handoffPromptOverride == 'HandOffConversationForFinals'}", - "type": "Speech", - "contentType": "text", - "content": "Welcome to the Alexa Prize Socialbot Grand Challenge 3: Grand Finale. Here’s one of the finalists.", - "description": "" - }, - { - "when": "${payload.result.handoffPromptOverride == 'HandOffConversationForRepeatUser'}", - "type": "Speech", - "contentType": "text", - "content": "Welcome to the Alexa Prize, a university competition to advance AI. It’s quarterfinals for these socialbots and your ratings help determine who makes it to the semifinals. I’ll get you a socialbot now. When you’re done, say stop, and I’ll ask you for your rating. Your conversation and feedback will be shared with the university to help the socialbots improve.", - "description": "" - }, - { - "when": "${payload.result.handoffPromptOverride == 'CancelHandoff'}", - "type": "Speech", - "contentType": "text", - "content": "Okay", - "description": "" - }, - { - "type": "Speech", - "contentType": "text", - "content": "Welcome to the Alexa Prize, a university competition to advance AI. It’s quarterfinals for these socialbots and your ratings help determine who makes it to the semifinals. I’ll get you a socialbot now. When you’re done, say stop, and I’ll ask you for your rating. Your conversation and feedback will be shared with the university to help the socialbots improve.", - "description": "This is the current default handoff prompt" - } - ] - } - } -} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/confirm_color_for_fruit_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/confirm_color_for_fruit_apla/document.json deleted file mode 100644 index 835d7a8e..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/confirm_color_for_fruit_apla/document.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": [ - "payload" - ], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "confirm color is ${payload.colorName} ? ", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/confirm_fruitName_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/confirm_fruitName_apla/document.json deleted file mode 100644 index 42d63adc..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/confirm_fruitName_apla/document.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": [ - "payload" - ], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "confirm fruit ${payload.fruitName} ? ", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/getEmployeePosition_success_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/getEmployeePosition_success_apla/document.json deleted file mode 100644 index 4f5794c0..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/getEmployeePosition_success_apla/document.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": [ - "payload" - ], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "${payload.result.name1} born on ${payload.result.a_dateOfBirth} with employee id ${payload.result.emplyee1id} , is an ${payload.result.position} ", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/no_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/no_apla/document.json deleted file mode 100644 index 76610fcc..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/no_apla/document.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": [ - "payload" - ], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "I'm sorry you didn't like it", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/nothing2_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/nothing2_apla/document.json deleted file mode 100644 index 98f7ebef..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/nothing2_apla/document.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": [ - "payload" - ], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "The number you gave us was not 3.", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/nothing_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/nothing_apla/document.json deleted file mode 100644 index 5272f2a9..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/nothing_apla/document.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": [ - "payload" - ], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "The number you gave us was 3.", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/numericfeedback_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/numericfeedback_apla/document.json deleted file mode 100644 index 5278049b..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/numericfeedback_apla/document.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": [ - "payload" - ], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [{ - "type": "Speech", - "contentType": "text", - "content": "Your random number was ${payload.num}. How did we do? Please give this interaction a rating between 1-5, where 5 is the highest rating", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - }] - } - } -} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/rating_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/rating_apla/document.json deleted file mode 100644 index 7d50a649..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/rating_apla/document.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": [ - "payload" - ], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "rating please?", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/requestArgs_request_fruitName_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/requestArgs_request_fruitName_apla/document.json deleted file mode 100644 index a27a7d1e..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/requestArgs_request_fruitName_apla/document.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": [ - "payload" - ], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "tell me the fruit name ?", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - }, - { - "type": "Speech", - "contentType": "text", - "content": "random slection tell me the fruit name ?", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/request_city_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/request_city_apla/document.json deleted file mode 100644 index 65c28562..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/request_city_apla/document.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": [ - "payload" - ], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "Which city?", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/request_city_date_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/request_city_date_apla/document.json deleted file mode 100644 index f685b93e..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/request_city_date_apla/document.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": [ - "payload" - ], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "Which city and for which date?", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/request_colorName_multiple_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/request_colorName_multiple_apla/document.json deleted file mode 100644 index 62911ca4..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/request_colorName_multiple_apla/document.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": [ - "payload" - ], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "which color?", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/request_date_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/request_date_apla/document.json deleted file mode 100644 index 3beebe7b..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/request_date_apla/document.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": [ - "payload" - ], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "Which date?", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/request_dob_getDate_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/request_dob_getDate_apla/document.json deleted file mode 100644 index cabe7441..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/request_dob_getDate_apla/document.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": [ - "payload" - ], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "SSML", - "content": "provide date?", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/request_getEmploeeID_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/request_getEmploeeID_apla/document.json deleted file mode 100644 index 7649453f..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/request_getEmploeeID_apla/document.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": [ - "payload" - ], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "SSML", - "content": "provide employee id?", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/request_name_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/request_name_apla/document.json deleted file mode 100644 index 8afc80bf..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/request_name_apla/document.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": [ - "payload" - ], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "SSML", - "content": "what is your cool name?", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/success_colorFruitAPI_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/success_colorFruitAPI_apla/document.json deleted file mode 100644 index 873e2711..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/success_colorFruitAPI_apla/document.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": [ - "payload" - ], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "price of an ${payload.result.fruitName} is free bucks ", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/success_fruitPriceAPI_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/success_fruitPriceAPI_apla/document.json deleted file mode 100644 index b4a7272b..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/success_fruitPriceAPI_apla/document.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": [ - "payload" - ], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "price of an ${payload.result.fruitName} is ${payload.result.price} bucks ", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/weather_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/weather_apla/document.json deleted file mode 100644 index 4c5d2883..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/weather_apla/document.json +++ /dev/null @@ -1,29 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": [ - "payload" - ], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "when": "${payload.weatherResult != null && payload.weatherResult.cityName != null && payload.weatherResult.highTemp != null && payload.weatherResult.lowTemp != null}", - "type": "Speech", - "contentType": "text", - "content": "In ${payload.weatherResult.cityName}, it's a high of ${payload.weatherResult.highTemp} degrees and a low of ${payload.weatherResult.lowTemp} degrees.", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - }, - { - "when": "${payload.weatherResult != null && payload.weatherResult.cityNameChanged != null && payload.weatherResult.highTemp != null && payload.weatherResult.lowTemp != null}", - "type": "Speech", - "contentType": "text", - "content": "In ${payload.weatherResult.cityName}, it's a high of ${payload.weatherResult.highTemp} degrees and a low of ${payload.weatherResult.lowTemp} degrees.", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/yes_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/yes_apla/document.json deleted file mode 100644 index 021dec67..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/yes_apla/document.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": [ - "payload" - ], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "Nice! Glad you like it", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/yesnofeedback_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/yesnofeedback_apla/document.json deleted file mode 100644 index f0242d89..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/response/prompts/yesnofeedback_apla/document.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": [ - "payload" - ], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "Your number was ${payload.num}. Is this a good number, yes or no?", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/skill.json b/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/skill.json deleted file mode 100644 index 122472ef..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-6/skill-package/skill.json +++ /dev/null @@ -1,97 +0,0 @@ -{ - "manifest": { - "apis": { - "custom": { - "dialogManagement": { - "dialogManagers": [ - { - "type": "AMAZON.Conversations" - } - ], - "sessionStartDelegationStrategy": { - "target": "AMAZON.Conversations" - } - }, - "endpoint": { - "uri": "arn:aws:lambda:us-west-2:267006587462:function:ramansatTestFunction" - }, - "interfaces": [ - { - "supportedViewports": [ - { - "maxHeight": 480, - "maxWidth": 480, - "minHeight": 480, - "minWidth": 480, - "mode": "HUB", - "shape": "ROUND" - }, - { - "maxHeight": 600, - "maxWidth": 1024, - "minHeight": 600, - "minWidth": 1024, - "mode": "HUB", - "shape": "RECTANGLE" - }, - { - "maxHeight": 800, - "maxWidth": 1280, - "minHeight": 800, - "minWidth": 1280, - "mode": "HUB", - "shape": "RECTANGLE" - }, - { - "maxHeight": 540, - "maxWidth": 960, - "minHeight": 540, - "minWidth": 960, - "mode": "TV", - "shape": "RECTANGLE" - } - ], - "type": "ALEXA_PRESENTATION_APL" - } - ], - "regions": { - "NA": { - "endpoint": { - "uri": "arn:aws:lambda:us-west-2:267006587462:function:ramansatTestFunction" - } - }, - "EU": { - "endpoint": { - "uri": "arn:aws:lambda:us-west-2:267006587462:function:ramansatTestFunction" - } - }, - "FE": { - "endpoint": { - "uri": "arn:aws:lambda:us-west-2:267006587462:function:ramansatTestFunction" - } - } - } - } - }, - "manifestVersion": "1.0", - "publishingInformation": { - "category": "KNOWLEDGE_AND_TRIVIA", - "distributionCountries": [], - "isAvailableWorldwide": true, - "locales": { - "en-US": { - "description": "Sample Full Description", - "examplePhrases": [ - "Alexa open hello world", - "hello", - "help" - ], - "keywords": [], - "name": "engineering test skill one_four", - "summary": "Sample Short Description" - } - }, - "testingInstructions": "Sample Testing Instructions." - } - } -} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-7/.ask/ask-states.json b/test/unit/fixture/dialog-evaluate/test-project-7/.ask/ask-states.json deleted file mode 100644 index 04b60573..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-7/.ask/ask-states.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "askcliStatesVersion": "2020-03-31", - "profiles": { - "default": { - "skillId": "amzn1.ask.skill.a39d8c76-9c33-4e1a-8d1f-7e99ba199551" - } - } -} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-7/ask-resources.json b/test/unit/fixture/dialog-evaluate/test-project-7/ask-resources.json deleted file mode 100644 index be9cb8d1..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-7/ask-resources.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "askcliResourcesVersion": "2020-03-31", - "profiles": { - "default": { - "skillMetadata": { - "src": "./skill-package" - } - } - } -} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/TestDataACDLi18n/deBye/document.json b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/TestDataACDLi18n/deBye/document.json deleted file mode 100644 index 5a2fc317..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/TestDataACDLi18n/deBye/document.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "APLA", - "version": "0.8", - "mainTemplate": { - "parameters": [ - "payload" - ], - "item": { - "type": "Selector", - "strategy": "randomItem", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "Tschüss satheesh" - } - ] - } - } -} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/TestDataACDLi18n/deHelp/document.json b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/TestDataACDLi18n/deHelp/document.json deleted file mode 100644 index bacc0deb..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/TestDataACDLi18n/deHelp/document.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "APLA", - "version": "0.8", - "mainTemplate": { - "parameters": [ - "payload" - ], - "item": { - "type": "Selector", - "strategy": "randomItem", - "description": "Change \u0027type\u0027 above to try different Selector Component Types like Sequencer", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "Hilfe leisten satheesh" - } - ] - } - } -} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/TestDataACDLi18n/deOutOfDomain/datasources/default.json b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/TestDataACDLi18n/deOutOfDomain/datasources/default.json deleted file mode 100644 index 9e26dfee..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/TestDataACDLi18n/deOutOfDomain/datasources/default.json +++ /dev/null @@ -1 +0,0 @@ -{} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/TestDataACDLi18n/deOutOfDomain/document.json b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/TestDataACDLi18n/deOutOfDomain/document.json deleted file mode 100644 index 6bd6148f..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/TestDataACDLi18n/deOutOfDomain/document.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "APLA", - "version": "0.8", - "mainTemplate": { - "parameters": [ - "payload" - ], - "item": { - "type": "Selector", - "strategy": "randomItem", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "Entschuldigung, ich verstehe Satheesh nicht" - } - ] - } - } -} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/TestDataACDLi18n/deRequireMore/document.json b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/TestDataACDLi18n/deRequireMore/document.json deleted file mode 100644 index 248b8172..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/TestDataACDLi18n/deRequireMore/document.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "APLA", - "version": "0.8", - "mainTemplate": { - "parameters": [ - "payload" - ], - "item": { - "type": "Selector", - "strategy": "randomItem", - "items": [ - { - "description": "This template is emitted after we deny an API. Since we only have one, this is functionally equivalent to needing to request the city again.", - "type": "Speech", - "contentType": "text", - "content": "mehr benötigen satheesh" - } - ] - } - } -} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/TestDataACDLi18n/deWelcome/document.json b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/TestDataACDLi18n/deWelcome/document.json deleted file mode 100644 index 6bd7db86..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/TestDataACDLi18n/deWelcome/document.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "APLA", - "version": "0.8", - "mainTemplate": { - "parameters": [ - "payload" - ], - "item": { - "type": "Selector", - "strategy": "randomItem", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "Willkommen meinen König Satheesh" - } - ] - } - } -} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/conversations/ALexaPrize.acdl b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/conversations/ALexaPrize.acdl deleted file mode 100644 index 086efb02..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/conversations/ALexaPrize.acdl +++ /dev/null @@ -1,203 +0,0 @@ -namespace com.alexaprize - -import com.amazon.alexa.ask.conversations.Affirm -import com.amazon.alexa.ask.conversations.Deny -import com.amazon.alexa.ask.conversations.Invoke -import com.amazon.alexa.ask.conversations.Notify -import com.amazon.alexa.ask.conversations.Offer -import com.amazon.alexa.ask.conversations.expect -import com.amazon.alexa.ask.conversations.response -import com.amazon.alexa.ask.conversations.utterances -import com.amazon.alexa.schema.Boolean -import com.amazon.alexa.schema.Nothing -import com.amazon.alexa.schema.String -import com.amazon.ask.types.builtins.AMAZON.NUMBER -import prompts.alexa_prize_preconditions_apla -import slotTypes.TopicType - -type ConversationDetails { - optional TopicType Topic -} - -letsChatEvent = utterances( - samples = [ - "let's chat", - "i want to chat", - "chat", - "talk", - "let's chat about {Topic}", - "i want to talk about {Topic}", - "can we talk about {Topic}" - ] -) - -affirmEvent = utterances( - samples = [ - "yes", - "yup", - "yeah", - "sure", - "alright" - ] -) - -denyEvent = utterances( - samples = [ - "no", - "nope", - "not really", - "not", - "naah" - ] -) - -type AlexaPrizePreconditions { - NUMBER isLocaleSupported - NUMBER isDeviceSupported - NUMBER isFalseWake - NUMBER isSocialBotAvailable - NUMBER isAlexaPrizeEnabled - NUMBER isTopicBanned - String handoffPromptOverride -} - -type AlexaPrizePreconditionsPayload { - AlexaPrizePreconditions result -} - -type HandoffResults { - String handoffPromptOverride -} - -type HandoffResultsPayload { - HandoffResults result -} - -action AlexaPrizePreconditions checkPreconditionsAndHandoff(TopicType Topic = nothing) - -action HandoffResults intentConfirmedHandoff() - -action HandoffResults intentDeniedHandoff() - -dialog Nothing AlexaPrizeDialog() { - sample { - preconditionsResult = checkPrecondition() - isHandoffPossible = (((preconditionsResult.isDeviceSupported == 1 && preconditionsResult.isLocaleSupported == 1) && preconditionsResult.isSocialBotAvailable == 1) && preconditionsResult.isAlexaPrizeEnabled == 1) - if (isHandoffPossible) { - isConfirmationNeeded = (preconditionsResult.isFalseWake == 1 || preconditionsResult.isTopicBanned == 1) - responses( - isConfirmationNeeded = isConfirmationNeeded, - preconditionsResult = preconditionsResult - ) - } else { - response( - response = alexa_prize_preconditions_apla, - act = Notify { - actionName = checkPreconditionsAndHandoff, - success = false - }, - payload = AlexaPrizePreconditionsPayload { - result = preconditionsResult - } - ) - } - } -} - -dialog AlexaPrizePreconditions checkPrecondition() { - sample { - chatRequest = expect( - act = Invoke, - event = letsChatEvent - ) - checkPreconditionsAndHandoff( - Topic = chatRequest.Topic - ) - } - sample { - expect( - act = Invoke, - event = letsChatEvent - ) - preconditionsResult = checkPreconditionsAndHandoff() - } -} - -dialog Nothing responses(Boolean isConfirmationNeeded, AlexaPrizePreconditions preconditionsResult) { - sample { - if (isConfirmationNeeded) { - handoffResult( - preconditionsResult = preconditionsResult - ) - } else { - response( - response = alexa_prize_preconditions_apla, - act = Notify { - actionName = checkPreconditionsAndHandoff - }, - payload = AlexaPrizePreconditionsPayload { - result = preconditionsResult - } - ) - } - } -} - -dialog Nothing handoffResult(AlexaPrizePreconditions preconditionsResult) { - sample { - response( - response = alexa_prize_preconditions_apla, - act = Notify { - actionName = checkPreconditionsAndHandoff - }, - nextAct = Offer { - actionName = intentConfirmedHandoff - }, - payload = AlexaPrizePreconditionsPayload { - result = preconditionsResult - } - ) - expect( - act = Affirm, - event = affirmEvent - ) - handoffResults = intentConfirmedHandoff() - response( - response = alexa_prize_preconditions_apla, - act = Notify { - actionName = intentConfirmedHandoff - }, - payload = HandoffResultsPayload { - result = handoffResults - } - ) - } - sample { - response( - response = alexa_prize_preconditions_apla, - act = Notify { - actionName = checkPreconditionsAndHandoff - }, - nextAct = Offer { - actionName = intentDeniedHandoff - }, - payload = AlexaPrizePreconditionsPayload { - result = preconditionsResult - } - ) - expect( - act = Deny, - event = denyEvent - ) - handoffResults = intentDeniedHandoff() - response( - response = alexa_prize_preconditions_apla, - act = Notify { - actionName = intentDeniedHandoff - }, - payload = HandoffResultsPayload { - result = handoffResults - } - ) - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/conversations/Dialog_NonDeployable.acdl b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/conversations/Dialog_NonDeployable.acdl deleted file mode 100644 index 90637c08..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/conversations/Dialog_NonDeployable.acdl +++ /dev/null @@ -1,79 +0,0 @@ -namespace dialogs_non_deployable - -import com.weatherbot.apis.* -import com.amazon.alexa.ask.conversations.Inform -import com.amazon.alexa.ask.conversations.Request -import com.amazon.alexa.ask.conversations.expect -import com.amazon.alexa.ask.conversations.response -import com.amazon.ask.types.builtins.AMAZON.DATE -import com.amazon.ask.types.builtins.AMAZON.NUMBER -import prompts.request_dob_getDate_apla -import prompts.request_getEmploeeID_apla -import prompts.request_name_apla -import slotTypes.complexNames -import types.complexResult -import com.weatherbot.utteracesets.* - -dialog complexNames getName() { - sample { - response( - response = request_name_apla, - act = Request { - arguments = [ - getEmployeeDetails.arguments.name1 - ] - } - ) - complexNamesReturn = expect( - act = Inform, - event = informComplexNameEvent - ) - complexNamesReturn.name - } -} - -dialog NUMBER getEmploeeID() { - sample { - response( - response = request_getEmploeeID_apla, - act = Request { - arguments = [ - getEmployeeDetails.arguments.emplyee1id - ] - } - ) - empID = expect( - act = Inform, - event = informEmployeeIDEvent - ) - empID.emplyee1id - } -} - -dialog DATE getDate() { - sample { - response( - response = request_dob_getDate_apla, - act = Request { - arguments = [ - getEmployeeDetails.arguments.a_dateOfBirth - ] - } - ) - dobEvent = expect( - act = Inform, - event = informDOBEvent - ) - dobEvent.a_dateOfBirth - } -} - -dialog complexResult a_getEmployeeDetails(complexNames name1, NUMBER emplyee1id, DATE a_dateOfBirth) { - sample { - complexResultEvent = getEmployeeDetails( - name1 = name1, - emplyee1id = emplyee1id, - a_dateOfBirth = a_dateOfBirth - ) - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/conversations/Dialogs_reusableDialogsUsage_NonDeployableDialogs.acdl b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/conversations/Dialogs_reusableDialogsUsage_NonDeployableDialogs.acdl deleted file mode 100644 index c1ffb111..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/conversations/Dialogs_reusableDialogsUsage_NonDeployableDialogs.acdl +++ /dev/null @@ -1,50 +0,0 @@ -namespace reusableDialogs.NonDeployableDialogs - -import com.weatherbot.apis.* -import com.amazon.alexa.ask.conversations.Invoke -import com.amazon.alexa.ask.conversations.Notify -import com.amazon.alexa.ask.conversations.expect -import com.amazon.alexa.ask.conversations.response -import com.amazon.alexa.schema.Nothing -import dialogs_non_deployable.a_getEmployeeDetails -import dialogs_non_deployable.getDate -import dialogs_non_deployable.getEmploeeID -import dialogs_non_deployable.getName -import prompts.getEmployeePosition_success_apla -import types.complexResult -import com.weatherbot.utteracesets.* -import slotTypes.* -import prompts.* -import displays.* -import com.amazon.ask.types.builtins.AMAZON.* -import com.amazon.alexa.schema.* -import com.amazon.alexa.ask.conversations.* -type PayLoadresult { - complexResult result -} - -dialog Nothing dilaog_getEmployeePosition() { - sample { - expect( - act = Invoke, - event = who_are_you - ) - complexNamesEvent = getName() - NUMBEREvent = getEmploeeID() - DATEEvent = getDate() - resultOne = a_getEmployeeDetails( - name1 = complexNamesEvent, - emplyee1id = NUMBEREvent, - a_dateOfBirth = DATEEvent - ) - response( - response = getEmployeePosition_success_apla, - act = Notify { - actionName = getEmployeeDetails - }, - payload = PayLoadresult { - result = resultOne - } - ) - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/conversations/MoreDialogs.acdl b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/conversations/MoreDialogs.acdl deleted file mode 100644 index 1661ff46..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/conversations/MoreDialogs.acdl +++ /dev/null @@ -1,174 +0,0 @@ -namespace testSatheesh -import prompts.* -import displays.* -import com.amazon.alexa.ask.conversations.* -import com.amazon.alexa.schema.* -import com.weatherbot.apis.* -import slotTypes.* -import com.weatherbot.utteracesets.* - -type PAYLOAD_TYPE5 { - resultthree result - } - - -type PAYLOAD_TYPE3 { - customColor colorName - } - - type PAYLOAD_TYPE4 { - customColor colorName - } - - type payloadgetFruitPriceEvent { - result result - } - -@locale(Locale.en_US, Locale.en_GB) -affirmMultipleColorEvent_enUSenGB = utterances( - samples = [ - "do it" - ] -) - -@locale(Locale.de_DE) -affirmMultipleColorEvent_deDE = utterances( - samples = [ - "tu es" - ] -) -affirmMultipleColorEvent = variations(affirmMultipleColorEvent_enUSenGB, affirmMultipleColorEvent_deDE) - - -@locale(Locale.de_DE) -whoAmiExpectInvoke_german = utterances( - samples = [ - "Wer bin ich", - "sag mir wer ich bin", - "sag wer das ist" - ] -) - -@locale(Locale.en_US, Locale.en_GB) -whoAmiExpectInvoke_englisg = utterances( - samples = [ - "who am i", - "tell me who i am", - "tell who is this" - ] - ) - - whoAmiExpectInvoke = variations(whoAmiExpectInvoke_englisg,whoAmiExpectInvoke_german ) - - type thyisIsenGB { - enGBUSCommon enGBUSName - } - - type informColorMultipleEventRequestType { - customColor colorName - } - @locale(Locale.en_US, Locale.en_GB) - informWhopAi_enGBenUS = utterances( - samples = [ - "this is {enGBUSName}", - "{enGBUSName} is this" - ] - ) - - @locale(Locale.de_DE) - informWhopAi_german = utterances( - samples = [ - "das ist {enGBUSName}", - "{enGBUSName} ist das" - ] -) - - -@locale(Locale.en_US, Locale.en_GB) -MultipleDialogEvent_enUSenGB = utterances( - samples = [ - "i want to buy a fruit" - ] -) - -@locale(Locale.en_US, Locale.en_GB) -informColorMultipleEvent_enUSenGB = utterances( - samples = [ - "color {colorName}", - "color is {colorName}", - "{colorName}" - ] -) - - - -@locale(Locale.de_DE) -informColorMultipleEvent_deDE = utterances( - samples = [ - "farbe {colorName}", - "farbe ist {colorName}", - "{colorName}" - ] -) - - -informColorMultipleEvent = variations(informColorMultipleEvent_enUSenGB, informColorMultipleEvent_deDE) - - -@locale(Locale.de_DE) -MultipleDialogEvent_deDE= utterances( - samples = [ - "ich möchte eine frucht kaufen" - ] -) - -MultipleDialogEvent = variations(MultipleDialogEvent_enUSenGB, MultipleDialogEvent_deDE) - - - informWhopAi = variations(informWhopAi_enGBenUS, informWhopAi_german) - - - - -@locale(Locale.en_US, Locale.de_DE, Locale.en_GB) -dialog Nothing WhoAmi { - sample { - expect(act = Invoke,event = whoAmiExpectInvoke) - response(act = Request { arguments = [ whoAmi.arguments.enGBUSName ]},response = MultiModalResponse { apla = request_name_apla}) - informWhopAiRequest = expect(act = Inform,event = informWhopAi) - resultthree0 = whoAmi(enGBUSName = informWhopAiRequest.enGBUSName) - response(act = Notify { success = true, actionName = whoAmi},response = MultiModalResponse { apla = whoAmiSuccess}) - } -} - - -dialog Nothing dialogName_MultipleDialogEvent() { - sample { - expect(act = Invoke,event = MultipleDialogEvent) - response(act = Request { arguments = [ colorFruitName.arguments.colorName ]},response = MultiModalResponse { apla = request_colorName_multiple_apla}) - informColorMultipleEventRequest = expect(act = Inform,event = informColorMultipleEvent) - response(act = ConfirmArgs { arguments = [ colorFruitName.arguments.colorName ]},payload = PAYLOAD_TYPE3 { colorName = informColorMultipleEventRequest.colorName},response = MultiModalResponse { apla = confirm_color_for_fruit_apla}) - expect(act = Affirm,event = affirmMultipleColorEvent) - response(act = ConfirmAction { actionName = colorFruitName},payload = PAYLOAD_TYPE4 { colorName = informColorMultipleEventRequest.colorName},response = MultiModalResponse { apla = response0Prompt16}) - expect(act = Affirm,event = affirmMultipleColorEvent) - result0 = fruitNameAPI(color = informColorMultipleEventRequest.colorName) - ensure(requestArgs = [ RequestArguments { response = MultiModalResponse { apla = request_colorName_multiple_apla }, arguments = [ fruitNameAPI.arguments.color ] }]) - resultthree0 = colorFruitName(colorName = informColorMultipleEventRequest.colorName) - response(act = Notify { success = true, actionName = colorFruitName},payload = PAYLOAD_TYPE5 { result = resultthree0},response = MultiModalResponse { apla = success_fruitPriceAPI_apla, apl = dummyLastScreen}) - } - - sample { - // "content": "what is the price of the fruit" - expect(act = Invoke,event = getFruitPriceEvent) - response(response = requestArgs_request_fruitName_apla,act = Request { arguments = [ fruitNameAPI.arguments.fruitName ]}) - // "content": "fruit name is apple" - fruitNameEvent = expect(act = Inform,event = informfruitNameEvent) - //response(response = confirm_fruitName_apla, act = ConfirmArgs { arguments = [fruitNameAPI.arguments.fruitName]},payload = paylaodCompleFruit { fruitName = fruitNameEvent.fruitName}) - - // expect(act = Affirm,event = affirmFruitAPIEvent) - resultOne = fruitNameAPI(fruitName = fruitNameEvent.fruitName) - // resposne1() - response(response = success_fruitPriceAPI_apla,act = Notify { actionName = fruitNameAPI},payload = payloadgetFruitPriceEvent { result = resultOne}) - - } - } \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/conversations/Weather.acdl b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/conversations/Weather.acdl deleted file mode 100644 index ce7abb8c..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/conversations/Weather.acdl +++ /dev/null @@ -1,154 +0,0 @@ -namespace com.weatherbot - -import com.amazon.alexa.ask.conversations.Invoke -import com.amazon.alexa.ask.conversations.Notify -import com.amazon.alexa.ask.conversations.RequestArguments -import com.amazon.alexa.ask.conversations.ensure -import com.amazon.alexa.ask.conversations.expect -import com.amazon.alexa.ask.conversations.response -import com.amazon.alexa.ask.conversations.utterances -import com.amazon.alexa.schema.Nothing -import com.amazon.alexa.schema.Thing -import com.amazon.ask.types.builtins.AMAZON.DATE -import com.amazon.ask.types.builtins.AMAZON.NUMBER -import com.amazon.ask.types.builtins.AMAZON.US_CITY -import prompts.request_city_apla -import prompts.request_date_apla - -import slotTypes.* -import prompts.* -import displays.* -import com.amazon.ask.types.builtins.AMAZON.* -import com.amazon.alexa.schema.* -import com.amazon.alexa.ask.conversations.* - -type CityAndDate { - optional myCustomCities cityNameChanged - optional US_CITY cityName - optional DATE date -} - - -@locale(Locale.en_US, Locale.en_GB) -getWeatherEvent_enUS = utterances( - samples = [ - "What's the weather {date} in {cityNameChanged}", - "What's the weather {date} in {cityName}", - "What is the weather {date} in {cityName}", - "what is the weather {date}", - "how is weather" - ] -) - - -@locale(Locale.de_DE) -getWeatherEvent_deDE = utterances( - samples = [ - "Wie ist das wetter {date} in {cityNameChanged}", - "wie ist das wetter {date} in {cityName}", - "wie ist das wetter {date}", - "wie ist das wetter" - ] -) - -getWeatherEvent = variations(getWeatherEvent_enUS,getWeatherEvent_deDE) - -@locale(Locale.en_US, Locale.en_GB) -weather_apla_en = apla("../../skill-package/response/prompts/weather_apla") - -@locale(Locale.de_DE) -weather_apla_de = apla("../../skill-package/response/prompts/weather_apla_de_apla") - -weather_apla_apla_apla = variations(weather_apla_en,weather_apla_de) - - -type cityNameshell{ - US_CITY cityName -} - -@locale(Locale.en_US, Locale.en_GB) -weather_apl_visual_en = apl("../../skill-package/response/display/confirm_weather_apla_display") - -@locale(Locale.de_DE) -weather_apl_visual_de = apl ("../../skill-package/response/display/display_de_apl") - -weather_apl_visual = variations(weather_apl_visual_en, weather_apl_visual_de) - -weather_apla_var = MultiModalResponse (apla = weather_apla_apla_apla, apl = weather_apl_visual) - -/* -what's the weather today in seattle -what is the weather today in madurai -what's the weather today in chennai -what's the weather today in speaker - -*/ - - - -type WeatherResult { - optional myCustomCities cityNameChanged - optional US_CITY cityName - NUMBER highTemp - NUMBER lowTemp -} - -type ResponsePayload { - WeatherResult weatherResult -} - -action WeatherResult getWeather(DATE date, US_CITY cityName = nothing, myCustomCities cityNameChanged = nothing) - - - -dialog Nothing Weather() { - sample { - weatherRequest = expect(act = Invoke,event = getWeatherEvent) - ensure( -requestArgs = [ - RequestArguments {arguments = [ getWeather.arguments.cityNameChanged],response = request_city_apla}, - RequestArguments {arguments = [ getWeather.arguments.cityName],response = request_city_apla}, - RequestArguments { arguments = [getWeather.arguments.date],response = request_date_apla} - ] - ) - weatherResult = getWeather(date = weatherRequest.date, cityName = weatherRequest.cityName) - response( - response = weather_apla_var, - act = Notify {actionName = getWeather}, - payload = ResponsePayload { weatherResult = weatherResult} - ) - } - - sample { - weatherRequest = expect(act = Invoke,event = getWeatherEvent) - ensure( -requestArgs = [ - RequestArguments {arguments = [ getWeather.arguments.cityNameChanged],response = request_city_apla}, - RequestArguments {arguments = [ getWeather.arguments.cityName],response = request_city_apla}, - RequestArguments { arguments = [getWeather.arguments.date],response = request_date_apla} - ] - ) - weatherResult = getWeather(date = weatherRequest.date, cityNameChanged = weatherRequest.cityNameChanged) - response( - response = weather_apla_var, - act = Notify {actionName = getWeather}, - payload = ResponsePayload { weatherResult = weatherResult} - ) - } -} - -dialog Nothing ComplexTest() { - sample { - Weather() - } -} - - - -type weatherRequestEvent0 { - optional myCustomCities cityNameChanged - optional US_CITY cityName - DATE date -} - - diff --git a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/conversations/apis.acdl b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/conversations/apis.acdl deleted file mode 100644 index 9cce7d36..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/conversations/apis.acdl +++ /dev/null @@ -1,36 +0,0 @@ -namespace com.weatherbot.apis - -import com.amazon.alexa.schema.Nothing -import com.amazon.ask.types.builtins.AMAZON.DATE -import com.amazon.ask.types.builtins.AMAZON.NUMBER -import slotTypes.complexNames -import slotTypes.signs -import slotTypes.* -import types.complexResult -import types.result_one -import com.amazon.ask.types.builtins.AMAZON.* - -action NUMBER whoAmi(enGBUSCommon enGBUSName) - -action NUMBER secondEarthAPI() - -action result_one favColorSign_Name(complexNames name, signs sign = nothing) - -action resultthree colorFruitName(customColor colorName) -action resultthree colorFruitNameA(myColors colorName) - - -action result fruitNameAPI(customColor color = nothing, Food fruitName = nothing) - -type result { - NUMBER price - Food fruitName - } - -action complexResult getEmployeeDetails(complexNames name1, NUMBER emplyee1id, DATE a_dateOfBirth = nothing) - -type resultthree { - Color colorName - Food fruitName - } - \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/conversations/apisNamepaceLambda b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/conversations/apisNamepaceLambda deleted file mode 100644 index 5fcdf369..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/conversations/apisNamepaceLambda +++ /dev/null @@ -1,23 +0,0 @@ -namespace com.weatherbot.apis - -import com.amazon.ask.types.builtins.AMAZON.Color -import com.amazon.ask.types.builtins.AMAZON.Food -import com.amazon.ask.types.builtins.AMAZON.NUMBER -import slotTypes.* - -type result { - Food fruitName - NUMBER price -} - -type payloadgetFruitPriceEvent { - result result -} - -action result fruitNameAPI(Food fruitName) - -action resultthree colorFruitName(myColors colorName) - -type resultthree { - Food fruitName -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/conversations/conversation_empty.acdl b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/conversations/conversation_empty.acdl deleted file mode 100644 index 4189bdda..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/conversations/conversation_empty.acdl +++ /dev/null @@ -1,114 +0,0 @@ -namespace com.numberbot - -import com.amazon.alexa.ask.conversations.APLA -import com.amazon.alexa.ask.conversations.Action -import com.amazon.alexa.ask.conversations.Bye -import com.amazon.alexa.ask.conversations.Invoke -import com.amazon.alexa.ask.conversations.Notify -import com.amazon.alexa.ask.conversations.Offer -import com.amazon.alexa.ask.conversations.RequestArguments -import com.amazon.alexa.ask.conversations.ensure -import com.amazon.alexa.ask.conversations.expect -import com.amazon.alexa.ask.conversations.response -import com.amazon.alexa.ask.conversations.utterances -import com.amazon.alexa.schema.Nothing -import com.amazon.alexa.schema.Number -import com.amazon.alexa.schema.Thing -import com.amazon.ask.types.builtins.AMAZON.NUMBER -import prompts.AlexaConversationsBye -import prompts.numericfeedback_apla -import prompts.rating_apla - -type NumPayload { - Number num -} - -type RatingRequest { - NUMBER rating -} - -InformRatingEvent = utterances( - samples = [ - "my score is {rating}", - "that was a {rating} conversation", - "i rate you a {rating}", - "{rating}" - ] -) - -getStart = utterances( - samples = [ - "give me a number please" - ] -) - -action Nothing saveRating(Number rating) - -action Number getNumber() - -dialog Nothing GetFeedback(APLA feedback_prompt, Number num, Action notifyAction) { - sample { - response( - response = feedback_prompt, - act = Notify { - actionName = notifyAction, - success = true - }, - nextAct = Offer { - actionName = saveRating, - arguments = [ - saveRating.arguments.rating - ] - }, - payload = NumPayload { - num = num - } - ) - myRating = expect( - act = Invoke, - event = InformRatingEvent - ) - ensure( - requestArgs = [ - RequestArguments { - arguments = [ - saveRating.arguments.rating - ], - response = rating_apla - } - ] - ) - saveRating( - rating = myRating.rating - ) - } -} - -dialog Number levelOne() { - sample { - expect( - act = Invoke, - event = getStart - ) - num = getNumber() - } -} - -dialog Nothing MainDialog() { - sample { - num = levelOne() - GetFeedback( - feedback_prompt = numericfeedback_apla, - num = num, - notifyAction = getNumber - ) - response( - response = AlexaConversationsBye, - act = Notify { - actionName = saveRating, - success = true - }, - nextAct = Bye {} - ) - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/conversations/delegateToSkill.acdl b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/conversations/delegateToSkill.acdl deleted file mode 100644 index 5a2ae76e..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/conversations/delegateToSkill.acdl +++ /dev/null @@ -1,33 +0,0 @@ -namespace delegateToSkill - -import com.amazon.alexa.ask.conversations.Invoke -import com.amazon.alexa.ask.conversations.Notify -import com.amazon.alexa.ask.conversations.expect -import com.amazon.alexa.ask.conversations.response -import com.amazon.alexa.schema.Nothing -import com.weatherbot.apis.secondEarthAPI -import com.weatherbot.utteracesets.delegateToSkill -import prompts.secondEarthAPI_apla -import slotTypes.* -import prompts.* -import displays.* -import com.weatherbot.utteracesets.* -import com.amazon.alexa.ask.conversations.* -import com.amazon.alexa.schema.* -import types.* -dialog Nothing testTwo() { - sample { - expect( - act = Invoke, - event = delegateToSkill - ) - secondEarthAPI() - response( - response = secondEarthAPI_apla, - act = Notify { - actionName = secondEarthAPI - }, - nextAct = nothing - ) - } -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/conversations/fruitNameApi.acdl b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/conversations/fruitNameApi.acdl deleted file mode 100644 index 4664f2f2..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/conversations/fruitNameApi.acdl +++ /dev/null @@ -1,34 +0,0 @@ -namespace test - -import com.amazon.alexa.ask.conversations.utterances -import com.amazon.ask.types.builtins.AMAZON.Food - -type fruitNameShell { - Food fruitName -} - -type paylaodCompleFruit { - Food fruitName -} - -getFruitPriceEvent = utterances( - samples = [ - "what is the price of the fruit", - "what is the price of fruit" - ] -) - -informfruitNameEvent = utterances( - samples = [ - "{fruitName}", - "fruit name is {fruitName}", - "fruit is {fruitName}" - ] -) - -affirmFruitAPIEvent = utterances( - samples = [ - "uh huh", - "yup" - ] -) diff --git a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/conversations/separateConfig.acdl b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/conversations/separateConfig.acdl deleted file mode 100644 index 514c4309..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/conversations/separateConfig.acdl +++ /dev/null @@ -1,83 +0,0 @@ -namespace configSkill - -import com.amazon.alexa.ask.conversations.skill -import com.amazon.alexa.ask.conversations.variations - -import com.amazon.alexa.ask.conversations.apla -import com.amazon.alexa.ask.conversations.apl -import com.amazon.alexa.ask.conversations.MultiModalResponse -import com.amazon.alexa.ask.conversations.Locale -import com.amazon.alexa.ask.conversations.locale -import com.amazon.alexa.ask.conversations.SkillLevelResponses -import com.amazon.alexa.ask.conversations.InvocationName - -import com.weatherbot.Weather -import soaACDl.sOA - -@locale(Locale.de_DE) -welcome_de = apla("../../skill-package/TestDataACDLi18n/deWelcome") - -@locale(Locale.en_US, Locale.en_GB, Locale.de_DE) -welcome_en_apl_tap = apl("../../skill-package/response/display/confirm_city_apl_display") - -welcome_apl = variations(welcome_en_apl_tap) - -@locale(Locale.en_US, Locale.en_GB) -welcome_en = apla("../../skill-package/response/prompts/AlexaConversationsWelcome") -combo_apla_welcome = variations( welcome_en , welcome_de) - - -@locale(Locale.en_US, Locale.en_GB) -out_of_domain_en = apla("../../skill-package/response/prompts/AlexaConversationsOutOfDomain") -@locale(Locale.en_US, Locale.en_GB) -bye_en = apla("../../skill-package/response/prompts/AlexaConversationsBye") -@locale(Locale.en_US, Locale.en_GB) -reqmore_en = apla("../../skill-package/response/prompts/AlexaConversationsRequestMore") -@locale(Locale.en_US, Locale.en_GB) -provide_help_en = apla("../../skill-package/response/prompts/AlexaConversationsProvideHelp") - -/* -@locale(Locale.es_US) -welcome_es_US = apla("../../skill-package/response/prompts/AlexaConversationsWelcome") -@locale(Locale.es_US) -out_of_domain_es_US = apla("../../skill-package/response/prompts/AlexaConversationsOutOfDomain") -@locale(Locale.es_US) -bye_es_US = apla("../../skill-package/response/prompts/AlexaConversationsBye") -@locale(Locale.es_US) -reqmore_es_US = apla("../../skill-package/response/prompts/AlexaConversationsRequestMore") -@locale(Locale.es_US) -provide_help_es_US = apla("../../skill-package/response/prompts/AlexaConversationsProvideHelp") -*/ - - -@locale(Locale.de_DE) -out_of_domain_de = apla("../../skill-package/TestDataACDLi18n/deOutOfDomain") -out_of_domainResponse = variations(out_of_domain_en, out_of_domain_de) - -@locale(Locale.de_DE) -bye_de = apla("../../skill-package/TestDataACDLi18n/deBye") -byeResponse = variations(bye_en, bye_de) - -@locale(Locale.de_DE) -reqmore_de = apla("../../skill-package/TestDataACDLi18n/deRequireMore") -reqmoreResponse = variations(reqmore_en, reqmore_de) - -@locale(Locale.de_DE) -provide_help_de = apla("../../skill-package/TestDataACDLi18n/deHelp") -provide_helpResponse = variations(provide_help_en, provide_help_de ) - - -combo = MultiModalResponse {apla = combo_apla_welcome, apl = welcome_apl} - -a = skill( - locales = [Locale.en_US, Locale.en_GB, Locale.de_DE], - skillLevelResponses = SkillLevelResponses - { - welcome = combo - ,out_of_domain = out_of_domainResponse - ,bye = byeResponse - ,reqmore = reqmoreResponse - ,provide_help = provide_helpResponse - } -) - diff --git a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/conversations/soaDialog.acdl b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/conversations/soaDialog.acdl deleted file mode 100644 index 1aaa772d..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/conversations/soaDialog.acdl +++ /dev/null @@ -1,132 +0,0 @@ -namespace soaACDl - -import com.amazon.alexa.ask.conversations.Affirm -import com.amazon.alexa.ask.conversations.ConfirmArgs -import com.amazon.alexa.ask.conversations.ConfirmAction -import com.weatherbot.apis.* -import com.amazon.alexa.ask.conversations.Invoke -import com.amazon.alexa.ask.conversations.Notify -import com.amazon.alexa.ask.conversations.Request -import com.amazon.alexa.ask.conversations.expect -//import com.amazon.alexa.ask.conversations.received -import com.amazon.alexa.ask.conversations.response -import com.amazon.alexa.ask.conversations.utterances -import types.* -import com.amazon.alexa.schema.String - -import com.weatherbot.apis.colorFruitName -import com.weatherbot.apis.fruitNameAPI -import com.weatherbot.apis.result -import prompts.confirm_color_for_fruit_apla -import prompts.request_colorName_multiple_apla -import prompts.success_fruitPriceAPI_apla -import prompts.request_city_apla -import slotTypes.* -import prompts.* -import displays.* -import com.amazon.ask.types.builtins.AMAZON.* -import com.amazon.alexa.schema.* -import com.amazon.alexa.ask.conversations.* - - - -type payloadMultipleDialogEvent { - resultthree result -} - -@locale(Locale.en_US,Locale.en_GB ) -MultipleDialogEvent_enUS = utterances( - samples = [ - "i want to buy a fruit" - ] -) -TRYTHI = MultipleDialogEvent_enUS - -@locale(Locale.de_DE) -MultipleDialogEvent_deDE = utterances( - samples = [ - "ich möchte eine frucht kaufen" - ] -) - -MultipleDialogEvent_temp = variations(TRYTHI) - -MultipleDialogEvent = variations(MultipleDialogEvent_temp, MultipleDialogEvent_deDE) - -@locale(Locale.en_US, Locale.en_GB) -informColorMultipleEvent_enUS = utterances( - samples = [ - "{colorName}", - "color is {colorName}", - "color {colorName}" - ] -) -@locale(Locale.de_DE) -informColorMultipleEvent_deDE = utterances( - samples = [ - "{colorName}", - "farbe ist {colorName}", - "farbe {colorName}" - ] -) - - -informColorMultipleEvent = variations(informColorMultipleEvent_enUS, informColorMultipleEvent_deDE) - -affirmMultipleColorEvent = utterances( - samples = [ - "do it" - ] -) - - -type colorNameShell { - myColors colorName -} - - -type payloadsOAConfirmArgs { - myColors colorName -} - - - - -/* - -informColorMultipleEvent = utterances( - samples = [ - "{colorName}", - "color is {colorName}", - "color {colorName}" - ] -) - -dialog Nothing stagingAreaOne() { - sample { - expect(act = Invoke,event = MultipleDialogEvent) - response(response = request_colorName_multiple_apla,act = Request {arguments = [colorFruitName.arguments.colorName]}) - } -} - - -*/ - -//com.amazon.alexa.ask.conversations.response(response = request_colorName_multiple_apla, act = com.amazon.alexa.ask.conversations.Request {arguments = [colorFruitName.arguments.colorName]}) - -@locale(Locale.de_DE, Locale.en_US, Locale.en_GB) -dialog Nothing sOA() { - //@locale(Locale.en_US) - sample { - expect(act = Invoke,event = MultipleDialogEvent) - response(response = request_colorName_multiple_apla,act = Request {arguments = [colorFruitNameA.arguments.colorName]}) - - colorEvent = expect(act = Inform,event = informColorMultipleEvent) - - resultEvent = colorFruitNameA(colorName = colorEvent.colorName) - response( response = success_colorFruitAPI_apla, act = Notify { actionName = colorFruitNameA}, - payload = payloadMultipleDialogEvent {result = resultEvent} - ) - } - -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/conversations/test b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/conversations/test deleted file mode 100644 index fcf67bdb..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/conversations/test +++ /dev/null @@ -1,4 +0,0 @@ -namespace testOne -import com.amazon.ask.types.builtins.AMAZON.* - -action asdasss asdas(Color asd, Food test = nothing ) \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/conversations/types.acdl b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/conversations/types.acdl deleted file mode 100644 index 439e8934..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/conversations/types.acdl +++ /dev/null @@ -1,43 +0,0 @@ -namespace types - -import com.amazon.ask.types.builtins.AMAZON.Color -import com.amazon.ask.types.builtins.AMAZON.DATE -import com.amazon.ask.types.builtins.AMAZON.Food -import com.amazon.ask.types.builtins.AMAZON.NUMBER -import slotTypes.complexNames -import slotTypes.position -import slotTypes.signs -import slotTypes.* - -type result_one { - Color colorName - complexNames name - signs sign -} - -type complexResult { - complexNames name1 - DATE a_dateOfBirth - NUMBER emplyee1id - position position -} - -type nameShell { - complexNames name -} - -type dobshell { - DATE a_dateOfBirth -} - -type employeeIDshell { - NUMBER emplyee1id -} - -type fruitNameShell { - Food fruitName -} -/ -type colorEvent0 { - myColors colorName -} diff --git a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/conversations/utteracesets.acdl b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/conversations/utteracesets.acdl deleted file mode 100644 index e994b216..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/conversations/utteracesets.acdl +++ /dev/null @@ -1,82 +0,0 @@ -namespace com.weatherbot.utteracesets - -import com.amazon.alexa.ask.conversations.utterances -import types.dobshell -import types.employeeIDshell -import types.fruitNameShell -import types.nameShell - -getFruitPriceEvent = utterances( - samples = [ - "what is the price of the fruit", - "what is the price of fruit" - ] -) - -affirmFruitAPIEvent = utterances( - samples = [ - "yeah" - ] -) - -informfruitNameEvent = utterances( - samples = [ - "{fruitName}", - "fruit name is {fruitName}", - "fruit is {fruitName}" - ] -) - -delegateToSkill = utterances( - samples = [ - "get me to paradise", - "take me to paradise" - ] -) - -getFavColorEvent = utterances( - samples = [ - "what is my favourite color", - "tell my favourite color" - ] -) - -affirmFavColorEvent = utterances( - samples = [ - "correct" - ] -) - -who_are_you = utterances( - samples = [ - "who are you", - "who is that", - "find his designation" - ] -) - -informComplexNameEvent = utterances( - samples = [ - "{name}", - "name is {name}", - "i am {name}" - ] -) - -informDOBEvent = utterances( - samples = [ - "date of birth is {a_dateOfBirth}", - "birth date is {a_dateOfBirth}" - ] -) - -informEmployeeIDEvent = utterances( - samples = [ - "employee i.d. is {emplyee1id}", - "employee identification is {emplyee1id}", - "identification is {emplyee1id}", - "employee id is {emplyee1id}", - "i.d. is {emplyee1id}", - "id is {emplyee1id}" - ] -) diff --git a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/interactionModels/custom/de-DE.json b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/interactionModels/custom/de-DE.json deleted file mode 100644 index 5f130508..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/interactionModels/custom/de-DE.json +++ /dev/null @@ -1,963 +0,0 @@ -{ - "interactionModel": { - "languageModel": { - "invocationName": "model feedback test skill six", - "intents": [{ - "name": "AMAZON.CancelIntent", - "samples": [] - }, - { - "name": "AMAZON.HelpIntent", - "samples": [] - }, - { - "name": "AMAZON.StopIntent", - "samples": [] - }, - { - "name": "GetWeatherIntent", - "samples": [ - "what is the weather", - "how is the weather", - "tell me the weather" - ] - }, - { - "name": "AMAZON.NavigateHomeIntent", - "samples": [] - }, - { - "name": "AMAZON.FallbackIntent", - "samples": [] - } - ], - "types": [{ - "values": [{ - "id": "movies", - "name": { - "value": "movies", - "synonyms": [] - } - }, - { - "id": "politics", - "name": { - "value": "politics", - "synonyms": [] - } - }, - { - "id": "sports", - "name": { - "value": "sports", - "synonyms": [] - } - }, - { - "id": "hobbies", - "name": { - "value": "hobbies", - "synonyms": [] - } - }, - { - "id": "astronomy", - "name": { - "value": "astronomy", - "synonyms": [] - } - }, - { - "id": "physics", - "name": { - "value": "physics", - "synonyms": [] - } - }, - { - "id": "los_angeles_dodgers", - "name": { - "value": "los angeles dodgers" - } - }, - { - "id": "president_emmanuel_macron", - "name": { - "value": "president emmanuel macron" - } - }, - { - "id": "emmanuel_macron", - "name": { - "value": "emmanuel macron" - } - }, - { - "id": "tax_cuts", - "name": { - "value": "tax cuts" - } - }, - { - "id": "middle_class", - "name": { - "value": "middle class" - } - }, - { - "id": "inequality_divide", - "name": { - "value": "inequality divide" - } - }, - { - "id": "wealth_inequality", - "name": { - "value": "wealth inequality" - } - }, - { - "id": "n._p._r.", - "name": { - "value": "n. p. r." - } - }, - { - "id": "president_trump", - "name": { - "value": "president trump" - } - }, - { - "id": "fox", - "name": { - "value": "fox" - } - }, - { - "id": "police_officers", - "name": { - "value": "police officers" - } - }, - { - "id": "jerome_hall", - "name": { - "value": "jerome hall" - } - }, - { - "id": "diversity_training_program", - "name": { - "value": "diversity training program" - } - }, - { - "id": "read_preble", - "name": { - "value": "read preble" - } - }, - { - "id": "christopher_preble", - "name": { - "value": "christopher preble" - } - }, - { - "id": "pacific_rim", - "name": { - "value": "pacific rim" - } - }, - { - "id": "washington_nationals", - "name": { - "value": "washington nationals" - } - }, - { - "id": "michael_cohen", - "name": { - "value": "michael cohen" - } - }, - { - "id": "john_wall", - "name": { - "value": "john wall" - } - }, - { - "id": "united_states", - "name": { - "value": "united states" - } - }, - { - "id": "washington_wizards", - "name": { - "value": "washington wizards" - } - }, - { - "id": "bryce_harper", - "name": { - "value": "bryce harper" - } - }, - { - "id": "capitals_playoff_hockey_capitals", - "name": { - "value": "capitals playoff hockey capitals" - } - }, - { - "id": "james_b._comey", - "name": { - "value": "james b. comey" - } - }, - { - "id": "mike_pompeo", - "name": { - "value": "mike pompeo" - } - }, - { - "id": "tom_toles", - "name": { - "value": "tom toles" - } - }, - { - "id": "white_house", - "name": { - "value": "white house" - } - }, - { - "id": "manny_machado", - "name": { - "value": "manny machado" - } - }, - { - "id": "national_league_east", - "name": { - "value": "national league east" - } - }, - { - "id": "otto_porter_jr._now", - "name": { - "value": "otto porter jr. now" - } - }, - { - "id": "hillary_clinton", - "name": { - "value": "hillary clinton" - } - }, - { - "id": "trea_turner", - "name": { - "value": "trea turner" - } - }, - { - "id": "max_scherzer", - "name": { - "value": "max scherzer" - } - }, - { - "id": "donald_trump", - "name": { - "value": "donald trump" - } - }, - { - "id": "bryce_harper_nationals", - "name": { - "value": "bryce harper nationals" - } - }, - { - "id": "michael_a._taylor", - "name": { - "value": "michael a. taylor" - } - }, - { - "id": "news_media", - "name": { - "value": "news media" - } - }, - { - "id": "conservative_political_action_conference", - "name": { - "value": "conservative political action conference" - } - }, - { - "id": "mainstream_media", - "name": { - "value": "mainstream media" - } - }, - { - "id": "baltimore_orioles", - "name": { - "value": "baltimore orioles" - } - }, - { - "id": "sean_hannity", - "name": { - "value": "sean hannity" - } - }, - { - "id": "privilege", - "name": { - "value": "privilege" - } - }, - { - "id": "sarah_hart", - "name": { - "value": "sarah hart" - } - }, - { - "id": "matt_kemp", - "name": { - "value": "matt kemp" - } - }, - { - "id": "stephen_strasburg", - "name": { - "value": "stephen strasburg" - } - }, - { - "id": "police_misconduct", - "name": { - "value": "police misconduct" - } - }, - { - "id": "sarah_huckabee_sanders", - "name": { - "value": "sarah huckabee sanders" - } - }, - { - "id": "washington_wizards_april", - "name": { - "value": "washington wizards april" - } - }, - { - "id": "environmental_protection_agency_administrator_scott_pruitt", - "name": { - "value": "environmental protection agency administrator scott pruitt" - } - }, - { - "id": "dodger_stadium", - "name": { - "value": "dodger stadium" - } - }, - { - "id": "environmental_protection_agency", - "name": { - "value": "environmental protection agency" - } - }, - { - "id": "barbara_bush", - "name": { - "value": "barbara bush" - } - }, - { - "id": "lewis_\"scooter\"_libby", - "name": { - "value": "lewis \"scooter\" libby" - } - }, - { - "id": "lewis_scooter_libby", - "name": { - "value": "lewis scooter libby" - } - }, - { - "id": "game_3._lowry", - "name": { - "value": "game 3. lowry" - } - }, - { - "id": "columbus_blue_jackets", - "name": { - "value": "columbus blue jackets" - } - }, - { - "id": "john_tortorella", - "name": { - "value": "john tortorella" - } - }, - { - "id": "george_w._bush", - "name": { - "value": "george w. bush" - } - }, - { - "id": "george_h.w._bush", - "name": { - "value": "george h.w. bush" - } - }, - { - "id": "jarrett_hurd", - "name": { - "value": "jarrett hurd" - } - }, - { - "id": "said_fred_hurd_sr.", - "name": { - "value": "said fred hurd sr." - } - }, - { - "id": "fred_hurd_sr.", - "name": { - "value": "fred hurd sr." - } - }, - { - "id": "san_antonio", - "name": { - "value": "san antonio" - } - }, - { - "id": "san_antonio_spurs", - "name": { - "value": "san antonio spurs" - } - }, - { - "id": "gregg_popovich", - "name": { - "value": "gregg popovich" - } - }, - { - "id": "kawhi_leonard", - "name": { - "value": "kawhi leonard" - } - }, - { - "id": "tim_bontemps_seth_jones", - "name": { - "value": "tim bontemps seth jones" - } - }, - { - "id": "consumer_sentiment_index", - "name": { - "value": "consumer sentiment index" - } - }, - { - "id": "pew_research_center", - "name": { - "value": "pew research center" - } - }, - { - "id": "conference_board_consumer_confidence_survey", - "name": { - "value": "conference board consumer confidence survey" - } - }, - { - "id": "speech_rights", - "name": { - "value": "speech rights" - } - }, - { - "id": "first_amendment", - "name": { - "value": "first amendment" - } - }, - { - "id": "golden_state", - "name": { - "value": "golden state" - } - }, - { - "id": "north_korea", - "name": { - "value": "north korea" - } - }, - { - "id": "woman_pilot", - "name": { - "value": "woman pilot" - } - }, - { - "id": "airline_pilot_population", - "name": { - "value": "airline pilot population" - } - }, - { - "id": "air_transport_pilot", - "name": { - "value": "air transport pilot" - } - }, - { - "id": "southwest_airlines", - "name": { - "value": "southwest airlines" - } - }, - { - "id": "democratic_national_committee", - "name": { - "value": "democratic national committee" - } - }, - { - "id": "senate_foreign_relations_committee", - "name": { - "value": "senate foreign relations committee" - } - }, - { - "id": "cia_director_mike_pompeo", - "name": { - "value": "cia director mike pompeo" - } - }, - { - "id": "playoff_overtime_games", - "name": { - "value": "playoff overtime games" - } - }, - { - "id": "lord_jesus", - "name": { - "value": "lord jesus" - } - }, - { - "id": "lgbtq_community", - "name": { - "value": "lgbtq community" - } - }, - { - "id": "health_and_human_services_department", - "name": { - "value": "health and human services department" - } - }, - { - "id": "group_prayer", - "name": { - "value": "group prayer" - } - }, - { - "id": "princess_charlotte_elizabeth_diana", - "name": { - "value": "princess charlotte elizabeth diana" - } - }, - { - "id": "term_war_economy", - "name": { - "value": "term war economy" - } - }, - { - "id": "melissa_kirk", - "name": { - "value": "melissa kirk" - } - }, - { - "id": "captain_america", - "name": { - "value": "captain america" - } - }, - { - "id": "draft_position", - "name": { - "value": "draft position" - } - }, - { - "id": "elysee_mbem-bosse", - "name": { - "value": "elysee mbem-bosse" - } - }, - { - "id": "water_crisis", - "name": { - "value": "water crisis" - } - }, - { - "id": "nationals_pitchers", - "name": { - "value": "nationals pitchers" - } - }, - { - "id": "sen._jennifer_t._wexton", - "name": { - "value": "sen. jennifer t. wexton" - } - }, - { - "id": "interest_rates", - "name": { - "value": "interest rates" - } - }, - { - "id": "town_crier", - "name": { - "value": "town crier" - } - }, - { - "id": "nancy_goes_millennial", - "name": { - "value": "nancy goes millennial" - } - }, - { - "id": "steve_rogers", - "name": { - "value": "steve rogers" - } - }, - { - "id": "game_3._lebron_james", - "name": { - "value": "game 3. lebron james" - } - }, - { - "id": "anthony_rendon", - "name": { - "value": "anthony rendon" - } - }, - { - "id": "buckingham_palace", - "name": { - "value": "buckingham palace" - } - }, - { - "id": "travis_reinking_suspected", - "name": { - "value": "travis reinking suspected" - } - }, - { - "id": "detroit_free_press", - "name": { - "value": "detroit free press" - } - }, - { - "id": "national_rifle_association", - "name": { - "value": "national rifle association" - } - }, - { - "id": "ed_harris", - "name": { - "value": "ed harris" - } - }, - { - "id": "overtime_playoff_games", - "name": { - "value": "overtime playoff games" - } - }, - { - "id": "republican_sen._bob_corker", - "name": { - "value": "republican sen. bob corker" - } - }, - { - "id": "electricity_sector_reforms", - "name": { - "value": "electricity sector reforms" - } - }, - { - "id": "baltimore_manager_buck_showalter", - "name": { - "value": "baltimore manager buck showalter" - } - }, - { - "id": "sen._joe_manchin_iii", - "name": { - "value": "sen. joe manchin iii" - } - }, - { - "id": "car_seat_belts", - "name": { - "value": "car seat belts" - } - }, - { - "id": "andrews_mcmeel.", - "name": { - "value": "andrews mcmeel." - } - }, - { - "id": "north_africa_program", - "name": { - "value": "north africa program" - } - }, - { - "id": "state_prosecutor_lobby", - "name": { - "value": "state prosecutor lobby" - } - }, - { - "id": "cape_town", - "name": { - "value": "cape town" - } - }, - { - "id": "data_privacy_law", - "name": { - "value": "data privacy law" - } - }, - { - "id": "president_trump_down", - "name": { - "value": "president trump down" - } - }, - { - "id": "christian_kirk", - "name": { - "value": "christian kirk" - } - }, - { - "id": "mitch_mcconnell", - "name": { - "value": "mitch mcconnell" - } - }, - { - "id": "federal_reserve", - "name": { - "value": "federal reserve" - } - } - ], - "name": "TopicType" - }, - { - "values": [{ - "name": { - "value": "cancer" - } - }, - { - "name": { - "value": "scorpio" - } - }, - { - "name": { - "value": "scorpion" - } - } - ], - "name": "signs" - }, - { - "values": [{ - "name": { - "value": "satheesh" - } - }, - { - "name": { - "value": "raman" - } - }, - { - "name": { - "value": "yadhu" - } - } - ], - "name": "complexNames" - }, - { - "values": [{ - "name": { - "value": "tester" - } - }, - { - "name": { - "value": "engineer" - } - }, - { - "name": { - "value": "manager" - } - } - ], - "name": "position" - }, - { - "values": [{ - "name": { - "value": "blue" - } - }, - { - "name": { - "value": "red" - } - }, - { - "name": { - "value": "rocket" - } - } - ], - "name": "myColors" - }, - { - "values": [{ - "name": { - "value": "flower city" - } - }, - { - "name": { - "value": "temple city" - } - }, - { - "name": { - "value": "ramapuram" - } - }, - { - "name": { - "value": "guindy" - } - }, - { - "name": { - "value": "porur" - } - } - ], - "name": "myCustomCities" - }, - { - "values": [{ - "name": { - "value": "flower city" - } - }, - { - "name": { - "value": "temple city" - } - }, - { - "name": { - "value": "ramapuram" - } - }, - { - "name": { - "value": "guindy" - } - }, - { - "name": { - "value": "porur" - } - } - ], - "name": "enGBUSCommon" - }, - { - "values": [{ - "name": { - "value": "blue" - } - }, - { - "name": { - "value": "red" - } - }, - { - "name": { - "value": "rocket" - } - } - ], - "name": "customColor" - } - ] - } - }, - "version": "18" -} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/interactionModels/custom/en-GB.json b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/interactionModels/custom/en-GB.json deleted file mode 100644 index 4ac624d8..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/interactionModels/custom/en-GB.json +++ /dev/null @@ -1,963 +0,0 @@ -{ - "interactionModel": { - "languageModel": { - "invocationName": "model feedback test skill six", - "intents": [{ - "name": "AMAZON.CancelIntent", - "samples": [] - }, - { - "name": "AMAZON.HelpIntent", - "samples": [] - }, - { - "name": "AMAZON.StopIntent", - "samples": [] - }, - { - "name": "GetWeatherIntent", - "samples": [ - "what is the weather", - "how is the weather", - "tell me the weather" - ] - }, - { - "name": "AMAZON.NavigateHomeIntent", - "samples": [] - }, - { - "name": "AMAZON.FallbackIntent", - "samples": [] - } - ], - "types": [{ - "values": [{ - "id": "movies", - "name": { - "value": "movies", - "synonyms": [] - } - }, - { - "id": "politics", - "name": { - "value": "politics", - "synonyms": [] - } - }, - { - "id": "sports", - "name": { - "value": "sports", - "synonyms": [] - } - }, - { - "id": "hobbies", - "name": { - "value": "hobbies", - "synonyms": [] - } - }, - { - "id": "astronomy", - "name": { - "value": "astronomy", - "synonyms": [] - } - }, - { - "id": "physics", - "name": { - "value": "physics", - "synonyms": [] - } - }, - { - "id": "los_angeles_dodgers", - "name": { - "value": "los angeles dodgers" - } - }, - { - "id": "president_emmanuel_macron", - "name": { - "value": "president emmanuel macron" - } - }, - { - "id": "emmanuel_macron", - "name": { - "value": "emmanuel macron" - } - }, - { - "id": "tax_cuts", - "name": { - "value": "tax cuts" - } - }, - { - "id": "middle_class", - "name": { - "value": "middle class" - } - }, - { - "id": "inequality_divide", - "name": { - "value": "inequality divide" - } - }, - { - "id": "wealth_inequality", - "name": { - "value": "wealth inequality" - } - }, - { - "id": "n._p._r.", - "name": { - "value": "n. p. r." - } - }, - { - "id": "president_trump", - "name": { - "value": "president trump" - } - }, - { - "id": "fox", - "name": { - "value": "fox" - } - }, - { - "id": "police_officers", - "name": { - "value": "police officers" - } - }, - { - "id": "jerome_hall", - "name": { - "value": "jerome hall" - } - }, - { - "id": "diversity_training_program", - "name": { - "value": "diversity training program" - } - }, - { - "id": "read_preble", - "name": { - "value": "read preble" - } - }, - { - "id": "christopher_preble", - "name": { - "value": "christopher preble" - } - }, - { - "id": "pacific_rim", - "name": { - "value": "pacific rim" - } - }, - { - "id": "washington_nationals", - "name": { - "value": "washington nationals" - } - }, - { - "id": "michael_cohen", - "name": { - "value": "michael cohen" - } - }, - { - "id": "john_wall", - "name": { - "value": "john wall" - } - }, - { - "id": "united_states", - "name": { - "value": "united states" - } - }, - { - "id": "washington_wizards", - "name": { - "value": "washington wizards" - } - }, - { - "id": "bryce_harper", - "name": { - "value": "bryce harper" - } - }, - { - "id": "capitals_playoff_hockey_capitals", - "name": { - "value": "capitals playoff hockey capitals" - } - }, - { - "id": "james_b._comey", - "name": { - "value": "james b. comey" - } - }, - { - "id": "mike_pompeo", - "name": { - "value": "mike pompeo" - } - }, - { - "id": "tom_toles", - "name": { - "value": "tom toles" - } - }, - { - "id": "white_house", - "name": { - "value": "white house" - } - }, - { - "id": "manny_machado", - "name": { - "value": "manny machado" - } - }, - { - "id": "national_league_east", - "name": { - "value": "national league east" - } - }, - { - "id": "otto_porter_jr._now", - "name": { - "value": "otto porter jr. now" - } - }, - { - "id": "hillary_clinton", - "name": { - "value": "hillary clinton" - } - }, - { - "id": "trea_turner", - "name": { - "value": "trea turner" - } - }, - { - "id": "max_scherzer", - "name": { - "value": "max scherzer" - } - }, - { - "id": "donald_trump", - "name": { - "value": "donald trump" - } - }, - { - "id": "bryce_harper_nationals", - "name": { - "value": "bryce harper nationals" - } - }, - { - "id": "michael_a._taylor", - "name": { - "value": "michael a. taylor" - } - }, - { - "id": "news_media", - "name": { - "value": "news media" - } - }, - { - "id": "conservative_political_action_conference", - "name": { - "value": "conservative political action conference" - } - }, - { - "id": "mainstream_media", - "name": { - "value": "mainstream media" - } - }, - { - "id": "baltimore_orioles", - "name": { - "value": "baltimore orioles" - } - }, - { - "id": "sean_hannity", - "name": { - "value": "sean hannity" - } - }, - { - "id": "privilege", - "name": { - "value": "privilege" - } - }, - { - "id": "sarah_hart", - "name": { - "value": "sarah hart" - } - }, - { - "id": "matt_kemp", - "name": { - "value": "matt kemp" - } - }, - { - "id": "stephen_strasburg", - "name": { - "value": "stephen strasburg" - } - }, - { - "id": "police_misconduct", - "name": { - "value": "police misconduct" - } - }, - { - "id": "sarah_huckabee_sanders", - "name": { - "value": "sarah huckabee sanders" - } - }, - { - "id": "washington_wizards_april", - "name": { - "value": "washington wizards april" - } - }, - { - "id": "environmental_protection_agency_administrator_scott_pruitt", - "name": { - "value": "environmental protection agency administrator scott pruitt" - } - }, - { - "id": "dodger_stadium", - "name": { - "value": "dodger stadium" - } - }, - { - "id": "environmental_protection_agency", - "name": { - "value": "environmental protection agency" - } - }, - { - "id": "barbara_bush", - "name": { - "value": "barbara bush" - } - }, - { - "id": "lewis_\"scooter\"_libby", - "name": { - "value": "lewis \"scooter\" libby" - } - }, - { - "id": "lewis_scooter_libby", - "name": { - "value": "lewis scooter libby" - } - }, - { - "id": "game_3._lowry", - "name": { - "value": "game 3. lowry" - } - }, - { - "id": "columbus_blue_jackets", - "name": { - "value": "columbus blue jackets" - } - }, - { - "id": "john_tortorella", - "name": { - "value": "john tortorella" - } - }, - { - "id": "george_w._bush", - "name": { - "value": "george w. bush" - } - }, - { - "id": "george_h.w._bush", - "name": { - "value": "george h.w. bush" - } - }, - { - "id": "jarrett_hurd", - "name": { - "value": "jarrett hurd" - } - }, - { - "id": "said_fred_hurd_sr.", - "name": { - "value": "said fred hurd sr." - } - }, - { - "id": "fred_hurd_sr.", - "name": { - "value": "fred hurd sr." - } - }, - { - "id": "san_antonio", - "name": { - "value": "san antonio" - } - }, - { - "id": "san_antonio_spurs", - "name": { - "value": "san antonio spurs" - } - }, - { - "id": "gregg_popovich", - "name": { - "value": "gregg popovich" - } - }, - { - "id": "kawhi_leonard", - "name": { - "value": "kawhi leonard" - } - }, - { - "id": "tim_bontemps_seth_jones", - "name": { - "value": "tim bontemps seth jones" - } - }, - { - "id": "consumer_sentiment_index", - "name": { - "value": "consumer sentiment index" - } - }, - { - "id": "pew_research_center", - "name": { - "value": "pew research center" - } - }, - { - "id": "conference_board_consumer_confidence_survey", - "name": { - "value": "conference board consumer confidence survey" - } - }, - { - "id": "speech_rights", - "name": { - "value": "speech rights" - } - }, - { - "id": "first_amendment", - "name": { - "value": "first amendment" - } - }, - { - "id": "golden_state", - "name": { - "value": "golden state" - } - }, - { - "id": "north_korea", - "name": { - "value": "north korea" - } - }, - { - "id": "woman_pilot", - "name": { - "value": "woman pilot" - } - }, - { - "id": "airline_pilot_population", - "name": { - "value": "airline pilot population" - } - }, - { - "id": "air_transport_pilot", - "name": { - "value": "air transport pilot" - } - }, - { - "id": "southwest_airlines", - "name": { - "value": "southwest airlines" - } - }, - { - "id": "democratic_national_committee", - "name": { - "value": "democratic national committee" - } - }, - { - "id": "senate_foreign_relations_committee", - "name": { - "value": "senate foreign relations committee" - } - }, - { - "id": "cia_director_mike_pompeo", - "name": { - "value": "cia director mike pompeo" - } - }, - { - "id": "playoff_overtime_games", - "name": { - "value": "playoff overtime games" - } - }, - { - "id": "lord_jesus", - "name": { - "value": "lord jesus" - } - }, - { - "id": "lgbtq_community", - "name": { - "value": "lgbtq community" - } - }, - { - "id": "health_and_human_services_department", - "name": { - "value": "health and human services department" - } - }, - { - "id": "group_prayer", - "name": { - "value": "group prayer" - } - }, - { - "id": "princess_charlotte_elizabeth_diana", - "name": { - "value": "princess charlotte elizabeth diana" - } - }, - { - "id": "term_war_economy", - "name": { - "value": "term war economy" - } - }, - { - "id": "melissa_kirk", - "name": { - "value": "melissa kirk" - } - }, - { - "id": "captain_america", - "name": { - "value": "captain america" - } - }, - { - "id": "draft_position", - "name": { - "value": "draft position" - } - }, - { - "id": "elysee_mbem-bosse", - "name": { - "value": "elysee mbem-bosse" - } - }, - { - "id": "water_crisis", - "name": { - "value": "water crisis" - } - }, - { - "id": "nationals_pitchers", - "name": { - "value": "nationals pitchers" - } - }, - { - "id": "sen._jennifer_t._wexton", - "name": { - "value": "sen. jennifer t. wexton" - } - }, - { - "id": "interest_rates", - "name": { - "value": "interest rates" - } - }, - { - "id": "town_crier", - "name": { - "value": "town crier" - } - }, - { - "id": "nancy_goes_millennial", - "name": { - "value": "nancy goes millennial" - } - }, - { - "id": "steve_rogers", - "name": { - "value": "steve rogers" - } - }, - { - "id": "game_3._lebron_james", - "name": { - "value": "game 3. lebron james" - } - }, - { - "id": "anthony_rendon", - "name": { - "value": "anthony rendon" - } - }, - { - "id": "buckingham_palace", - "name": { - "value": "buckingham palace" - } - }, - { - "id": "travis_reinking_suspected", - "name": { - "value": "travis reinking suspected" - } - }, - { - "id": "detroit_free_press", - "name": { - "value": "detroit free press" - } - }, - { - "id": "national_rifle_association", - "name": { - "value": "national rifle association" - } - }, - { - "id": "ed_harris", - "name": { - "value": "ed harris" - } - }, - { - "id": "overtime_playoff_games", - "name": { - "value": "overtime playoff games" - } - }, - { - "id": "republican_sen._bob_corker", - "name": { - "value": "republican sen. bob corker" - } - }, - { - "id": "electricity_sector_reforms", - "name": { - "value": "electricity sector reforms" - } - }, - { - "id": "baltimore_manager_buck_showalter", - "name": { - "value": "baltimore manager buck showalter" - } - }, - { - "id": "sen._joe_manchin_iii", - "name": { - "value": "sen. joe manchin iii" - } - }, - { - "id": "car_seat_belts", - "name": { - "value": "car seat belts" - } - }, - { - "id": "andrews_mcmeel.", - "name": { - "value": "andrews mcmeel." - } - }, - { - "id": "north_africa_program", - "name": { - "value": "north africa program" - } - }, - { - "id": "state_prosecutor_lobby", - "name": { - "value": "state prosecutor lobby" - } - }, - { - "id": "cape_town", - "name": { - "value": "cape town" - } - }, - { - "id": "data_privacy_law", - "name": { - "value": "data privacy law" - } - }, - { - "id": "president_trump_down", - "name": { - "value": "president trump down" - } - }, - { - "id": "christian_kirk", - "name": { - "value": "christian kirk" - } - }, - { - "id": "mitch_mcconnell", - "name": { - "value": "mitch mcconnell" - } - }, - { - "id": "federal_reserve", - "name": { - "value": "federal reserve" - } - } - ], - "name": "TopicType" - }, - { - "values": [{ - "name": { - "value": "cancer" - } - }, - { - "name": { - "value": "scorpio" - } - }, - { - "name": { - "value": "scorpion" - } - } - ], - "name": "signs" - }, - { - "values": [{ - "name": { - "value": "satheesh" - } - }, - { - "name": { - "value": "raman" - } - }, - { - "name": { - "value": "yadhu" - } - } - ], - "name": "complexNames" - }, - { - "values": [{ - "name": { - "value": "tester" - } - }, - { - "name": { - "value": "engineer" - } - }, - { - "name": { - "value": "manager" - } - } - ], - "name": "position" - }, - { - "values": [{ - "name": { - "value": "blue" - } - }, - { - "name": { - "value": "red" - } - }, - { - "name": { - "value": "rocket" - } - } - ], - "name": "myColors" - }, - { - "values": [{ - "name": { - "value": "blue" - } - }, - { - "name": { - "value": "red" - } - }, - { - "name": { - "value": "rocket" - } - } - ], - "name": "customColor" - }, - { - "values": [{ - "name": { - "value": "flower city" - } - }, - { - "name": { - "value": "temple city" - } - }, - { - "name": { - "value": "ramapuram" - } - }, - { - "name": { - "value": "guindy" - } - }, - { - "name": { - "value": "porur" - } - } - ], - "name": "myCustomCities" - }, - { - "values": [{ - "name": { - "value": "flower city" - } - }, - { - "name": { - "value": "temple city" - } - }, - { - "name": { - "value": "ramapuram" - } - }, - { - "name": { - "value": "guindy" - } - }, - { - "name": { - "value": "porur" - } - } - ], - "name": "enGBUSCommon" - } - ] - } - }, - "version": "18" -} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/interactionModels/custom/en-US.json b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/interactionModels/custom/en-US.json deleted file mode 100644 index 22e3efd3..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/interactionModels/custom/en-US.json +++ /dev/null @@ -1,976 +0,0 @@ -{ - "interactionModel": { - "languageModel": { - "invocationName": "model feedback test skill six", - "intents": [{ - "name": "AMAZON.CancelIntent", - "samples": [] - }, - { - "name": "AMAZON.HelpIntent", - "samples": [] - }, - { - "name": "AMAZON.StopIntent", - "samples": [] - }, - { - "name": "GetWeatherIntent", - "samples": [ - "what is the weather", - "how is the weather", - "tell me the weather" - ] - }, - { - "name": "SkillToColtrane", - "samples": [ - "switch to coltrane", - "hit coltrane", - "make coltrane DM" - ] - }, - { - "name": "NoDialog", - "samples": [ - "show me the wonders" - ] - }, { - "name": "AMAZON.NavigateHomeIntent", - "samples": [] - }, - { - "name": "AMAZON.FallbackIntent", - "samples": [] - } - ], - "types": [{ - "values": [{ - "id": "movies", - "name": { - "value": "movies", - "synonyms": [] - } - }, - { - "id": "politics", - "name": { - "value": "politics", - "synonyms": [] - } - }, - { - "id": "sports", - "name": { - "value": "sports", - "synonyms": [] - } - }, - { - "id": "hobbies", - "name": { - "value": "hobbies", - "synonyms": [] - } - }, - { - "id": "astronomy", - "name": { - "value": "astronomy", - "synonyms": [] - } - }, - { - "id": "physics", - "name": { - "value": "physics", - "synonyms": [] - } - }, - { - "id": "los_angeles_dodgers", - "name": { - "value": "los angeles dodgers" - } - }, - { - "id": "president_emmanuel_macron", - "name": { - "value": "president emmanuel macron" - } - }, - { - "id": "emmanuel_macron", - "name": { - "value": "emmanuel macron" - } - }, - { - "id": "tax_cuts", - "name": { - "value": "tax cuts" - } - }, - { - "id": "middle_class", - "name": { - "value": "middle class" - } - }, - { - "id": "inequality_divide", - "name": { - "value": "inequality divide" - } - }, - { - "id": "wealth_inequality", - "name": { - "value": "wealth inequality" - } - }, - { - "id": "n._p._r.", - "name": { - "value": "n. p. r." - } - }, - { - "id": "president_trump", - "name": { - "value": "president trump" - } - }, - { - "id": "fox", - "name": { - "value": "fox" - } - }, - { - "id": "police_officers", - "name": { - "value": "police officers" - } - }, - { - "id": "jerome_hall", - "name": { - "value": "jerome hall" - } - }, - { - "id": "diversity_training_program", - "name": { - "value": "diversity training program" - } - }, - { - "id": "read_preble", - "name": { - "value": "read preble" - } - }, - { - "id": "christopher_preble", - "name": { - "value": "christopher preble" - } - }, - { - "id": "pacific_rim", - "name": { - "value": "pacific rim" - } - }, - { - "id": "washington_nationals", - "name": { - "value": "washington nationals" - } - }, - { - "id": "michael_cohen", - "name": { - "value": "michael cohen" - } - }, - { - "id": "john_wall", - "name": { - "value": "john wall" - } - }, - { - "id": "united_states", - "name": { - "value": "united states" - } - }, - { - "id": "washington_wizards", - "name": { - "value": "washington wizards" - } - }, - { - "id": "bryce_harper", - "name": { - "value": "bryce harper" - } - }, - { - "id": "capitals_playoff_hockey_capitals", - "name": { - "value": "capitals playoff hockey capitals" - } - }, - { - "id": "james_b._comey", - "name": { - "value": "james b. comey" - } - }, - { - "id": "mike_pompeo", - "name": { - "value": "mike pompeo" - } - }, - { - "id": "tom_toles", - "name": { - "value": "tom toles" - } - }, - { - "id": "white_house", - "name": { - "value": "white house" - } - }, - { - "id": "manny_machado", - "name": { - "value": "manny machado" - } - }, - { - "id": "national_league_east", - "name": { - "value": "national league east" - } - }, - { - "id": "otto_porter_jr._now", - "name": { - "value": "otto porter jr. now" - } - }, - { - "id": "hillary_clinton", - "name": { - "value": "hillary clinton" - } - }, - { - "id": "trea_turner", - "name": { - "value": "trea turner" - } - }, - { - "id": "max_scherzer", - "name": { - "value": "max scherzer" - } - }, - { - "id": "donald_trump", - "name": { - "value": "donald trump" - } - }, - { - "id": "bryce_harper_nationals", - "name": { - "value": "bryce harper nationals" - } - }, - { - "id": "michael_a._taylor", - "name": { - "value": "michael a. taylor" - } - }, - { - "id": "news_media", - "name": { - "value": "news media" - } - }, - { - "id": "conservative_political_action_conference", - "name": { - "value": "conservative political action conference" - } - }, - { - "id": "mainstream_media", - "name": { - "value": "mainstream media" - } - }, - { - "id": "baltimore_orioles", - "name": { - "value": "baltimore orioles" - } - }, - { - "id": "sean_hannity", - "name": { - "value": "sean hannity" - } - }, - { - "id": "privilege", - "name": { - "value": "privilege" - } - }, - { - "id": "sarah_hart", - "name": { - "value": "sarah hart" - } - }, - { - "id": "matt_kemp", - "name": { - "value": "matt kemp" - } - }, - { - "id": "stephen_strasburg", - "name": { - "value": "stephen strasburg" - } - }, - { - "id": "police_misconduct", - "name": { - "value": "police misconduct" - } - }, - { - "id": "sarah_huckabee_sanders", - "name": { - "value": "sarah huckabee sanders" - } - }, - { - "id": "washington_wizards_april", - "name": { - "value": "washington wizards april" - } - }, - { - "id": "environmental_protection_agency_administrator_scott_pruitt", - "name": { - "value": "environmental protection agency administrator scott pruitt" - } - }, - { - "id": "dodger_stadium", - "name": { - "value": "dodger stadium" - } - }, - { - "id": "environmental_protection_agency", - "name": { - "value": "environmental protection agency" - } - }, - { - "id": "barbara_bush", - "name": { - "value": "barbara bush" - } - }, - { - "id": "lewis_\"scooter\"_libby", - "name": { - "value": "lewis \"scooter\" libby" - } - }, - { - "id": "lewis_scooter_libby", - "name": { - "value": "lewis scooter libby" - } - }, - { - "id": "game_3._lowry", - "name": { - "value": "game 3. lowry" - } - }, - { - "id": "columbus_blue_jackets", - "name": { - "value": "columbus blue jackets" - } - }, - { - "id": "john_tortorella", - "name": { - "value": "john tortorella" - } - }, - { - "id": "george_w._bush", - "name": { - "value": "george w. bush" - } - }, - { - "id": "george_h.w._bush", - "name": { - "value": "george h.w. bush" - } - }, - { - "id": "jarrett_hurd", - "name": { - "value": "jarrett hurd" - } - }, - { - "id": "said_fred_hurd_sr.", - "name": { - "value": "said fred hurd sr." - } - }, - { - "id": "fred_hurd_sr.", - "name": { - "value": "fred hurd sr." - } - }, - { - "id": "san_antonio", - "name": { - "value": "san antonio" - } - }, - { - "id": "san_antonio_spurs", - "name": { - "value": "san antonio spurs" - } - }, - { - "id": "gregg_popovich", - "name": { - "value": "gregg popovich" - } - }, - { - "id": "kawhi_leonard", - "name": { - "value": "kawhi leonard" - } - }, - { - "id": "tim_bontemps_seth_jones", - "name": { - "value": "tim bontemps seth jones" - } - }, - { - "id": "consumer_sentiment_index", - "name": { - "value": "consumer sentiment index" - } - }, - { - "id": "pew_research_center", - "name": { - "value": "pew research center" - } - }, - { - "id": "conference_board_consumer_confidence_survey", - "name": { - "value": "conference board consumer confidence survey" - } - }, - { - "id": "speech_rights", - "name": { - "value": "speech rights" - } - }, - { - "id": "first_amendment", - "name": { - "value": "first amendment" - } - }, - { - "id": "golden_state", - "name": { - "value": "golden state" - } - }, - { - "id": "north_korea", - "name": { - "value": "north korea" - } - }, - { - "id": "woman_pilot", - "name": { - "value": "woman pilot" - } - }, - { - "id": "airline_pilot_population", - "name": { - "value": "airline pilot population" - } - }, - { - "id": "air_transport_pilot", - "name": { - "value": "air transport pilot" - } - }, - { - "id": "southwest_airlines", - "name": { - "value": "southwest airlines" - } - }, - { - "id": "democratic_national_committee", - "name": { - "value": "democratic national committee" - } - }, - { - "id": "senate_foreign_relations_committee", - "name": { - "value": "senate foreign relations committee" - } - }, - { - "id": "cia_director_mike_pompeo", - "name": { - "value": "cia director mike pompeo" - } - }, - { - "id": "playoff_overtime_games", - "name": { - "value": "playoff overtime games" - } - }, - { - "id": "lord_jesus", - "name": { - "value": "lord jesus" - } - }, - { - "id": "lgbtq_community", - "name": { - "value": "lgbtq community" - } - }, - { - "id": "health_and_human_services_department", - "name": { - "value": "health and human services department" - } - }, - { - "id": "group_prayer", - "name": { - "value": "group prayer" - } - }, - { - "id": "princess_charlotte_elizabeth_diana", - "name": { - "value": "princess charlotte elizabeth diana" - } - }, - { - "id": "term_war_economy", - "name": { - "value": "term war economy" - } - }, - { - "id": "melissa_kirk", - "name": { - "value": "melissa kirk" - } - }, - { - "id": "captain_america", - "name": { - "value": "captain america" - } - }, - { - "id": "draft_position", - "name": { - "value": "draft position" - } - }, - { - "id": "elysee_mbem-bosse", - "name": { - "value": "elysee mbem-bosse" - } - }, - { - "id": "water_crisis", - "name": { - "value": "water crisis" - } - }, - { - "id": "nationals_pitchers", - "name": { - "value": "nationals pitchers" - } - }, - { - "id": "sen._jennifer_t._wexton", - "name": { - "value": "sen. jennifer t. wexton" - } - }, - { - "id": "interest_rates", - "name": { - "value": "interest rates" - } - }, - { - "id": "town_crier", - "name": { - "value": "town crier" - } - }, - { - "id": "nancy_goes_millennial", - "name": { - "value": "nancy goes millennial" - } - }, - { - "id": "steve_rogers", - "name": { - "value": "steve rogers" - } - }, - { - "id": "game_3._lebron_james", - "name": { - "value": "game 3. lebron james" - } - }, - { - "id": "anthony_rendon", - "name": { - "value": "anthony rendon" - } - }, - { - "id": "buckingham_palace", - "name": { - "value": "buckingham palace" - } - }, - { - "id": "travis_reinking_suspected", - "name": { - "value": "travis reinking suspected" - } - }, - { - "id": "detroit_free_press", - "name": { - "value": "detroit free press" - } - }, - { - "id": "national_rifle_association", - "name": { - "value": "national rifle association" - } - }, - { - "id": "ed_harris", - "name": { - "value": "ed harris" - } - }, - { - "id": "overtime_playoff_games", - "name": { - "value": "overtime playoff games" - } - }, - { - "id": "republican_sen._bob_corker", - "name": { - "value": "republican sen. bob corker" - } - }, - { - "id": "electricity_sector_reforms", - "name": { - "value": "electricity sector reforms" - } - }, - { - "id": "baltimore_manager_buck_showalter", - "name": { - "value": "baltimore manager buck showalter" - } - }, - { - "id": "sen._joe_manchin_iii", - "name": { - "value": "sen. joe manchin iii" - } - }, - { - "id": "car_seat_belts", - "name": { - "value": "car seat belts" - } - }, - { - "id": "andrews_mcmeel.", - "name": { - "value": "andrews mcmeel." - } - }, - { - "id": "north_africa_program", - "name": { - "value": "north africa program" - } - }, - { - "id": "state_prosecutor_lobby", - "name": { - "value": "state prosecutor lobby" - } - }, - { - "id": "cape_town", - "name": { - "value": "cape town" - } - }, - { - "id": "data_privacy_law", - "name": { - "value": "data privacy law" - } - }, - { - "id": "president_trump_down", - "name": { - "value": "president trump down" - } - }, - { - "id": "christian_kirk", - "name": { - "value": "christian kirk" - } - }, - { - "id": "mitch_mcconnell", - "name": { - "value": "mitch mcconnell" - } - }, - { - "id": "federal_reserve", - "name": { - "value": "federal reserve" - } - } - ], - "name": "TopicType" - }, - { - "values": [{ - "name": { - "value": "cancer" - } - }, - { - "name": { - "value": "scorpio" - } - }, - { - "name": { - "value": "scorpion" - } - } - ], - "name": "signs" - }, - { - "values": [{ - "name": { - "value": "satheesh" - } - }, - { - "name": { - "value": "raman" - } - }, - { - "name": { - "value": "yadhu" - } - } - ], - "name": "complexNames" - }, - { - "values": [{ - "name": { - "value": "tester" - } - }, - { - "name": { - "value": "engineer" - } - }, - { - "name": { - "value": "manager" - } - } - ], - "name": "position" - }, - { - "values": [{ - "name": { - "value": "blue" - } - }, - { - "name": { - "value": "red" - } - }, - { - "name": { - "value": "rocket" - } - } - ], - "name": "myColors" - }, - { - "values": [{ - "name": { - "value": "blue" - } - }, - { - "name": { - "value": "red" - } - }, - { - "name": { - "value": "rocket" - } - } - ], - "name": "customColor" - }, - { - "values": [{ - "name": { - "value": "flower city" - } - }, - { - "name": { - "value": "temple city" - } - }, - { - "name": { - "value": "ramapuram" - } - }, - { - "name": { - "value": "guindy" - } - }, - { - "name": { - "value": "porur" - } - } - ], - "name": "myCustomCities" - }, - { - "values": [{ - "name": { - "value": "flower city" - } - }, - { - "name": { - "value": "temple city" - } - }, - { - "name": { - "value": "ramapuram" - } - }, - { - "name": { - "value": "guindy" - } - }, - { - "name": { - "value": "porur" - } - } - ], - "name": "enGBUSCommon" - } - ] - } - }, - "version": "18" -} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/display/confirm_city_apl_display/document.json b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/display/confirm_city_apl_display/document.json deleted file mode 100644 index 741e1a5f..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/display/confirm_city_apl_display/document.json +++ /dev/null @@ -1,358 +0,0 @@ -{ - "type": "APL", - "version": "1.1", - "settings": {}, - "theme": "dark", - "import": [ - { - "name": "alexa-layouts", - "version": "1.0.0" - } - ], - "resources": [ - { - "description": "Stock color for the light theme", - "colors": { - "colorTextPrimary": "#151920" - } - }, - { - "description": "Stock color for the dark theme", - "when": "${viewport.theme == 'dark'}", - "colors": { - "colorTextPrimary": "#f0f1ef" - } - }, - { - "description": "Standard font sizes", - "dimensions": { - "textSizeBody": 48, - "textSizePrimary": 27, - "textSizeSecondary": 23, - "textSizeDetails": 20, - "textSizeSecondaryHint": 25 - } - }, - { - "description": "Common spacing values", - "dimensions": { - "spacingThin": 6, - "spacingSmall": 12, - "spacingMedium": 24, - "spacingLarge": 48, - "spacingExtraLarge": 72 - } - }, - { - "description": "Common margins and padding", - "dimensions": { - "marginTop": 40, - "marginLeft": 60, - "marginRight": 60, - "marginBottom": 40 - } - } - ], - "styles": { - "textStyleBase": { - "description": "Base font description; set color", - "values": [ - { - "color": "@colorTextPrimary" - } - ] - }, - "textStyleBase0": { - "description": "Thin version of basic font", - "extend": "textStyleBase", - "values": { - "fontWeight": "100" - } - }, - "textStyleBase1": { - "description": "Light version of basic font", - "extend": "textStyleBase", - "values": { - "fontWeight": "300" - } - }, - "textStyleBase2": { - "description": "Regular version of basic font", - "extend": "textStyleBase", - "values": { - "fontWeight": "500" - } - }, - "mixinBody": { - "values": { - "fontSize": "@textSizeBody" - } - }, - "mixinPrimary": { - "values": { - "fontSize": "@textSizePrimary" - } - }, - "mixinDetails": { - "values": { - "fontSize": "@textSizeDetails" - } - }, - "mixinSecondary": { - "values": { - "fontSize": "@textSizeSecondary" - } - }, - "textStylePrimary": { - "extend": [ - "textStyleBase1", - "mixinPrimary" - ] - }, - "textStyleSecondary": { - "extend": [ - "textStyleBase0", - "mixinSecondary" - ] - }, - "textStyleBody": { - "extend": [ - "textStyleBase1", - "mixinBody" - ] - }, - "textStyleSecondaryHint": { - "values": { - "fontFamily": "Bookerly", - "fontStyle": "italic", - "fontSize": "@textSizeSecondaryHint", - "color": "@colorTextPrimary" - } - }, - "textStyleDetails": { - "extend": [ - "textStyleBase2", - "mixinDetails" - ] - } - }, - "onMount": [], - "graphics": {}, - "commands": {}, - "layouts": { - "ListTemplate1": { - "parameters": [ - "backgroundImage", - "title", - "logo", - "hintText", - "listData" - ], - "item": [ - { - "type": "Container", - "width": "100vw", - "height": "100vh", - "direction": "column", - "items": [ - { - "type": "Image", - "source": "${backgroundImage}", - "scale": "best-fill", - "width": "100vw", - "height": "100vh", - "position": "absolute" - }, - { - "type": "AlexaHeader", - "headerTitle": "${title}", - "headerAttributionImage": "${logo}" - }, - { - "type": "Sequence", - "grow": 1, - "height": "80vh", - "scrollDirection": "vertical", - "paddingLeft": "@marginLeft", - "paddingRight": "@marginRight", - "data": "${listData}", - "numbered": true, - "items": [ - { - "type": "VerticalListItem", - "image": "${data.image.sources[0].url}", - "primaryText": "${data.textContent.primaryText.text}", - "secondaryText": "${data.textContent.secondaryText.text}", - "tertiaryText": "${data.textContent.tertiaryText.text}" - } - ] - } - ] - } - ] - }, - "VerticalListItem": { - "parameters": [ - "primaryText", - "secondaryText", - "tertiaryText", - "image" - ], - "item": [ - { - "when": "${viewport.shape == 'round'}", - "type": "Container", - "direction": "row", - "height": 200, - "width": 500, - "alignItems": "center", - "items": [ - { - "type": "Text", - "text": "${ordinal}", - "paddingBottom": "20dp", - "color": "white", - "spacing": "5dp" - }, - { - "type": "Image", - "when": "${image}", - "source": "${image}", - "height": 150, - "width": 150, - "spacing": 15, - "scale": "best-fit", - "align": "top" - }, - { - "type": "Container", - "direction": "column", - "spacing": 25, - "items": [ - { - "type": "Text", - "text": "${primaryText}", - "style": "textStyleDetail", - "grow": 1, - "shrink": 1, - "fontWeight": "300", - "maxLines": 1 - }, - { - "type": "Text", - "text": "${secondaryText}", - "style": "textStyleCaption", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - }, - { - "type": "Text", - "text": "${tertiaryText}", - "style": "textStyleDetails", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - } - ] - } - ] - }, - { - "type": "Container", - "direction": "row", - "height": 125, - "width": 800, - "alignItems": "center", - "items": [ - { - "type": "Text", - "text": "${ordinal}", - "paddingBottom": "20dp", - "color": "white", - "spacing": "5dp" - }, - { - "type": "Image", - "when": "${image}", - "source": "${image}", - "height": 100, - "width": 100, - "align": "top", - "spacing": 50, - "scale": "best-fit" - }, - { - "type": "Container", - "spacing": 30, - "direction": "column", - "items": [ - { - "type": "Text", - "text": "${primaryText}", - "style": "textStyleBody", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - }, - { - "type": "Text", - "text": "${secondaryText}", - "style": "textStyleDetails", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - } - ] - }, - { - "type": "Text", - "text": "${tertiaryText}", - "style": "textStyleBody", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "textAlign": "right", - "maxLines": 1 - } - ] - } - ] - } - }, - "mainTemplate": { - "parameters": [ - "payload" - ], - "item": [ - { - "type": "Container", - "id": "BookCabSimpleDialogAPL", - "items": [ - { - "type": "TouchWrapper", - "onPress": { - "type": "SendEvent", - "arguments": [ - "delegateToColtraneOld" - ] - }, - "item": { - "type": "Text", - "id": "BookCabSimpleDialogAPL", - "paddingTop": "100", - "paddingLeft": "100", - "color": "green", - "size": 50, - "text": "which city ?" - } - } - ] - } - ] - } -} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/display/confirm_date_apl_display/document.json b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/display/confirm_date_apl_display/document.json deleted file mode 100644 index 9ff71e5c..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/display/confirm_date_apl_display/document.json +++ /dev/null @@ -1,358 +0,0 @@ -{ - "type": "APL", - "version": "1.1", - "settings": {}, - "theme": "dark", - "import": [ - { - "name": "alexa-layouts", - "version": "1.0.0" - } - ], - "resources": [ - { - "description": "Stock color for the light theme", - "colors": { - "colorTextPrimary": "#151920" - } - }, - { - "description": "Stock color for the dark theme", - "when": "${viewport.theme == 'dark'}", - "colors": { - "colorTextPrimary": "#f0f1ef" - } - }, - { - "description": "Standard font sizes", - "dimensions": { - "textSizeBody": 48, - "textSizePrimary": 27, - "textSizeSecondary": 23, - "textSizeDetails": 20, - "textSizeSecondaryHint": 25 - } - }, - { - "description": "Common spacing values", - "dimensions": { - "spacingThin": 6, - "spacingSmall": 12, - "spacingMedium": 24, - "spacingLarge": 48, - "spacingExtraLarge": 72 - } - }, - { - "description": "Common margins and padding", - "dimensions": { - "marginTop": 40, - "marginLeft": 60, - "marginRight": 60, - "marginBottom": 40 - } - } - ], - "styles": { - "textStyleBase": { - "description": "Base font description; set color", - "values": [ - { - "color": "@colorTextPrimary" - } - ] - }, - "textStyleBase0": { - "description": "Thin version of basic font", - "extend": "textStyleBase", - "values": { - "fontWeight": "100" - } - }, - "textStyleBase1": { - "description": "Light version of basic font", - "extend": "textStyleBase", - "values": { - "fontWeight": "300" - } - }, - "textStyleBase2": { - "description": "Regular version of basic font", - "extend": "textStyleBase", - "values": { - "fontWeight": "500" - } - }, - "mixinBody": { - "values": { - "fontSize": "@textSizeBody" - } - }, - "mixinPrimary": { - "values": { - "fontSize": "@textSizePrimary" - } - }, - "mixinDetails": { - "values": { - "fontSize": "@textSizeDetails" - } - }, - "mixinSecondary": { - "values": { - "fontSize": "@textSizeSecondary" - } - }, - "textStylePrimary": { - "extend": [ - "textStyleBase1", - "mixinPrimary" - ] - }, - "textStyleSecondary": { - "extend": [ - "textStyleBase0", - "mixinSecondary" - ] - }, - "textStyleBody": { - "extend": [ - "textStyleBase1", - "mixinBody" - ] - }, - "textStyleSecondaryHint": { - "values": { - "fontFamily": "Bookerly", - "fontStyle": "italic", - "fontSize": "@textSizeSecondaryHint", - "color": "@colorTextPrimary" - } - }, - "textStyleDetails": { - "extend": [ - "textStyleBase2", - "mixinDetails" - ] - } - }, - "onMount": [], - "graphics": {}, - "commands": {}, - "layouts": { - "ListTemplate1": { - "parameters": [ - "backgroundImage", - "title", - "logo", - "hintText", - "listData" - ], - "item": [ - { - "type": "Container", - "width": "100vw", - "height": "100vh", - "direction": "column", - "items": [ - { - "type": "Image", - "source": "${backgroundImage}", - "scale": "best-fill", - "width": "100vw", - "height": "100vh", - "position": "absolute" - }, - { - "type": "AlexaHeader", - "headerTitle": "${title}", - "headerAttributionImage": "${logo}" - }, - { - "type": "Sequence", - "grow": 1, - "height": "80vh", - "scrollDirection": "vertical", - "paddingLeft": "@marginLeft", - "paddingRight": "@marginRight", - "data": "${listData}", - "numbered": true, - "items": [ - { - "type": "VerticalListItem", - "image": "${data.image.sources[0].url}", - "primaryText": "${data.textContent.primaryText.text}", - "secondaryText": "${data.textContent.secondaryText.text}", - "tertiaryText": "${data.textContent.tertiaryText.text}" - } - ] - } - ] - } - ] - }, - "VerticalListItem": { - "parameters": [ - "primaryText", - "secondaryText", - "tertiaryText", - "image" - ], - "item": [ - { - "when": "${viewport.shape == 'round'}", - "type": "Container", - "direction": "row", - "height": 200, - "width": 500, - "alignItems": "center", - "items": [ - { - "type": "Text", - "text": "${ordinal}", - "paddingBottom": "20dp", - "color": "white", - "spacing": "5dp" - }, - { - "type": "Image", - "when": "${image}", - "source": "${image}", - "height": 150, - "width": 150, - "spacing": 15, - "scale": "best-fit", - "align": "top" - }, - { - "type": "Container", - "direction": "column", - "spacing": 25, - "items": [ - { - "type": "Text", - "text": "${primaryText}", - "style": "textStyleDetail", - "grow": 1, - "shrink": 1, - "fontWeight": "300", - "maxLines": 1 - }, - { - "type": "Text", - "text": "${secondaryText}", - "style": "textStyleCaption", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - }, - { - "type": "Text", - "text": "${tertiaryText}", - "style": "textStyleDetails", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - } - ] - } - ] - }, - { - "type": "Container", - "direction": "row", - "height": 125, - "width": 800, - "alignItems": "center", - "items": [ - { - "type": "Text", - "text": "${ordinal}", - "paddingBottom": "20dp", - "color": "white", - "spacing": "5dp" - }, - { - "type": "Image", - "when": "${image}", - "source": "${image}", - "height": 100, - "width": 100, - "align": "top", - "spacing": 50, - "scale": "best-fit" - }, - { - "type": "Container", - "spacing": 30, - "direction": "column", - "items": [ - { - "type": "Text", - "text": "${primaryText}", - "style": "textStyleBody", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - }, - { - "type": "Text", - "text": "${secondaryText}", - "style": "textStyleDetails", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - } - ] - }, - { - "type": "Text", - "text": "${tertiaryText}", - "style": "textStyleBody", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "textAlign": "right", - "maxLines": 1 - } - ] - } - ] - } - }, - "mainTemplate": { - "parameters": [ - "payload" - ], - "item": [ - { - "type": "Container", - "id": "BookCabSimpleDialogAPL", - "items": [ - { - "type": "TouchWrapper", - "onPress": { - "type": "SendEvent", - "arguments": [ - "delegateToColtraneOld" - ] - }, - "item": { - "type": "Text", - "id": "BookCabSimpleDialogAPL", - "paddingTop": "100", - "paddingLeft": "100", - "color": "green", - "size": 50, - "text": "which date ?" - } - } - ] - } - ] - } - } \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/display/confirm_weather_apla_display/document.json b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/display/confirm_weather_apla_display/document.json deleted file mode 100644 index 1974945a..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/display/confirm_weather_apla_display/document.json +++ /dev/null @@ -1,412 +0,0 @@ -{ - "type": "APL", - "version": "1.1", - "settings": {}, - "theme": "dark", - "import": [ - { - "name": "alexa-layouts", - "version": "1.0.0" - } - ], - "resources": [ - { - "description": "Stock color for the light theme", - "colors": { - "colorTextPrimary": "#151920" - } - }, - { - "description": "Stock color for the dark theme", - "when": "${viewport.theme == 'dark'}", - "colors": { - "colorTextPrimary": "#f0f1ef" - } - }, - { - "description": "Standard font sizes", - "dimensions": { - "textSizeBody": 48, - "textSizePrimary": 27, - "textSizeSecondary": 23, - "textSizeDetails": 20, - "textSizeSecondaryHint": 25 - } - }, - { - "description": "Common spacing values", - "dimensions": { - "spacingThin": 6, - "spacingSmall": 12, - "spacingMedium": 24, - "spacingLarge": 48, - "spacingExtraLarge": 72 - } - }, - { - "description": "Common margins and padding", - "dimensions": { - "marginTop": 40, - "marginLeft": 60, - "marginRight": 60, - "marginBottom": 40 - } - } - ], - "styles": { - "textStyleBase": { - "description": "Base font description; set color", - "values": [ - { - "color": "@colorTextPrimary" - } - ] - }, - "textStyleBase0": { - "description": "Thin version of basic font", - "extend": "textStyleBase", - "values": { - "fontWeight": "100" - } - }, - "textStyleBase1": { - "description": "Light version of basic font", - "extend": "textStyleBase", - "values": { - "fontWeight": "300" - } - }, - "textStyleBase2": { - "description": "Regular version of basic font", - "extend": "textStyleBase", - "values": { - "fontWeight": "500" - } - }, - "mixinBody": { - "values": { - "fontSize": "@textSizeBody" - } - }, - "mixinPrimary": { - "values": { - "fontSize": "@textSizePrimary" - } - }, - "mixinDetails": { - "values": { - "fontSize": "@textSizeDetails" - } - }, - "mixinSecondary": { - "values": { - "fontSize": "@textSizeSecondary" - } - }, - "textStylePrimary": { - "extend": [ - "textStyleBase1", - "mixinPrimary" - ] - }, - "textStyleSecondary": { - "extend": [ - "textStyleBase0", - "mixinSecondary" - ] - }, - "textStyleBody": { - "extend": [ - "textStyleBase1", - "mixinBody" - ] - }, - "textStyleSecondaryHint": { - "values": { - "fontFamily": "Bookerly", - "fontStyle": "italic", - "fontSize": "@textSizeSecondaryHint", - "color": "@colorTextPrimary" - } - }, - "textStyleDetails": { - "extend": [ - "textStyleBase2", - "mixinDetails" - ] - } - }, - "onMount": [], - "graphics": {}, - "commands": {}, - "layouts": { - "ListTemplate1": { - "parameters": [ - "backgroundImage", - "title", - "logo", - "hintText", - "listData" - ], - "item": [ - { - "type": "Container", - "width": "100vw", - "height": "100vh", - "direction": "column", - "items": [ - { - "type": "Image", - "source": "${backgroundImage}", - "scale": "best-fill", - "width": "100vw", - "height": "100vh", - "position": "absolute" - }, - { - "type": "AlexaHeader", - "headerTitle": "${title}", - "headerAttributionImage": "${logo}" - }, - { - "type": "Sequence", - "grow": 1, - "height": "80vh", - "scrollDirection": "vertical", - "paddingLeft": "@marginLeft", - "paddingRight": "@marginRight", - "data": "${listData}", - "numbered": true, - "items": [ - { - "type": "VerticalListItem", - "image": "${data.image.sources[0].url}", - "primaryText": "${data.textContent.primaryText.text}", - "secondaryText": "${data.textContent.secondaryText.text}", - "tertiaryText": "${data.textContent.tertiaryText.text}" - } - ] - } - ] - } - ] - }, - "VerticalListItem": { - "parameters": [ - "primaryText", - "secondaryText", - "tertiaryText", - "image" - ], - "item": [ - { - "when": "${viewport.shape == 'round'}", - "type": "Container", - "direction": "row", - "height": 200, - "width": 500, - "alignItems": "center", - "items": [ - { - "type": "Text", - "text": "${ordinal}", - "paddingBottom": "20dp", - "color": "white", - "spacing": "5dp" - }, - { - "type": "Image", - "when": "${image}", - "source": "${image}", - "height": 150, - "width": 150, - "spacing": 15, - "scale": "best-fit", - "align": "top" - }, - { - "type": "Container", - "direction": "column", - "spacing": 25, - "items": [ - { - "type": "Text", - "text": "${primaryText}", - "style": "textStyleDetail", - "grow": 1, - "shrink": 1, - "fontWeight": "300", - "maxLines": 1 - }, - { - "type": "Text", - "text": "${secondaryText}", - "style": "textStyleCaption", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - }, - { - "type": "Text", - "text": "${tertiaryText}", - "style": "textStyleDetails", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - } - ] - } - ] - }, - { - "type": "Container", - "direction": "row", - "height": 125, - "width": 800, - "alignItems": "center", - "items": [ - { - "type": "Text", - "text": "${ordinal}", - "paddingBottom": "20dp", - "color": "white", - "spacing": "5dp" - }, - { - "type": "Image", - "when": "${image}", - "source": "${image}", - "height": 100, - "width": 100, - "align": "top", - "spacing": 50, - "scale": "best-fit" - }, - { - "type": "Container", - "spacing": 30, - "direction": "column", - "items": [ - { - "type": "Text", - "text": "${primaryText}", - "style": "textStyleBody", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - }, - { - "type": "Text", - "text": "${secondaryText}", - "style": "textStyleDetails", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - } - ] - }, - { - "type": "Text", - "text": "${tertiaryText}", - "style": "textStyleBody", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "textAlign": "right", - "maxLines": 1 - } - ] - } - ] - } - }, - "mainTemplate": { - "parameters": [ - "payload" - ], - "item": [ - { - "type": "Container", - "id": "BookCabSimpleDialogAPL", - "items": [ - { - "type": "TouchWrapper", - "onPress": { - "type": "SendEvent", - "arguments": [ - "delegateToSkillNew" - ] - }, - "item": { - "type": "Text", - "id": "BookCabSimpleDialogAPL", - "paddingTop": "100", - "paddingLeft": "100", - "color": "green", - "size": 50, - "text": "delegateToSkillNew" - } - }, - { - "type": "TouchWrapper", - "onPress": { - "type": "SendEvent", - "arguments": [ - "delegateToSkillOld" - ] - }, - "item": { - "type": "Text", - "id": "BookCabSimpleDialogAPL", - "paddingTop": "100", - "paddingLeft": "100", - "color": "green", - "size": 50, - "text": "delegateToSkillOld" - } - }, - { - "type": "TouchWrapper", - "onPress": { - "type": "SendEvent", - "arguments": [ - "delegateToColtraneNew" - ] - }, - "item": { - "type": "Text", - "id": "BookCabSimpleDialogAPL", - "paddingTop": "100", - "paddingLeft": "100", - "color": "green", - "size": 50, - "text": "delegateToColtraneNew" - } - }, - { - "type": "TouchWrapper", - "onPress": { - "type": "SendEvent", - "arguments": [ - "delegateToColtraneOld" - ] - }, - "item": { - "type": "Text", - "id": "BookCabSimpleDialogAPL", - "paddingTop": "100", - "paddingLeft": "100", - "color": "green", - "size": 50, - "text": "delegateToColtraneOld" - } - } - ] - } - ] - } -} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/display/display_de_apl/document.json b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/display/display_de_apl/document.json deleted file mode 100644 index 741e1a5f..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/display/display_de_apl/document.json +++ /dev/null @@ -1,358 +0,0 @@ -{ - "type": "APL", - "version": "1.1", - "settings": {}, - "theme": "dark", - "import": [ - { - "name": "alexa-layouts", - "version": "1.0.0" - } - ], - "resources": [ - { - "description": "Stock color for the light theme", - "colors": { - "colorTextPrimary": "#151920" - } - }, - { - "description": "Stock color for the dark theme", - "when": "${viewport.theme == 'dark'}", - "colors": { - "colorTextPrimary": "#f0f1ef" - } - }, - { - "description": "Standard font sizes", - "dimensions": { - "textSizeBody": 48, - "textSizePrimary": 27, - "textSizeSecondary": 23, - "textSizeDetails": 20, - "textSizeSecondaryHint": 25 - } - }, - { - "description": "Common spacing values", - "dimensions": { - "spacingThin": 6, - "spacingSmall": 12, - "spacingMedium": 24, - "spacingLarge": 48, - "spacingExtraLarge": 72 - } - }, - { - "description": "Common margins and padding", - "dimensions": { - "marginTop": 40, - "marginLeft": 60, - "marginRight": 60, - "marginBottom": 40 - } - } - ], - "styles": { - "textStyleBase": { - "description": "Base font description; set color", - "values": [ - { - "color": "@colorTextPrimary" - } - ] - }, - "textStyleBase0": { - "description": "Thin version of basic font", - "extend": "textStyleBase", - "values": { - "fontWeight": "100" - } - }, - "textStyleBase1": { - "description": "Light version of basic font", - "extend": "textStyleBase", - "values": { - "fontWeight": "300" - } - }, - "textStyleBase2": { - "description": "Regular version of basic font", - "extend": "textStyleBase", - "values": { - "fontWeight": "500" - } - }, - "mixinBody": { - "values": { - "fontSize": "@textSizeBody" - } - }, - "mixinPrimary": { - "values": { - "fontSize": "@textSizePrimary" - } - }, - "mixinDetails": { - "values": { - "fontSize": "@textSizeDetails" - } - }, - "mixinSecondary": { - "values": { - "fontSize": "@textSizeSecondary" - } - }, - "textStylePrimary": { - "extend": [ - "textStyleBase1", - "mixinPrimary" - ] - }, - "textStyleSecondary": { - "extend": [ - "textStyleBase0", - "mixinSecondary" - ] - }, - "textStyleBody": { - "extend": [ - "textStyleBase1", - "mixinBody" - ] - }, - "textStyleSecondaryHint": { - "values": { - "fontFamily": "Bookerly", - "fontStyle": "italic", - "fontSize": "@textSizeSecondaryHint", - "color": "@colorTextPrimary" - } - }, - "textStyleDetails": { - "extend": [ - "textStyleBase2", - "mixinDetails" - ] - } - }, - "onMount": [], - "graphics": {}, - "commands": {}, - "layouts": { - "ListTemplate1": { - "parameters": [ - "backgroundImage", - "title", - "logo", - "hintText", - "listData" - ], - "item": [ - { - "type": "Container", - "width": "100vw", - "height": "100vh", - "direction": "column", - "items": [ - { - "type": "Image", - "source": "${backgroundImage}", - "scale": "best-fill", - "width": "100vw", - "height": "100vh", - "position": "absolute" - }, - { - "type": "AlexaHeader", - "headerTitle": "${title}", - "headerAttributionImage": "${logo}" - }, - { - "type": "Sequence", - "grow": 1, - "height": "80vh", - "scrollDirection": "vertical", - "paddingLeft": "@marginLeft", - "paddingRight": "@marginRight", - "data": "${listData}", - "numbered": true, - "items": [ - { - "type": "VerticalListItem", - "image": "${data.image.sources[0].url}", - "primaryText": "${data.textContent.primaryText.text}", - "secondaryText": "${data.textContent.secondaryText.text}", - "tertiaryText": "${data.textContent.tertiaryText.text}" - } - ] - } - ] - } - ] - }, - "VerticalListItem": { - "parameters": [ - "primaryText", - "secondaryText", - "tertiaryText", - "image" - ], - "item": [ - { - "when": "${viewport.shape == 'round'}", - "type": "Container", - "direction": "row", - "height": 200, - "width": 500, - "alignItems": "center", - "items": [ - { - "type": "Text", - "text": "${ordinal}", - "paddingBottom": "20dp", - "color": "white", - "spacing": "5dp" - }, - { - "type": "Image", - "when": "${image}", - "source": "${image}", - "height": 150, - "width": 150, - "spacing": 15, - "scale": "best-fit", - "align": "top" - }, - { - "type": "Container", - "direction": "column", - "spacing": 25, - "items": [ - { - "type": "Text", - "text": "${primaryText}", - "style": "textStyleDetail", - "grow": 1, - "shrink": 1, - "fontWeight": "300", - "maxLines": 1 - }, - { - "type": "Text", - "text": "${secondaryText}", - "style": "textStyleCaption", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - }, - { - "type": "Text", - "text": "${tertiaryText}", - "style": "textStyleDetails", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - } - ] - } - ] - }, - { - "type": "Container", - "direction": "row", - "height": 125, - "width": 800, - "alignItems": "center", - "items": [ - { - "type": "Text", - "text": "${ordinal}", - "paddingBottom": "20dp", - "color": "white", - "spacing": "5dp" - }, - { - "type": "Image", - "when": "${image}", - "source": "${image}", - "height": 100, - "width": 100, - "align": "top", - "spacing": 50, - "scale": "best-fit" - }, - { - "type": "Container", - "spacing": 30, - "direction": "column", - "items": [ - { - "type": "Text", - "text": "${primaryText}", - "style": "textStyleBody", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - }, - { - "type": "Text", - "text": "${secondaryText}", - "style": "textStyleDetails", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - } - ] - }, - { - "type": "Text", - "text": "${tertiaryText}", - "style": "textStyleBody", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "textAlign": "right", - "maxLines": 1 - } - ] - } - ] - } - }, - "mainTemplate": { - "parameters": [ - "payload" - ], - "item": [ - { - "type": "Container", - "id": "BookCabSimpleDialogAPL", - "items": [ - { - "type": "TouchWrapper", - "onPress": { - "type": "SendEvent", - "arguments": [ - "delegateToColtraneOld" - ] - }, - "item": { - "type": "Text", - "id": "BookCabSimpleDialogAPL", - "paddingTop": "100", - "paddingLeft": "100", - "color": "green", - "size": 50, - "text": "which city ?" - } - } - ] - } - ] - } -} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/display/dummyLastScreen/datasources/default.json b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/display/dummyLastScreen/datasources/default.json deleted file mode 100644 index 9e26dfee..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/display/dummyLastScreen/datasources/default.json +++ /dev/null @@ -1 +0,0 @@ -{} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/display/dummyLastScreen/document.json b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/display/dummyLastScreen/document.json deleted file mode 100644 index d8790b65..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/display/dummyLastScreen/document.json +++ /dev/null @@ -1 +0,0 @@ -{"type":"APL","version":"1.1","settings":{},"theme":"dark","import":[{"name":"alexa-layouts","version":"1.0.0"}],"resources":[{"description":"Stock color for the light theme","colors":{"colorTextPrimary":"#151920"}},{"description":"Stock color for the dark theme","when":"${viewport.theme == 'dark'}","colors":{"colorTextPrimary":"#f0f1ef"}},{"description":"Standard font sizes","dimensions":{"textSizeBody":48,"textSizePrimary":27,"textSizeSecondary":23,"textSizeDetails":20,"textSizeSecondaryHint":25}},{"description":"Common spacing values","dimensions":{"spacingThin":6,"spacingSmall":12,"spacingMedium":24,"spacingLarge":48,"spacingExtraLarge":72}},{"description":"Common margins and padding","dimensions":{"marginTop":40,"marginLeft":60,"marginRight":60,"marginBottom":40}}],"styles":{"textStyleBase":{"description":"Base font description; set color","values":[{"color":"@colorTextPrimary"}]},"textStyleBase0":{"description":"Thin version of basic font","extend":"textStyleBase","values":{"fontWeight":"100"}},"textStyleBase1":{"description":"Light version of basic font","extend":"textStyleBase","values":{"fontWeight":"300"}},"textStyleBase2":{"description":"Regular version of basic font","extend":"textStyleBase","values":{"fontWeight":"500"}},"mixinBody":{"values":{"fontSize":"@textSizeBody"}},"mixinPrimary":{"values":{"fontSize":"@textSizePrimary"}},"mixinDetails":{"values":{"fontSize":"@textSizeDetails"}},"mixinSecondary":{"values":{"fontSize":"@textSizeSecondary"}},"textStylePrimary":{"extend":["textStyleBase1","mixinPrimary"]},"textStyleSecondary":{"extend":["textStyleBase0","mixinSecondary"]},"textStyleBody":{"extend":["textStyleBase1","mixinBody"]},"textStyleSecondaryHint":{"values":{"fontFamily":"Bookerly","fontStyle":"italic","fontSize":"@textSizeSecondaryHint","color":"@colorTextPrimary"}},"textStyleDetails":{"extend":["textStyleBase2","mixinDetails"]}},"onMount":[],"graphics":{},"commands":{},"layouts":{"ListTemplate1":{"parameters":["backgroundImage","title","logo","hintText","listData"],"item":[{"type":"Container","width":"100vw","height":"100vh","direction":"column","items":[{"type":"Image","source":"${backgroundImage}","scale":"best-fill","width":"100vw","height":"100vh","position":"absolute"},{"type":"AlexaHeader","headerTitle":"${title}","headerAttributionImage":"${logo}"},{"type":"Sequence","grow":1,"height":"80vh","scrollDirection":"vertical","paddingLeft":"@marginLeft","paddingRight":"@marginRight","data":"${listData}","numbered":true,"items":[{"type":"VerticalListItem","image":"${data.image.sources[0].url}","primaryText":"${data.textContent.primaryText.text}","secondaryText":"${data.textContent.secondaryText.text}","tertiaryText":"${data.textContent.tertiaryText.text}"}]}]}]},"VerticalListItem":{"parameters":["primaryText","secondaryText","tertiaryText","image"],"item":[{"when":"${viewport.shape == 'round'}","type":"Container","direction":"row","height":200,"width":500,"alignItems":"center","items":[{"type":"Text","text":"${ordinal}","paddingBottom":"20dp","color":"white","spacing":"5dp"},{"type":"Image","when":"${image}","source":"${image}","height":150,"width":150,"spacing":15,"scale":"best-fit","align":"top"},{"type":"Container","direction":"column","spacing":25,"items":[{"type":"Text","text":"${primaryText}","style":"textStyleDetail","grow":1,"shrink":1,"fontWeight":"300","maxLines":1},{"type":"Text","text":"${secondaryText}","style":"textStyleCaption","fontWeight":"300","grow":1,"shrink":1,"maxLines":1},{"type":"Text","text":"${tertiaryText}","style":"textStyleDetails","fontWeight":"300","grow":1,"shrink":1,"maxLines":1}]}]},{"type":"Container","direction":"row","height":125,"width":800,"alignItems":"center","items":[{"type":"Text","text":"${ordinal}","paddingBottom":"20dp","color":"white","spacing":"5dp"},{"type":"Image","when":"${image}","source":"${image}","height":100,"width":100,"align":"top","spacing":50,"scale":"best-fit"},{"type":"Container","spacing":30,"direction":"column","items":[{"type":"Text","text":"${primaryText}","style":"textStyleBody","fontWeight":"300","grow":1,"shrink":1,"maxLines":1},{"type":"Text","text":"${secondaryText}","style":"textStyleDetails","fontWeight":"300","grow":1,"shrink":1,"maxLines":1}]},{"type":"Text","text":"${tertiaryText}","style":"textStyleBody","fontWeight":"300","grow":1,"shrink":1,"textAlign":"right","maxLines":1}]}]}},"mainTemplate":{"parameters":["payload"],"item":[{"type":"Container","id":"BookCabSimpleDialogAPL","items":[[],{"type":"Text","id":"BookCabSimpleDialogAPL","paddingTop":"100","paddingLeft":"100","color":"green","size":50,"text":"Blah Blah Blaa !!"}]}]}} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/display/dummyLastScreen/sources/default.json b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/display/dummyLastScreen/sources/default.json deleted file mode 100644 index 9e26dfee..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/display/dummyLastScreen/sources/default.json +++ /dev/null @@ -1 +0,0 @@ -{} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/display/request_city_apl_display/document.json b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/display/request_city_apl_display/document.json deleted file mode 100644 index 741e1a5f..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/display/request_city_apl_display/document.json +++ /dev/null @@ -1,358 +0,0 @@ -{ - "type": "APL", - "version": "1.1", - "settings": {}, - "theme": "dark", - "import": [ - { - "name": "alexa-layouts", - "version": "1.0.0" - } - ], - "resources": [ - { - "description": "Stock color for the light theme", - "colors": { - "colorTextPrimary": "#151920" - } - }, - { - "description": "Stock color for the dark theme", - "when": "${viewport.theme == 'dark'}", - "colors": { - "colorTextPrimary": "#f0f1ef" - } - }, - { - "description": "Standard font sizes", - "dimensions": { - "textSizeBody": 48, - "textSizePrimary": 27, - "textSizeSecondary": 23, - "textSizeDetails": 20, - "textSizeSecondaryHint": 25 - } - }, - { - "description": "Common spacing values", - "dimensions": { - "spacingThin": 6, - "spacingSmall": 12, - "spacingMedium": 24, - "spacingLarge": 48, - "spacingExtraLarge": 72 - } - }, - { - "description": "Common margins and padding", - "dimensions": { - "marginTop": 40, - "marginLeft": 60, - "marginRight": 60, - "marginBottom": 40 - } - } - ], - "styles": { - "textStyleBase": { - "description": "Base font description; set color", - "values": [ - { - "color": "@colorTextPrimary" - } - ] - }, - "textStyleBase0": { - "description": "Thin version of basic font", - "extend": "textStyleBase", - "values": { - "fontWeight": "100" - } - }, - "textStyleBase1": { - "description": "Light version of basic font", - "extend": "textStyleBase", - "values": { - "fontWeight": "300" - } - }, - "textStyleBase2": { - "description": "Regular version of basic font", - "extend": "textStyleBase", - "values": { - "fontWeight": "500" - } - }, - "mixinBody": { - "values": { - "fontSize": "@textSizeBody" - } - }, - "mixinPrimary": { - "values": { - "fontSize": "@textSizePrimary" - } - }, - "mixinDetails": { - "values": { - "fontSize": "@textSizeDetails" - } - }, - "mixinSecondary": { - "values": { - "fontSize": "@textSizeSecondary" - } - }, - "textStylePrimary": { - "extend": [ - "textStyleBase1", - "mixinPrimary" - ] - }, - "textStyleSecondary": { - "extend": [ - "textStyleBase0", - "mixinSecondary" - ] - }, - "textStyleBody": { - "extend": [ - "textStyleBase1", - "mixinBody" - ] - }, - "textStyleSecondaryHint": { - "values": { - "fontFamily": "Bookerly", - "fontStyle": "italic", - "fontSize": "@textSizeSecondaryHint", - "color": "@colorTextPrimary" - } - }, - "textStyleDetails": { - "extend": [ - "textStyleBase2", - "mixinDetails" - ] - } - }, - "onMount": [], - "graphics": {}, - "commands": {}, - "layouts": { - "ListTemplate1": { - "parameters": [ - "backgroundImage", - "title", - "logo", - "hintText", - "listData" - ], - "item": [ - { - "type": "Container", - "width": "100vw", - "height": "100vh", - "direction": "column", - "items": [ - { - "type": "Image", - "source": "${backgroundImage}", - "scale": "best-fill", - "width": "100vw", - "height": "100vh", - "position": "absolute" - }, - { - "type": "AlexaHeader", - "headerTitle": "${title}", - "headerAttributionImage": "${logo}" - }, - { - "type": "Sequence", - "grow": 1, - "height": "80vh", - "scrollDirection": "vertical", - "paddingLeft": "@marginLeft", - "paddingRight": "@marginRight", - "data": "${listData}", - "numbered": true, - "items": [ - { - "type": "VerticalListItem", - "image": "${data.image.sources[0].url}", - "primaryText": "${data.textContent.primaryText.text}", - "secondaryText": "${data.textContent.secondaryText.text}", - "tertiaryText": "${data.textContent.tertiaryText.text}" - } - ] - } - ] - } - ] - }, - "VerticalListItem": { - "parameters": [ - "primaryText", - "secondaryText", - "tertiaryText", - "image" - ], - "item": [ - { - "when": "${viewport.shape == 'round'}", - "type": "Container", - "direction": "row", - "height": 200, - "width": 500, - "alignItems": "center", - "items": [ - { - "type": "Text", - "text": "${ordinal}", - "paddingBottom": "20dp", - "color": "white", - "spacing": "5dp" - }, - { - "type": "Image", - "when": "${image}", - "source": "${image}", - "height": 150, - "width": 150, - "spacing": 15, - "scale": "best-fit", - "align": "top" - }, - { - "type": "Container", - "direction": "column", - "spacing": 25, - "items": [ - { - "type": "Text", - "text": "${primaryText}", - "style": "textStyleDetail", - "grow": 1, - "shrink": 1, - "fontWeight": "300", - "maxLines": 1 - }, - { - "type": "Text", - "text": "${secondaryText}", - "style": "textStyleCaption", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - }, - { - "type": "Text", - "text": "${tertiaryText}", - "style": "textStyleDetails", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - } - ] - } - ] - }, - { - "type": "Container", - "direction": "row", - "height": 125, - "width": 800, - "alignItems": "center", - "items": [ - { - "type": "Text", - "text": "${ordinal}", - "paddingBottom": "20dp", - "color": "white", - "spacing": "5dp" - }, - { - "type": "Image", - "when": "${image}", - "source": "${image}", - "height": 100, - "width": 100, - "align": "top", - "spacing": 50, - "scale": "best-fit" - }, - { - "type": "Container", - "spacing": 30, - "direction": "column", - "items": [ - { - "type": "Text", - "text": "${primaryText}", - "style": "textStyleBody", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - }, - { - "type": "Text", - "text": "${secondaryText}", - "style": "textStyleDetails", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - } - ] - }, - { - "type": "Text", - "text": "${tertiaryText}", - "style": "textStyleBody", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "textAlign": "right", - "maxLines": 1 - } - ] - } - ] - } - }, - "mainTemplate": { - "parameters": [ - "payload" - ], - "item": [ - { - "type": "Container", - "id": "BookCabSimpleDialogAPL", - "items": [ - { - "type": "TouchWrapper", - "onPress": { - "type": "SendEvent", - "arguments": [ - "delegateToColtraneOld" - ] - }, - "item": { - "type": "Text", - "id": "BookCabSimpleDialogAPL", - "paddingTop": "100", - "paddingLeft": "100", - "color": "green", - "size": 50, - "text": "which city ?" - } - } - ] - } - ] - } -} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/display/request_date_apl_display/document.json b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/display/request_date_apl_display/document.json deleted file mode 100644 index 9ff71e5c..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/display/request_date_apl_display/document.json +++ /dev/null @@ -1,358 +0,0 @@ -{ - "type": "APL", - "version": "1.1", - "settings": {}, - "theme": "dark", - "import": [ - { - "name": "alexa-layouts", - "version": "1.0.0" - } - ], - "resources": [ - { - "description": "Stock color for the light theme", - "colors": { - "colorTextPrimary": "#151920" - } - }, - { - "description": "Stock color for the dark theme", - "when": "${viewport.theme == 'dark'}", - "colors": { - "colorTextPrimary": "#f0f1ef" - } - }, - { - "description": "Standard font sizes", - "dimensions": { - "textSizeBody": 48, - "textSizePrimary": 27, - "textSizeSecondary": 23, - "textSizeDetails": 20, - "textSizeSecondaryHint": 25 - } - }, - { - "description": "Common spacing values", - "dimensions": { - "spacingThin": 6, - "spacingSmall": 12, - "spacingMedium": 24, - "spacingLarge": 48, - "spacingExtraLarge": 72 - } - }, - { - "description": "Common margins and padding", - "dimensions": { - "marginTop": 40, - "marginLeft": 60, - "marginRight": 60, - "marginBottom": 40 - } - } - ], - "styles": { - "textStyleBase": { - "description": "Base font description; set color", - "values": [ - { - "color": "@colorTextPrimary" - } - ] - }, - "textStyleBase0": { - "description": "Thin version of basic font", - "extend": "textStyleBase", - "values": { - "fontWeight": "100" - } - }, - "textStyleBase1": { - "description": "Light version of basic font", - "extend": "textStyleBase", - "values": { - "fontWeight": "300" - } - }, - "textStyleBase2": { - "description": "Regular version of basic font", - "extend": "textStyleBase", - "values": { - "fontWeight": "500" - } - }, - "mixinBody": { - "values": { - "fontSize": "@textSizeBody" - } - }, - "mixinPrimary": { - "values": { - "fontSize": "@textSizePrimary" - } - }, - "mixinDetails": { - "values": { - "fontSize": "@textSizeDetails" - } - }, - "mixinSecondary": { - "values": { - "fontSize": "@textSizeSecondary" - } - }, - "textStylePrimary": { - "extend": [ - "textStyleBase1", - "mixinPrimary" - ] - }, - "textStyleSecondary": { - "extend": [ - "textStyleBase0", - "mixinSecondary" - ] - }, - "textStyleBody": { - "extend": [ - "textStyleBase1", - "mixinBody" - ] - }, - "textStyleSecondaryHint": { - "values": { - "fontFamily": "Bookerly", - "fontStyle": "italic", - "fontSize": "@textSizeSecondaryHint", - "color": "@colorTextPrimary" - } - }, - "textStyleDetails": { - "extend": [ - "textStyleBase2", - "mixinDetails" - ] - } - }, - "onMount": [], - "graphics": {}, - "commands": {}, - "layouts": { - "ListTemplate1": { - "parameters": [ - "backgroundImage", - "title", - "logo", - "hintText", - "listData" - ], - "item": [ - { - "type": "Container", - "width": "100vw", - "height": "100vh", - "direction": "column", - "items": [ - { - "type": "Image", - "source": "${backgroundImage}", - "scale": "best-fill", - "width": "100vw", - "height": "100vh", - "position": "absolute" - }, - { - "type": "AlexaHeader", - "headerTitle": "${title}", - "headerAttributionImage": "${logo}" - }, - { - "type": "Sequence", - "grow": 1, - "height": "80vh", - "scrollDirection": "vertical", - "paddingLeft": "@marginLeft", - "paddingRight": "@marginRight", - "data": "${listData}", - "numbered": true, - "items": [ - { - "type": "VerticalListItem", - "image": "${data.image.sources[0].url}", - "primaryText": "${data.textContent.primaryText.text}", - "secondaryText": "${data.textContent.secondaryText.text}", - "tertiaryText": "${data.textContent.tertiaryText.text}" - } - ] - } - ] - } - ] - }, - "VerticalListItem": { - "parameters": [ - "primaryText", - "secondaryText", - "tertiaryText", - "image" - ], - "item": [ - { - "when": "${viewport.shape == 'round'}", - "type": "Container", - "direction": "row", - "height": 200, - "width": 500, - "alignItems": "center", - "items": [ - { - "type": "Text", - "text": "${ordinal}", - "paddingBottom": "20dp", - "color": "white", - "spacing": "5dp" - }, - { - "type": "Image", - "when": "${image}", - "source": "${image}", - "height": 150, - "width": 150, - "spacing": 15, - "scale": "best-fit", - "align": "top" - }, - { - "type": "Container", - "direction": "column", - "spacing": 25, - "items": [ - { - "type": "Text", - "text": "${primaryText}", - "style": "textStyleDetail", - "grow": 1, - "shrink": 1, - "fontWeight": "300", - "maxLines": 1 - }, - { - "type": "Text", - "text": "${secondaryText}", - "style": "textStyleCaption", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - }, - { - "type": "Text", - "text": "${tertiaryText}", - "style": "textStyleDetails", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - } - ] - } - ] - }, - { - "type": "Container", - "direction": "row", - "height": 125, - "width": 800, - "alignItems": "center", - "items": [ - { - "type": "Text", - "text": "${ordinal}", - "paddingBottom": "20dp", - "color": "white", - "spacing": "5dp" - }, - { - "type": "Image", - "when": "${image}", - "source": "${image}", - "height": 100, - "width": 100, - "align": "top", - "spacing": 50, - "scale": "best-fit" - }, - { - "type": "Container", - "spacing": 30, - "direction": "column", - "items": [ - { - "type": "Text", - "text": "${primaryText}", - "style": "textStyleBody", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - }, - { - "type": "Text", - "text": "${secondaryText}", - "style": "textStyleDetails", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - } - ] - }, - { - "type": "Text", - "text": "${tertiaryText}", - "style": "textStyleBody", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "textAlign": "right", - "maxLines": 1 - } - ] - } - ] - } - }, - "mainTemplate": { - "parameters": [ - "payload" - ], - "item": [ - { - "type": "Container", - "id": "BookCabSimpleDialogAPL", - "items": [ - { - "type": "TouchWrapper", - "onPress": { - "type": "SendEvent", - "arguments": [ - "delegateToColtraneOld" - ] - }, - "item": { - "type": "Text", - "id": "BookCabSimpleDialogAPL", - "paddingTop": "100", - "paddingLeft": "100", - "color": "green", - "size": 50, - "text": "which date ?" - } - } - ] - } - ] - } - } \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/display/weather_success_apl_display/document.json b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/display/weather_success_apl_display/document.json deleted file mode 100644 index 1974945a..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/display/weather_success_apl_display/document.json +++ /dev/null @@ -1,412 +0,0 @@ -{ - "type": "APL", - "version": "1.1", - "settings": {}, - "theme": "dark", - "import": [ - { - "name": "alexa-layouts", - "version": "1.0.0" - } - ], - "resources": [ - { - "description": "Stock color for the light theme", - "colors": { - "colorTextPrimary": "#151920" - } - }, - { - "description": "Stock color for the dark theme", - "when": "${viewport.theme == 'dark'}", - "colors": { - "colorTextPrimary": "#f0f1ef" - } - }, - { - "description": "Standard font sizes", - "dimensions": { - "textSizeBody": 48, - "textSizePrimary": 27, - "textSizeSecondary": 23, - "textSizeDetails": 20, - "textSizeSecondaryHint": 25 - } - }, - { - "description": "Common spacing values", - "dimensions": { - "spacingThin": 6, - "spacingSmall": 12, - "spacingMedium": 24, - "spacingLarge": 48, - "spacingExtraLarge": 72 - } - }, - { - "description": "Common margins and padding", - "dimensions": { - "marginTop": 40, - "marginLeft": 60, - "marginRight": 60, - "marginBottom": 40 - } - } - ], - "styles": { - "textStyleBase": { - "description": "Base font description; set color", - "values": [ - { - "color": "@colorTextPrimary" - } - ] - }, - "textStyleBase0": { - "description": "Thin version of basic font", - "extend": "textStyleBase", - "values": { - "fontWeight": "100" - } - }, - "textStyleBase1": { - "description": "Light version of basic font", - "extend": "textStyleBase", - "values": { - "fontWeight": "300" - } - }, - "textStyleBase2": { - "description": "Regular version of basic font", - "extend": "textStyleBase", - "values": { - "fontWeight": "500" - } - }, - "mixinBody": { - "values": { - "fontSize": "@textSizeBody" - } - }, - "mixinPrimary": { - "values": { - "fontSize": "@textSizePrimary" - } - }, - "mixinDetails": { - "values": { - "fontSize": "@textSizeDetails" - } - }, - "mixinSecondary": { - "values": { - "fontSize": "@textSizeSecondary" - } - }, - "textStylePrimary": { - "extend": [ - "textStyleBase1", - "mixinPrimary" - ] - }, - "textStyleSecondary": { - "extend": [ - "textStyleBase0", - "mixinSecondary" - ] - }, - "textStyleBody": { - "extend": [ - "textStyleBase1", - "mixinBody" - ] - }, - "textStyleSecondaryHint": { - "values": { - "fontFamily": "Bookerly", - "fontStyle": "italic", - "fontSize": "@textSizeSecondaryHint", - "color": "@colorTextPrimary" - } - }, - "textStyleDetails": { - "extend": [ - "textStyleBase2", - "mixinDetails" - ] - } - }, - "onMount": [], - "graphics": {}, - "commands": {}, - "layouts": { - "ListTemplate1": { - "parameters": [ - "backgroundImage", - "title", - "logo", - "hintText", - "listData" - ], - "item": [ - { - "type": "Container", - "width": "100vw", - "height": "100vh", - "direction": "column", - "items": [ - { - "type": "Image", - "source": "${backgroundImage}", - "scale": "best-fill", - "width": "100vw", - "height": "100vh", - "position": "absolute" - }, - { - "type": "AlexaHeader", - "headerTitle": "${title}", - "headerAttributionImage": "${logo}" - }, - { - "type": "Sequence", - "grow": 1, - "height": "80vh", - "scrollDirection": "vertical", - "paddingLeft": "@marginLeft", - "paddingRight": "@marginRight", - "data": "${listData}", - "numbered": true, - "items": [ - { - "type": "VerticalListItem", - "image": "${data.image.sources[0].url}", - "primaryText": "${data.textContent.primaryText.text}", - "secondaryText": "${data.textContent.secondaryText.text}", - "tertiaryText": "${data.textContent.tertiaryText.text}" - } - ] - } - ] - } - ] - }, - "VerticalListItem": { - "parameters": [ - "primaryText", - "secondaryText", - "tertiaryText", - "image" - ], - "item": [ - { - "when": "${viewport.shape == 'round'}", - "type": "Container", - "direction": "row", - "height": 200, - "width": 500, - "alignItems": "center", - "items": [ - { - "type": "Text", - "text": "${ordinal}", - "paddingBottom": "20dp", - "color": "white", - "spacing": "5dp" - }, - { - "type": "Image", - "when": "${image}", - "source": "${image}", - "height": 150, - "width": 150, - "spacing": 15, - "scale": "best-fit", - "align": "top" - }, - { - "type": "Container", - "direction": "column", - "spacing": 25, - "items": [ - { - "type": "Text", - "text": "${primaryText}", - "style": "textStyleDetail", - "grow": 1, - "shrink": 1, - "fontWeight": "300", - "maxLines": 1 - }, - { - "type": "Text", - "text": "${secondaryText}", - "style": "textStyleCaption", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - }, - { - "type": "Text", - "text": "${tertiaryText}", - "style": "textStyleDetails", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - } - ] - } - ] - }, - { - "type": "Container", - "direction": "row", - "height": 125, - "width": 800, - "alignItems": "center", - "items": [ - { - "type": "Text", - "text": "${ordinal}", - "paddingBottom": "20dp", - "color": "white", - "spacing": "5dp" - }, - { - "type": "Image", - "when": "${image}", - "source": "${image}", - "height": 100, - "width": 100, - "align": "top", - "spacing": 50, - "scale": "best-fit" - }, - { - "type": "Container", - "spacing": 30, - "direction": "column", - "items": [ - { - "type": "Text", - "text": "${primaryText}", - "style": "textStyleBody", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - }, - { - "type": "Text", - "text": "${secondaryText}", - "style": "textStyleDetails", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - } - ] - }, - { - "type": "Text", - "text": "${tertiaryText}", - "style": "textStyleBody", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "textAlign": "right", - "maxLines": 1 - } - ] - } - ] - } - }, - "mainTemplate": { - "parameters": [ - "payload" - ], - "item": [ - { - "type": "Container", - "id": "BookCabSimpleDialogAPL", - "items": [ - { - "type": "TouchWrapper", - "onPress": { - "type": "SendEvent", - "arguments": [ - "delegateToSkillNew" - ] - }, - "item": { - "type": "Text", - "id": "BookCabSimpleDialogAPL", - "paddingTop": "100", - "paddingLeft": "100", - "color": "green", - "size": 50, - "text": "delegateToSkillNew" - } - }, - { - "type": "TouchWrapper", - "onPress": { - "type": "SendEvent", - "arguments": [ - "delegateToSkillOld" - ] - }, - "item": { - "type": "Text", - "id": "BookCabSimpleDialogAPL", - "paddingTop": "100", - "paddingLeft": "100", - "color": "green", - "size": 50, - "text": "delegateToSkillOld" - } - }, - { - "type": "TouchWrapper", - "onPress": { - "type": "SendEvent", - "arguments": [ - "delegateToColtraneNew" - ] - }, - "item": { - "type": "Text", - "id": "BookCabSimpleDialogAPL", - "paddingTop": "100", - "paddingLeft": "100", - "color": "green", - "size": 50, - "text": "delegateToColtraneNew" - } - }, - { - "type": "TouchWrapper", - "onPress": { - "type": "SendEvent", - "arguments": [ - "delegateToColtraneOld" - ] - }, - "item": { - "type": "Text", - "id": "BookCabSimpleDialogAPL", - "paddingTop": "100", - "paddingLeft": "100", - "color": "green", - "size": 50, - "text": "delegateToColtraneOld" - } - } - ] - } - ] - } -} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/AlexaConversationsBye/document.json b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/AlexaConversationsBye/document.json deleted file mode 100644 index bde5ee56..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/AlexaConversationsBye/document.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": [ - "payload" - ], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "Bye.", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/AlexaConversationsNotifyFailure/document.json b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/AlexaConversationsNotifyFailure/document.json deleted file mode 100644 index c31fe279..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/AlexaConversationsNotifyFailure/document.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": [ - "payload" - ], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "Sorry, there was an error in the request.", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/AlexaConversationsOutOfDomain/document.json b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/AlexaConversationsOutOfDomain/document.json deleted file mode 100644 index 3796d4d5..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/AlexaConversationsOutOfDomain/document.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": [ - "payload" - ], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "Sorry, I don't understand.", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/AlexaConversationsProvideHelp/document.json b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/AlexaConversationsProvideHelp/document.json deleted file mode 100644 index 13b27c11..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/AlexaConversationsProvideHelp/document.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": [ - "payload" - ], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "I can give you the weather report. Just say \"what's the weather\" to start.", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/AlexaConversationsRequestMore/document.json b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/AlexaConversationsRequestMore/document.json deleted file mode 100644 index fb3e56ae..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/AlexaConversationsRequestMore/document.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": [ - "payload" - ], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "What do you want to do.", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/AlexaConversationsThankYou/document.json b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/AlexaConversationsThankYou/document.json deleted file mode 100644 index 2112f02e..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/AlexaConversationsThankYou/document.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": [ - "payload" - ], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "Thank you.", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/AlexaConversationsWelcome/document.json b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/AlexaConversationsWelcome/document.json deleted file mode 100644 index aeacaae2..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/AlexaConversationsWelcome/document.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": [ - "payload" - ], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "Welcome to the weather bot, I can give you the weather report. Just say \"what's the weather\" to start.", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/AlexaConversationsYouAreWelcome/document.json b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/AlexaConversationsYouAreWelcome/document.json deleted file mode 100644 index 7ade07ba..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/AlexaConversationsYouAreWelcome/document.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": [ - "payload" - ], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "You are welcome.", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/alexa_prize_preconditions_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/alexa_prize_preconditions_apla/document.json deleted file mode 100644 index e50c4e94..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/alexa_prize_preconditions_apla/document.json +++ /dev/null @@ -1,91 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": [ - "payload" - ], - "item": { - "type": "Selector", - "description": "Selects the speech response to render when device/locale is not supported", - "items": [ - { - "when": "${payload.result.isDeviceSupported == 0}", - "type": "Speech", - "contentType": "text", - "content": "Sorry, Alexa Prize is not available on this device.", - "description": "" - }, - { - "when": "${payload.result.isLocaleSupported == 0}", - "type": "Speech", - "contentType": "text", - "content": "Sorry, Alexa Prize is not available in your locale.", - "description": "" - }, - { - "when": "${payload.result.isSocialBotAvailable == 0}", - "type": "Speech", - "contentType": "text", - "content": "Right now the Alexa Prize socialbots are busy. Please try again soon and help the university students in their competition to advance conversational A I.", - "description": "" - }, - { - "when": "${payload.result.isAlexaPrizeEnabled == 0}", - "type": "Speech", - "contentType": "text", - "content": "Alexa Prize is currently disabled for this account. Please visit the skill store in the Alexa App to re-enable it.", - "description": "" - }, - { - "when": "${payload.result.isTopicBanned == 1}", - "type": "Speech", - "contentType": "text", - "content": "I’d rather not talk about that, but there’s lots of other things to chat about. Do you still wanna chat?", - "description": "The topic that user wants to talk about is banned, ask if they still want to chat about something else" - }, - { - "when": "${payload.result.isFalseWake == 1}", - "type": "Speech", - "contentType": "text", - "content": "Would you like to chat with an Alexa Prize socialbot?", - "description": "" - }, - { - "when": "${payload.result.handoffPromptOverride == 'HandOffConversationForFilming'}", - "type": "Speech", - "contentType": "text", - "content": "Welcome to the Finals of the Alexa Prize Socialbot Grand Challenge 3, a university competition to advance AI. I’ll get you a socialbot now.", - "description": "" - }, - { - "when": "${payload.result.handoffPromptOverride == 'HandOffConversationForFinals'}", - "type": "Speech", - "contentType": "text", - "content": "Welcome to the Alexa Prize Socialbot Grand Challenge 3: Grand Finale. Here’s one of the finalists.", - "description": "" - }, - { - "when": "${payload.result.handoffPromptOverride == 'HandOffConversationForRepeatUser'}", - "type": "Speech", - "contentType": "text", - "content": "Welcome to the Alexa Prize, a university competition to advance AI. It’s quarterfinals for these socialbots and your ratings help determine who makes it to the semifinals. I’ll get you a socialbot now. When you’re done, say stop, and I’ll ask you for your rating. Your conversation and feedback will be shared with the university to help the socialbots improve.", - "description": "" - }, - { - "when": "${payload.result.handoffPromptOverride == 'CancelHandoff'}", - "type": "Speech", - "contentType": "text", - "content": "Okay", - "description": "" - }, - { - "type": "Speech", - "contentType": "text", - "content": "Welcome to the Alexa Prize, a university competition to advance AI. It’s quarterfinals for these socialbots and your ratings help determine who makes it to the semifinals. I’ll get you a socialbot now. When you’re done, say stop, and I’ll ask you for your rating. Your conversation and feedback will be shared with the university to help the socialbots improve.", - "description": "This is the current default handoff prompt" - } - ] - } - } -} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/confirm_color_for_fruit_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/confirm_color_for_fruit_apla/document.json deleted file mode 100644 index 835d7a8e..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/confirm_color_for_fruit_apla/document.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": [ - "payload" - ], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "confirm color is ${payload.colorName} ? ", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/confirm_fruitName_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/confirm_fruitName_apla/document.json deleted file mode 100644 index 42d63adc..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/confirm_fruitName_apla/document.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": [ - "payload" - ], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "confirm fruit ${payload.fruitName} ? ", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/getEmployeePosition_success_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/getEmployeePosition_success_apla/document.json deleted file mode 100644 index 4f5794c0..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/getEmployeePosition_success_apla/document.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": [ - "payload" - ], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "${payload.result.name1} born on ${payload.result.a_dateOfBirth} with employee id ${payload.result.emplyee1id} , is an ${payload.result.position} ", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/no_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/no_apla/document.json deleted file mode 100644 index 76610fcc..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/no_apla/document.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": [ - "payload" - ], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "I'm sorry you didn't like it", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/nothing2_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/nothing2_apla/document.json deleted file mode 100644 index 98f7ebef..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/nothing2_apla/document.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": [ - "payload" - ], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "The number you gave us was not 3.", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/nothing_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/nothing_apla/document.json deleted file mode 100644 index 5272f2a9..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/nothing_apla/document.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": [ - "payload" - ], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "The number you gave us was 3.", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/numericfeedback_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/numericfeedback_apla/document.json deleted file mode 100644 index 4d855af6..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/numericfeedback_apla/document.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": [ - "payload" - ], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "Your random number was ${payload.num}. How did we do? Please give this interaction a rating between 1-5, where 5 is the highest rating", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/rating_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/rating_apla/document.json deleted file mode 100644 index 7d50a649..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/rating_apla/document.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": [ - "payload" - ], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "rating please?", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/requestArgs_request_fruitName_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/requestArgs_request_fruitName_apla/document.json deleted file mode 100644 index a27a7d1e..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/requestArgs_request_fruitName_apla/document.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": [ - "payload" - ], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "tell me the fruit name ?", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - }, - { - "type": "Speech", - "contentType": "text", - "content": "random slection tell me the fruit name ?", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/request_city_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/request_city_apla/document.json deleted file mode 100644 index 65c28562..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/request_city_apla/document.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": [ - "payload" - ], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "Which city?", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/request_city_date_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/request_city_date_apla/document.json deleted file mode 100644 index f685b93e..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/request_city_date_apla/document.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": [ - "payload" - ], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "Which city and for which date?", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/request_colorName_multiple_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/request_colorName_multiple_apla/document.json deleted file mode 100644 index 62911ca4..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/request_colorName_multiple_apla/document.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": [ - "payload" - ], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "which color?", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/request_date_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/request_date_apla/document.json deleted file mode 100644 index 3beebe7b..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/request_date_apla/document.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": [ - "payload" - ], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "Which date?", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/request_dob_getDate_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/request_dob_getDate_apla/document.json deleted file mode 100644 index cabe7441..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/request_dob_getDate_apla/document.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": [ - "payload" - ], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "SSML", - "content": "provide date?", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/request_getEmploeeID_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/request_getEmploeeID_apla/document.json deleted file mode 100644 index 7649453f..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/request_getEmploeeID_apla/document.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": [ - "payload" - ], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "SSML", - "content": "provide employee id?", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/request_name_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/request_name_apla/document.json deleted file mode 100644 index 8afc80bf..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/request_name_apla/document.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": [ - "payload" - ], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "SSML", - "content": "what is your cool name?", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/response0Prompt16/document.json b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/response0Prompt16/document.json deleted file mode 100644 index 9460f0b2..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/response0Prompt16/document.json +++ /dev/null @@ -1 +0,0 @@ -{"type":"APLA","version":"0.8","mainTemplate":{"parameters":["payload"],"item":{"type":"Selector","strategy":"randomItem","description":"Change 'type' above to try different Selector Component Types like Sequencer","items":[{"type":"Speech","contentType":"text","content":"confirm color is ${payload.colorName} ?","description":"Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that"}]}}} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/secondEarthAPI_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/secondEarthAPI_apla/document.json deleted file mode 100644 index be1095b2..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/secondEarthAPI_apla/document.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": [ - "payload" - ], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "success delegating", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/success_colorFruitAPI_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/success_colorFruitAPI_apla/document.json deleted file mode 100644 index 873e2711..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/success_colorFruitAPI_apla/document.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": [ - "payload" - ], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "price of an ${payload.result.fruitName} is free bucks ", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/success_fruitPriceAPI_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/success_fruitPriceAPI_apla/document.json deleted file mode 100644 index b4a7272b..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/success_fruitPriceAPI_apla/document.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": [ - "payload" - ], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "price of an ${payload.result.fruitName} is ${payload.result.price} bucks ", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/weather_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/weather_apla/document.json deleted file mode 100644 index 4c5d2883..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/weather_apla/document.json +++ /dev/null @@ -1,29 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": [ - "payload" - ], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "when": "${payload.weatherResult != null && payload.weatherResult.cityName != null && payload.weatherResult.highTemp != null && payload.weatherResult.lowTemp != null}", - "type": "Speech", - "contentType": "text", - "content": "In ${payload.weatherResult.cityName}, it's a high of ${payload.weatherResult.highTemp} degrees and a low of ${payload.weatherResult.lowTemp} degrees.", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - }, - { - "when": "${payload.weatherResult != null && payload.weatherResult.cityNameChanged != null && payload.weatherResult.highTemp != null && payload.weatherResult.lowTemp != null}", - "type": "Speech", - "contentType": "text", - "content": "In ${payload.weatherResult.cityName}, it's a high of ${payload.weatherResult.highTemp} degrees and a low of ${payload.weatherResult.lowTemp} degrees.", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/weather_apla_de_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/weather_apla_de_apla/document.json deleted file mode 100644 index a2d34b37..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/weather_apla_de_apla/document.json +++ /dev/null @@ -1,29 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": [ - "payload" - ], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "when": "${payload.weatherResult != null && payload.weatherResult.cityName != null && payload.weatherResult.highTemp != null && payload.weatherResult.lowTemp != null}", - "type": "Speech", - "contentType": "text", - "content": "German result satheesh In ${payload.weatherResult.cityName}, it's a high of ${payload.weatherResult.highTemp} degrees and a low of ${payload.weatherResult.lowTemp} degrees.", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - }, - { - "when": "${payload.weatherResult != null && payload.weatherResult.cityNameChanged != null && payload.weatherResult.highTemp != null && payload.weatherResult.lowTemp != null}", - "type": "Speech", - "contentType": "text", - "content": "German result satheesh In ${payload.weatherResult.cityName}, it's a high of ${payload.weatherResult.highTemp} degrees and a low of ${payload.weatherResult.lowTemp} degrees.", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/whoAmiSuccess/datasources/default.json b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/whoAmiSuccess/datasources/default.json deleted file mode 100644 index 6f317d9e..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/whoAmiSuccess/datasources/default.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "weatherResult": { - "cityName": "Houston", - "highTemperature": "92", - "lowTemperature": "78" - } -} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/whoAmiSuccess/document.json b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/whoAmiSuccess/document.json deleted file mode 100644 index 4c7b4dc2..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/whoAmiSuccess/document.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "type": "APLA", - "version": "0.8", - "mainTemplate": { - "parameters": [ - "payload" - ], - "item": { - "type": "Selector", - "strategy": "randomItem", - "description": "Change 'type' above to try different Selector Component Types like Sequencer", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "who am i result", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/yes_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/yes_apla/document.json deleted file mode 100644 index 021dec67..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/yes_apla/document.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": [ - "payload" - ], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "Nice! Glad you like it", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/yesnofeedback_apla/document.json b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/yesnofeedback_apla/document.json deleted file mode 100644 index f0242d89..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/response/prompts/yesnofeedback_apla/document.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": [ - "payload" - ], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "Your number was ${payload.num}. Is this a good number, yes or no?", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} \ No newline at end of file diff --git a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/skill.json b/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/skill.json deleted file mode 100644 index 4b64e280..00000000 --- a/test/unit/fixture/dialog-evaluate/test-project-7/skill-package/skill.json +++ /dev/null @@ -1,119 +0,0 @@ -{ - "manifest": { - "apis": { - "custom": { - "dialogManagement": { - "dialogManagers": [ - { - "type": "AMAZON.Conversations" - } - ], - "sessionStartDelegationStrategy": { - "target": "AMAZON.Conversations" - } - }, - "endpoint": { - "uri": "arn:aws:lambda:us-west-2:267006587462:function:ramansatTestFunction" - }, - "interfaces": [ - { - "supportedViewports": [ - { - "maxHeight": 480, - "maxWidth": 480, - "minHeight": 480, - "minWidth": 480, - "mode": "HUB", - "shape": "ROUND" - }, - { - "maxHeight": 600, - "maxWidth": 1024, - "minHeight": 600, - "minWidth": 1024, - "mode": "HUB", - "shape": "RECTANGLE" - }, - { - "maxHeight": 800, - "maxWidth": 1280, - "minHeight": 800, - "minWidth": 1280, - "mode": "HUB", - "shape": "RECTANGLE" - }, - { - "maxHeight": 540, - "maxWidth": 960, - "minHeight": 540, - "minWidth": 960, - "mode": "TV", - "shape": "RECTANGLE" - } - ], - "type": "ALEXA_PRESENTATION_APL" - } - ], - "regions": { - "NA": { - "endpoint": { - "uri": "arn:aws:lambda:us-west-2:267006587462:function:ramansatTestFunction" - } - }, - "EU": { - "endpoint": { - "uri": "arn:aws:lambda:us-west-2:267006587462:function:ramansatTestFunction" - } - }, - "FE": { - "endpoint": { - "uri": "arn:aws:lambda:us-west-2:267006587462:function:ramansatTestFunction" - } - } - } - } - }, - "manifestVersion": "1.0", - "publishingInformation": { - "category": "KNOWLEDGE_AND_TRIVIA", - "distributionCountries": [], - "isAvailableWorldwide": true, - "locales": { - "en-US": { - "description": "Sample Full Description", - "examplePhrases": [ - "Alexa open hello world", - "hello", - "help" - ], - "keywords": [], - "name": "engineering test skill three_six", - "summary": "Sample Short Description" - }, - "de-DE": { - "description": "Sample Full Description", - "examplePhrases": [ - "Alexa open hello world", - "hello", - "help" - ], - "keywords": [], - "name": "engineering test skill three_three", - "summary": "Sample Short Description" - }, - "en-GB": { - "description": "Sample Full Description", - "examplePhrases": [ - "Alexa open hello world", - "hello", - "help" - ], - "keywords": [], - "name": "engineering test skill three_three", - "summary": "Sample Short Description" - } - }, - "testingInstructions": "Sample Testing Instructions." - } - } -} \ No newline at end of file From 2e897eda16bc83703b63132b83b2f8370d1d0cfa Mon Sep 17 00:00:00 2001 From: Mario Doiron <4956+doiron@users.noreply.github.com> Date: Fri, 31 Mar 2023 10:39:18 -0700 Subject: [PATCH 10/10] fix: removing more unused dialog-evaluate test projects --- .../test-project-1/.ask/ask-states.json | 8 - .../test-project-1/ask-resources.json | 10 - .../conversations/dialogEight.acdl | 71 ---- .../conversations/dialogEleven.acdl | 109 ----- .../conversations/dialogFive.acdl | 87 ---- .../conversations/dialogFour.acdl | 84 ---- .../conversations/dialogNine.acdl | 38 -- .../conversations/dialogOne.acdl | 72 ---- .../conversations/dialogSeven.acdl | 56 --- .../conversations/dialogSix.acdl | 64 --- .../conversations/dialogTen.acdl | 59 --- .../conversations/dialogThree.acdl | 56 --- .../conversations/dialogTwo.acdl | 80 ---- .../interactionModels/custom/en-US.json | 180 --------- .../confirm_city_apl_display/document.json | 331 --------------- .../confirm_date_apl_display/document.json | 331 --------------- .../document.json | 379 ------------------ .../request_city_apl_display/document.json | 331 --------------- .../request_date_apl_display/document.json | 331 --------------- .../weather_success_apl_display/document.json | 379 ------------------ .../AlexaConversationsBye/document.json | 19 - .../document.json | 19 - .../document.json | 19 - .../document.json | 19 - .../document.json | 19 - .../AlexaConversationsThankYou/document.json | 19 - .../AlexaConversationsWelcome/document.json | 19 - .../document.json | 19 - .../document.json | 19 - .../document.json | 19 - .../confirm_colorName_apla/document.json | 19 - .../document.json | 19 - .../prompts/notused_apla/document.json | 19 - .../numericfeedback_apla/document.json | 19 - .../prompts/rating_apla/document.json | 19 - .../prompts/request_city_apla/document.json | 19 - .../request_city_date_apla/document.json | 19 - .../request_colorName_apla/document.json | 19 - .../prompts/request_date_apla/document.json | 19 - .../request_fruitName_apla/document.json | 25 -- .../request_listAddOns_apla/document.json | 19 - .../request_mainFoodName_apla/document.json | 19 - .../prompts/request_name_apla/document.json | 19 - .../success_colorFruitAPI_apla/document.json | 19 - .../success_cookingAPI_apla/document.json | 19 - .../document.json | 19 - .../success_fruitNameAPI_apla/document.json | 19 - .../success_weather_apla/document.json | 19 - .../test-project-1/skill-package/skill.json | 92 ----- 49 files changed, 3686 deletions(-) delete mode 100644 test/fixture/dialog-evaluate/test-project-1/.ask/ask-states.json delete mode 100644 test/fixture/dialog-evaluate/test-project-1/ask-resources.json delete mode 100644 test/fixture/dialog-evaluate/test-project-1/skill-package/conversations/dialogEight.acdl delete mode 100644 test/fixture/dialog-evaluate/test-project-1/skill-package/conversations/dialogEleven.acdl delete mode 100644 test/fixture/dialog-evaluate/test-project-1/skill-package/conversations/dialogFive.acdl delete mode 100644 test/fixture/dialog-evaluate/test-project-1/skill-package/conversations/dialogFour.acdl delete mode 100644 test/fixture/dialog-evaluate/test-project-1/skill-package/conversations/dialogNine.acdl delete mode 100644 test/fixture/dialog-evaluate/test-project-1/skill-package/conversations/dialogOne.acdl delete mode 100644 test/fixture/dialog-evaluate/test-project-1/skill-package/conversations/dialogSeven.acdl delete mode 100644 test/fixture/dialog-evaluate/test-project-1/skill-package/conversations/dialogSix.acdl delete mode 100644 test/fixture/dialog-evaluate/test-project-1/skill-package/conversations/dialogTen.acdl delete mode 100644 test/fixture/dialog-evaluate/test-project-1/skill-package/conversations/dialogThree.acdl delete mode 100644 test/fixture/dialog-evaluate/test-project-1/skill-package/conversations/dialogTwo.acdl delete mode 100644 test/fixture/dialog-evaluate/test-project-1/skill-package/interactionModels/custom/en-US.json delete mode 100644 test/fixture/dialog-evaluate/test-project-1/skill-package/response/display/confirm_city_apl_display/document.json delete mode 100644 test/fixture/dialog-evaluate/test-project-1/skill-package/response/display/confirm_date_apl_display/document.json delete mode 100644 test/fixture/dialog-evaluate/test-project-1/skill-package/response/display/confirm_weather_apla_display/document.json delete mode 100644 test/fixture/dialog-evaluate/test-project-1/skill-package/response/display/request_city_apl_display/document.json delete mode 100644 test/fixture/dialog-evaluate/test-project-1/skill-package/response/display/request_date_apl_display/document.json delete mode 100644 test/fixture/dialog-evaluate/test-project-1/skill-package/response/display/weather_success_apl_display/document.json delete mode 100644 test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/AlexaConversationsBye/document.json delete mode 100644 test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/AlexaConversationsNotifyFailure/document.json delete mode 100644 test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/AlexaConversationsOutOfDomain/document.json delete mode 100644 test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/AlexaConversationsProvideHelp/document.json delete mode 100644 test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/AlexaConversationsRequestMore/document.json delete mode 100644 test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/AlexaConversationsThankYou/document.json delete mode 100644 test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/AlexaConversationsWelcome/document.json delete mode 100644 test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/AlexaConversationsYouAreWelcome/document.json delete mode 100644 test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/confirmAction_complexNames_apla/document.json delete mode 100644 test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/confirmArgs_complexNames_apla/document.json delete mode 100644 test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/confirm_colorName_apla/document.json delete mode 100644 test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/confirm_main_addon_list_apla/document.json delete mode 100644 test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/notused_apla/document.json delete mode 100644 test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/numericfeedback_apla/document.json delete mode 100644 test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/rating_apla/document.json delete mode 100644 test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/request_city_apla/document.json delete mode 100644 test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/request_city_date_apla/document.json delete mode 100644 test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/request_colorName_apla/document.json delete mode 100644 test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/request_date_apla/document.json delete mode 100644 test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/request_fruitName_apla/document.json delete mode 100644 test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/request_listAddOns_apla/document.json delete mode 100644 test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/request_mainFoodName_apla/document.json delete mode 100644 test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/request_name_apla/document.json delete mode 100644 test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/success_colorFruitAPI_apla/document.json delete mode 100644 test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/success_cookingAPI_apla/document.json delete mode 100644 test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/success_favColorSign_Name_apla/document.json delete mode 100644 test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/success_fruitNameAPI_apla/document.json delete mode 100644 test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/success_weather_apla/document.json delete mode 100644 test/fixture/dialog-evaluate/test-project-1/skill-package/skill.json diff --git a/test/fixture/dialog-evaluate/test-project-1/.ask/ask-states.json b/test/fixture/dialog-evaluate/test-project-1/.ask/ask-states.json deleted file mode 100644 index 18048d0e..00000000 --- a/test/fixture/dialog-evaluate/test-project-1/.ask/ask-states.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "askcliStatesVersion": "2020-03-31", - "profiles": { - "TEST_PROFILE": { - "skillId": "TEST_SKILL_ID" - } - } -} diff --git a/test/fixture/dialog-evaluate/test-project-1/ask-resources.json b/test/fixture/dialog-evaluate/test-project-1/ask-resources.json deleted file mode 100644 index 649c901b..00000000 --- a/test/fixture/dialog-evaluate/test-project-1/ask-resources.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "askcliResourcesVersion": "2020-03-31", - "profiles": { - "TEST_PROFILE": { - "skillMetadata": { - "src": "./skill-package" - } - } - } -} diff --git a/test/fixture/dialog-evaluate/test-project-1/skill-package/conversations/dialogEight.acdl b/test/fixture/dialog-evaluate/test-project-1/skill-package/conversations/dialogEight.acdl deleted file mode 100644 index a32c092a..00000000 --- a/test/fixture/dialog-evaluate/test-project-1/skill-package/conversations/dialogEight.acdl +++ /dev/null @@ -1,71 +0,0 @@ -namespace com.dialogEight - -import com.amazon.alexa.ask.conversations.* -import com.amazon.alexa.schema.* -import com.amazon.ask.types.builtins.AMAZON.* -import prompts.* -import slotTypes.* - -// API Action - -action colorFruitNameResponseType colorFruitName(Color colorName, Food fruitName = nothing) - -action fruitNameResultType fruitNameAPI(Food fruitName) - -// UtteraceSets - -InvokeEvent = utterances( - samples = [ - "i want to buy a fruit" - ] -) - -informColorEvent = utterances( - samples = [ - "{colorName}", - "color is {colorName}", - "color {colorName}" - ] -) - -affirmEvent = utterances( - samples = [ - "do it" - ] -) - -// Type - -type colorNameType { - Color colorName -} - -type colorFruitNameResponseType { - Food fruitName - Color colorName -} - -type fruitNameResultType { - Food fruitName - NUMBER price -} - -type responsePayloadType { - fruitNameResultType fruitNameResult -} - -dialog Nothing dialogEight() { - sample { - expect(act = Invoke, event = InvokeEvent) - response( response = request_colorName_apla, - act = Request {arguments = [colorFruitName.arguments.colorName]}) - colorEvent = expect(act = Inform, event = informColorEvent) - response(response = confirm_colorName_apla, act = ConfirmArgs {arguments = [colorFruitName.arguments.colorName]}, - payload = colorNameType { colorName = colorEvent.colorName}) - expect(act = Affirm, event = affirmEvent) - apiResponseOne = colorFruitName(colorName = colorEvent.colorName) - apiResponseTwo = fruitNameAPI(fruitName = apiResponseOne.fruitName) - response(response = success_fruitNameAPI_apla, act = Notify { actionName = fruitNameAPI}, - payload = responsePayloadType { fruitNameResult = apiResponseTwo}) - } -} diff --git a/test/fixture/dialog-evaluate/test-project-1/skill-package/conversations/dialogEleven.acdl b/test/fixture/dialog-evaluate/test-project-1/skill-package/conversations/dialogEleven.acdl deleted file mode 100644 index f3ed4ba6..00000000 --- a/test/fixture/dialog-evaluate/test-project-1/skill-package/conversations/dialogEleven.acdl +++ /dev/null @@ -1,109 +0,0 @@ -namespace com.dialogEleven - -import com.amazon.alexa.ask.conversations.* -import com.amazon.alexa.schema.* -import com.amazon.ask.types.builtins.AMAZON.* -import prompts.* -import slotTypes.* - -// API Action - -action fruitNameApiResponseType fruitNameAPI(Color color = nothing, Food fruitName = nothing) - -action colorFruitNameResponseType colorFruitName(Color color) - -// UtteraceSets - -InvokeEventOne = utterances( - samples = [ - "i want to buy a fruit" - ] -) - -InvokeEventTwo = utterances( - samples = [ - "what is the price of the fruit", - "what is the price of fruit" - ] -) - -informColorEvent = utterances( - samples = [ - "color {colorName}", - "color is {colorName}", - "{colorName}" - ] -) - -affirmMultipleColorEvent = utterances( - samples = [ - "do it" - ] -) - -informfruitNameEvent = utterances( - samples = [ - "{fruitName}", - "fruit name is {fruitName}", - "fruit is {fruitName}" - ] -) - -// Type - -type fruitNameApiResponseType { - NUMBER price - Food fruitName -} - -type colorFruitNameResponseType { - Color colorName - Food fruitName -} - -type colorNameType { - Color colorName -} - -type fruitNameType { - Food fruitName -} - -type responsePayloadTypeOne { - colorFruitNameResponseType colorFruitNameResponse -} -type responsePayloadTypeTwo { - fruitNameApiResponseType fruitNameApiResponse -} - - -dialog Nothing dialogEleven() { - - sample { - expect(act = Invoke, event = InvokeEventOne) - response(act = Request { arguments = [ colorFruitName.arguments.color ]}, - response = MultiModalResponse { apla = request_colorName_apla}) - informColorMultipleEventRequest = expect(act = Inform,event = informColorEvent) - response(act = ConfirmAction { actionName = colorFruitName}, - payload = colorNameType { colorName = informColorMultipleEventRequest.colorName}, - response = MultiModalResponse { apla = confirm_colorName_apla}) - expect(act = Affirm, event = affirmMultipleColorEvent) - apiResponseOne = fruitNameAPI(color = informColorMultipleEventRequest.colorName) - ensure(requestArgs = [ RequestArguments {response = MultiModalResponse {apla = request_colorName_apla}, arguments = [fruitNameAPI.arguments.color]}]) - apiResponseTwo = colorFruitName(color = informColorMultipleEventRequest.colorName) - response(act = Notify { success = true, actionName = colorFruitName}, - payload = responsePayloadTypeOne { colorFruitNameResponse = apiResponseTwo}, - response = MultiModalResponse { apla = success_fruitNameAPI_apla}) - } - - sample { - expect(act = Invoke, event = InvokeEventTwo) - response(response = request_fruitName_apla, - act = Request { arguments = [ fruitNameAPI.arguments.fruitName ]}) - fruitNameEvent = expect(act = Inform, event = informfruitNameEvent) - apiResponse = fruitNameAPI(fruitName = fruitNameEvent.fruitName) - response(response = success_fruitNameAPI_apla, act = Notify { actionName = fruitNameAPI}, - payload = responsePayloadTypeTwo { fruitNameApiResponse = apiResponse}) - } - -} diff --git a/test/fixture/dialog-evaluate/test-project-1/skill-package/conversations/dialogFive.acdl b/test/fixture/dialog-evaluate/test-project-1/skill-package/conversations/dialogFive.acdl deleted file mode 100644 index 3fc5dbd0..00000000 --- a/test/fixture/dialog-evaluate/test-project-1/skill-package/conversations/dialogFive.acdl +++ /dev/null @@ -1,87 +0,0 @@ -namespace com.dialogFive - -import com.amazon.alexa.ask.conversations.* -import com.amazon.alexa.schema.* -import com.amazon.ask.types.builtins.AMAZON.* -import prompts.* -import slotTypes.* - -// API Action - -action favColorSignNameResponseType favColorSign_Name(complexNames name) - -// UtteraceSets - -InvokeEventOne = utterances( - samples = [ - "what is my favourite color" - ] - ) - -InvokeEventTwo = utterances( - samples = [ - "guess the color" - ] -) - -informComplexNameEvent = utterances( - samples = [ - "{name}", - "name is {name}", - "i am {name}" - ] - ) - -affirmFavColorEvent = utterances( - samples = [ - "correct" - ] -) - -// Type - -type favColorSignNameResponseType { - Color colorName - complexNames name - signs sign - } - -type customNameType { - complexNames name -} - -type responsePayloadType { - favColorSignNameResponseType favColorSignNameResponse -} - - dialog Nothing dialogFive() { - - sample { - expect(act = Invoke, event = InvokeEventOne) - response(act = Request {arguments = [favColorSign_Name.arguments.name]}, - response = MultiModalResponse { apla = request_name_apla}) - ComplexNameEvent = expect(act = Inform, event = informComplexNameEvent) - response(response = confirmArgs_complexNames_apla, act = ConfirmArgs {arguments = [ favColorSign_Name.arguments.name ]}, - payload = customNameType {name = ComplexNameEvent.name}) - expect(act = Affirm, event = affirmFavColorEvent) - apiResponse = favColorSign_Name(name = ComplexNameEvent.name) - response(response = success_favColorSign_Name_apla,act = Notify { actionName = favColorSign_Name}, - payload = responsePayloadType { favColorSignNameResponse = apiResponse}) - } - - sample { - expect(act = Invoke,event = InvokeEventTwo) - response(act = Request { arguments = [ favColorSign_Name.arguments.name ]}, - response = MultiModalResponse { apla = request_name_apla}) - ComplexNameEvent = expect(act = Inform,event = informComplexNameEvent) - response(response = confirmAction_complexNames_apla, act = ConfirmAction {actionName = favColorSign_Name}, - payload = customNameType { name = ComplexNameEvent.name}) - expect(act = Affirm,event = affirmFavColorEvent) - apiResponse = favColorSign_Name(name = ComplexNameEvent.name) - response(response = success_favColorSign_Name_apla, act = Notify { actionName = favColorSign_Name}, - payload = responsePayloadType { favColorSignNameResponse = apiResponse}) - } - - } - - diff --git a/test/fixture/dialog-evaluate/test-project-1/skill-package/conversations/dialogFour.acdl b/test/fixture/dialog-evaluate/test-project-1/skill-package/conversations/dialogFour.acdl deleted file mode 100644 index b2c61682..00000000 --- a/test/fixture/dialog-evaluate/test-project-1/skill-package/conversations/dialogFour.acdl +++ /dev/null @@ -1,84 +0,0 @@ -namespace com.dialogFour - -import com.amazon.alexa.ask.conversations.* -import com.amazon.alexa.schema.* -import com.amazon.ask.types.builtins.AMAZON.* -import prompts.* -import slotTypes.* - -// API Action - -action fruitNameResultType fruitNameAPI(Food fruitName) - -action fruitNameResultType colorFruitNameAAA(Food fruitName) - -// UtteraceSets - -InvokeEventOne = utterances( - samples = [ - "what is the price of the fruit" - ] -) - -InvokeEventTwo = utterances( - samples = [ - "take me to market place" - ] -) - -informfruitNameEvent = utterances( - samples = [ - "{fruitName}", - "fruit name is {fruitName}", - "fruit is {fruitName}" - ] -) - -informMarketPlaceNameEvent = utterances( - samples = [ - "{fruitName}", - "marketplace name is {fruitName}", - "marketplace is {fruitName}", - "market place is {fruitName}", - "market place name is {fruitName}" - ] -) - -// Type - -type fruitNameType { - Food fruitName -} - -type fruitNameResultType { - Food fruitName - NUMBER price -} - -type responsePayloadType { - fruitNameResultType fruitNameResult -} - -dialog Nothing dialogFour() { - - sample { - expect(act = Invoke, event = InvokeEventOne) - response(response = request_fruitName_apla, - act = Request { arguments = [fruitNameAPI.arguments.fruitName]}) - fruitNameEvent = expect(act = Inform, event = informfruitNameEvent) - apiResponse = fruitNameAPI(fruitName = fruitNameEvent.fruitName) - response(response = success_fruitNameAPI_apla, act = Notify {actionName = fruitNameAPI}, - payload = responsePayloadType {fruitNameResult = apiResponse}) - } - - sample { - expect(act = Invoke,event = InvokeEventTwo) - response(response = request_fruitName_apla, - act = Request {arguments = [colorFruitNameAAA.arguments.fruitName]}) - MarketPlaceInformResponseEvent = expect(act = Inform,event = informMarketPlaceNameEvent) - apiResponse = colorFruitNameAAA(fruitName = MarketPlaceInformResponseEvent.fruitName) - response(response = success_fruitNameAPI_apla, act = Notify { actionName = colorFruitNameAAA}, - payload = responsePayloadType { fruitNameResult = apiResponse}) - } - -} diff --git a/test/fixture/dialog-evaluate/test-project-1/skill-package/conversations/dialogNine.acdl b/test/fixture/dialog-evaluate/test-project-1/skill-package/conversations/dialogNine.acdl deleted file mode 100644 index 12bc5e37..00000000 --- a/test/fixture/dialog-evaluate/test-project-1/skill-package/conversations/dialogNine.acdl +++ /dev/null @@ -1,38 +0,0 @@ -namespace com.dialogNine - -import com.amazon.alexa.ask.conversations.* -import com.amazon.alexa.schema.* -import com.amazon.ask.types.builtins.AMAZON.* -import prompts.* -import slotTypes.* - -// API Action - -action Nothing delegateToSkill() - -action fruitNameResultType fruitNameAPI(Food fruitName = nothing) - -// UtteraceSets - -InvokeEvent = utterances( - samples = [ - "switch to skill focus dialog manager" - ] -) - -// type - -type fruitNameResultType { - Food fruitName - NUMBER price -} - -dialog Nothing dialogNine() { - - sample { - expect(act = Invoke, event = InvokeEvent) - delegateToSkill() - response(response = notused_apla, act = Notify {actionName = delegateToSkill}, nextAct = nothing) - } - -} \ No newline at end of file diff --git a/test/fixture/dialog-evaluate/test-project-1/skill-package/conversations/dialogOne.acdl b/test/fixture/dialog-evaluate/test-project-1/skill-package/conversations/dialogOne.acdl deleted file mode 100644 index 5f116397..00000000 --- a/test/fixture/dialog-evaluate/test-project-1/skill-package/conversations/dialogOne.acdl +++ /dev/null @@ -1,72 +0,0 @@ -namespace com.dialogOne - -import com.amazon.alexa.ask.conversations.* -import com.amazon.alexa.schema.* -import com.amazon.ask.types.builtins.AMAZON.* -import prompts.* -import slotTypes.* - -// API Action - -action weatherResultType getWeather(DATE date, US_CITY cityName = nothing, - myCustomCities cityNameChanged = nothing) - -// UtteraceSets - -InvokeEvent = utterances( - samples = [ - "What's the weather {date} in {cityNameChanged}", - "What's the weather {date} in {cityName}", - "what is the weather {date}", - "how is weather" - ] -) - -// Type - -type cityAndDateType { - optional myCustomCities cityNameChanged - optional US_CITY cityName - optional DATE date -} - -type weatherResultType { - optional myCustomCities cityNameChanged - optional US_CITY cityName - NUMBER highTemp - NUMBER lowTemp -} - -type responsePayloadType { - weatherResultType weatherResult -} - -dialog Nothing dialogOne() { - - sample { - weatherRequest = expect(act = Invoke, event = InvokeEvent) - ensure(requestArgs = [ - RequestArguments {arguments = [getWeather.arguments.cityNameChanged], response = request_city_apla}, - RequestArguments {arguments = [getWeather.arguments.cityName], response = request_city_apla}, - RequestArguments {arguments = [getWeather.arguments.date], response = request_date_apla} - ] - ) - apiResponse = getWeather(date = weatherRequest.date, cityName = weatherRequest.cityName) - response(response = success_weather_apla, act = Notify {actionName = getWeather}, - payload = responsePayloadType {weatherResult = apiResponse}) - } - - sample { - weatherRequest = expect(act = Invoke, event = InvokeEvent) - ensure(requestArgs = [ - RequestArguments {arguments = [getWeather.arguments.cityNameChanged], response = request_city_apla}, - RequestArguments {arguments = [getWeather.arguments.cityName], response = request_city_apla}, - RequestArguments {arguments = [getWeather.arguments.date], response = request_date_apla} - ] - ) - apiResponse = getWeather(date = weatherRequest.date, cityNameChanged = weatherRequest.cityNameChanged) - response(response = success_weather_apla, act = Notify {actionName = getWeather}, - payload = responsePayloadType {weatherResult = apiResponse}) - } - -} \ No newline at end of file diff --git a/test/fixture/dialog-evaluate/test-project-1/skill-package/conversations/dialogSeven.acdl b/test/fixture/dialog-evaluate/test-project-1/skill-package/conversations/dialogSeven.acdl deleted file mode 100644 index 3646a304..00000000 --- a/test/fixture/dialog-evaluate/test-project-1/skill-package/conversations/dialogSeven.acdl +++ /dev/null @@ -1,56 +0,0 @@ -namespace com.dialogSeven - -import com.amazon.alexa.ask.conversations.* -import com.amazon.alexa.schema.* -import com.amazon.ask.types.builtins.AMAZON.* -import prompts.* -import slotTypes.* - -// API Action - -action colorFruitNameResponseType colorFruitName(myColors colorName, Food fruitName = nothing) - -// UtteraceSets - -InvokeEvent = utterances( - samples = [ - "i want to buy a fruit" - ] -) - -informColorEvent = utterances( - samples = [ - "{colorName}", - "color is {colorName}", - "color {colorName}" - ] -) - -// Type - -type colorNameType { - myColors colorName -} - -type colorFruitNameResponseType { - Food fruitName - myColors colorName -} - -type responsePayloadType { - colorFruitNameResponseType colorFruitNameResponse -} - -dialog Nothing dialogSeven() { - - sample { - expect(act = Invoke, event = InvokeEvent) - response( response = request_colorName_apla, - act = Request {arguments = [colorFruitName.arguments.colorName]}) - colorEvent = expect(act = Inform, event = informColorEvent) - apiResponse = colorFruitName(colorName = colorEvent.colorName) - response(response = success_colorFruitAPI_apla, act = Notify {actionName = colorFruitName}, - payload = responsePayloadType {colorFruitNameResponse = apiResponse}) - } - -} \ No newline at end of file diff --git a/test/fixture/dialog-evaluate/test-project-1/skill-package/conversations/dialogSix.acdl b/test/fixture/dialog-evaluate/test-project-1/skill-package/conversations/dialogSix.acdl deleted file mode 100644 index a2252f90..00000000 --- a/test/fixture/dialog-evaluate/test-project-1/skill-package/conversations/dialogSix.acdl +++ /dev/null @@ -1,64 +0,0 @@ -namespace com.dialogSix - -import com.amazon.alexa.ask.conversations.* -import com.amazon.alexa.schema.* -import com.amazon.ask.types.builtins.AMAZON.* -import prompts.* -import slotTypes.* - -// API Action - -action colorFruitNameResponseType colorFruitName(Color colorName, Food fruitName = nothing) - -// UtteraceSets - -InvokeEvent = utterances( - samples = [ - "i want to buy a fruit" - ] -) - -informColorEvent = utterances( - samples = [ - "{colorName}", - "color is {colorName}", - "color {colorName}" - ] -) - -affirmEvent = utterances( - samples = [ - "do it" - ] -) -// Type - -type colorNameType { - Color colorName -} - -type colorFruitNameResponseType { - Food fruitName - Color colorName -} - -type responsePayloadType { - colorFruitNameResponseType colorFruitNameResponse -} - -dialog Nothing dialogSix() { - - sample { - expect(act = Invoke, event = InvokeEvent) - response( response = request_colorName_apla, - act = Request {arguments = [colorFruitName.arguments.colorName]}) - colorEvent = expect(act = Inform, event = informColorEvent) - response(response = confirm_colorName_apla, act = ConfirmArgs {arguments = [colorFruitName.arguments.colorName]}, - payload = colorNameType { colorName = colorEvent.colorName}) - expect(act = Affirm, event = affirmEvent) - apiResponse = colorFruitName(colorName = colorEvent.colorName) - response(response = success_colorFruitAPI_apla, act = Notify {actionName = colorFruitName}, - payload = responsePayloadType {colorFruitNameResponse = apiResponse}) - } - -} \ No newline at end of file diff --git a/test/fixture/dialog-evaluate/test-project-1/skill-package/conversations/dialogTen.acdl b/test/fixture/dialog-evaluate/test-project-1/skill-package/conversations/dialogTen.acdl deleted file mode 100644 index f820d47f..00000000 --- a/test/fixture/dialog-evaluate/test-project-1/skill-package/conversations/dialogTen.acdl +++ /dev/null @@ -1,59 +0,0 @@ -namespace com.dialogTen - -import com.amazon.alexa.ask.conversations.* -import com.amazon.alexa.schema.* -import com.amazon.ask.types.builtins.AMAZON.* -import prompts.* -import slotTypes.* - -// API Action - -action Nothing saveRating(Number rating) - -action Number getNumber() - -// UtteraceSets - -InformRatingEvent = utterances( - samples = [ - "my score is {rating}", - "that was a {rating} conversation", - "i rate you a {rating}", - "{rating}" - ] -) - -getStart = utterances( - samples = [ - "give me a number please" - ] -) - -// Type - -type NumPayload { - Number num -} - -type RatingRequest { - NUMBER rating -} - - -dialog Nothing dialogTen() { - - sample { - expect(act = Invoke, event = getStart) - num = getNumber() - response(response = numericfeedback_apla, act = Notify {actionName = getNumber, success = true}, - nextAct = Offer { actionName = saveRating, arguments = [saveRating.arguments.rating]}, - payload = NumPayload {num = num}) - myRating = expect( act = Invoke,event = InformRatingEvent) - ensure(requestArgs = [RequestArguments {arguments = [saveRating.arguments.rating], - response = rating_apla}]) - saveRating(rating = myRating.rating) - response(response = AlexaConversationsBye, act = Notify { actionName = saveRating,success = true}, - nextAct = Bye {}) - } - -} diff --git a/test/fixture/dialog-evaluate/test-project-1/skill-package/conversations/dialogThree.acdl b/test/fixture/dialog-evaluate/test-project-1/skill-package/conversations/dialogThree.acdl deleted file mode 100644 index 5a3ddbb8..00000000 --- a/test/fixture/dialog-evaluate/test-project-1/skill-package/conversations/dialogThree.acdl +++ /dev/null @@ -1,56 +0,0 @@ -namespace com.dialogThree - -import com.amazon.alexa.ask.conversations.* -import com.amazon.alexa.schema.* -import com.amazon.ask.types.builtins.AMAZON.* -import prompts.* -import slotTypes.* - -// API Action - -action colorFruitNameResponseType colorFruitName(Color colorName, Food fruitName = nothing) - -// UtteraceSets - -InvokeEvent = utterances( - samples = [ - "i want to buy a fruit" - ] -) - -informColorEvent = utterances( - samples = [ - "{colorName}", - "color is {colorName}", - "color {colorName}" - ] -) - -// Type - -type colorNameType { - Color colorName -} - -type colorFruitNameResponseType { - Food fruitName - Color colorName -} - -type responsePayloadType { - colorFruitNameResponseType colorFruitNameResponse -} - -dialog Nothing dialogThree() { - - sample { - expect(act = Invoke, event = InvokeEvent) - response( response = request_colorName_apla, - act = Request {arguments = [colorFruitName.arguments.colorName]}) - colorEvent = expect(act = Inform, event = informColorEvent) - apiResponse = colorFruitName(colorName = colorEvent.colorName) - response(response = success_colorFruitAPI_apla, act = Notify {actionName = colorFruitName}, - payload = responsePayloadType {colorFruitNameResponse = apiResponse}) - } - -} \ No newline at end of file diff --git a/test/fixture/dialog-evaluate/test-project-1/skill-package/conversations/dialogTwo.acdl b/test/fixture/dialog-evaluate/test-project-1/skill-package/conversations/dialogTwo.acdl deleted file mode 100644 index 92bdcd06..00000000 --- a/test/fixture/dialog-evaluate/test-project-1/skill-package/conversations/dialogTwo.acdl +++ /dev/null @@ -1,80 +0,0 @@ -namespace com.dialogTwo - -import com.amazon.alexa.ask.conversations.* -import com.amazon.alexa.schema.* -import com.amazon.ask.types.builtins.AMAZON.* -import prompts.* -import slotTypes.* - -// API Action - -action orderStatus cookingAPI(Food foodName, List addOn) - -// UtteraceSets - -InvokeEvent = utterances( - samples = [ - "let us cook" - ] -) - -informlistAddOnsEvent = utterances( - samples = [ - "{addOn}", - "add {addOn}", - "mix {addOn}" - ] -) - -informFoodNameEvent = utterances( - samples = [ - "{foodName}", - "food is {foodName}", - "let us make {foodName}" - ] -) - -affirmCookAPIEvent = utterances( - samples = [ - "ok", - "that is ok", - "ok for sure" - ] -) - -// Type - -type foodNameType { - Food foodName -} - -type addOnType { - List addOn -} - -type responsePayloadType { - orderStatus status -} - -type payloadConfirmActionType { - optional Food foodName - List addOn -} - -dialog Nothing dialogTwo() { - - sample { - expect(act = Invoke, event = InvokeEvent) - response(response = request_listAddOns_apla, act = Request {arguments = [cookingAPI.arguments.addOn]}) - listAddOnsEvent = expect(act = Inform, event = informlistAddOnsEvent) - response(response = request_mainFoodName_apla, act = Request {arguments = [cookingAPI.arguments.foodName]}) - FoodNameEvent = expect(act = Inform, event = informFoodNameEvent) - response(response = confirm_main_addon_list_apla, act = ConfirmAction {actionName = cookingAPI}, - payload = payloadConfirmActionType {foodName = FoodNameEvent.foodName, addOn = listAddOnsEvent.addOn}) - expect(act = Affirm, event = affirmCookAPIEvent) - apiResponse = cookingAPI(foodName = FoodNameEvent.foodName, addOn = listAddOnsEvent.addOn) - response(response = success_cookingAPI_apla, act = Notify {actionName = cookingAPI}, - payload = responsePayloadType {status = apiResponse}) - } - -} \ No newline at end of file diff --git a/test/fixture/dialog-evaluate/test-project-1/skill-package/interactionModels/custom/en-US.json b/test/fixture/dialog-evaluate/test-project-1/skill-package/interactionModels/custom/en-US.json deleted file mode 100644 index f6ddb35d..00000000 --- a/test/fixture/dialog-evaluate/test-project-1/skill-package/interactionModels/custom/en-US.json +++ /dev/null @@ -1,180 +0,0 @@ -{ - "interactionModel": { - "languageModel": { - "invocationName": "test skill", - "intents": [ - { - "name": "AMAZON.CancelIntent", - "samples": [] - }, - { - "name": "AMAZON.HelpIntent", - "samples": [] - }, - { - "name": "AMAZON.StopIntent", - "samples": [] - }, - { - "name": "GetWeatherIntent", - "samples": ["what is the weather", "how is the weather", "tell me the weather"] - }, - { - "name": "AMAZON.NavigateHomeIntent", - "samples": [] - }, - { - "name": "AMAZON.FallbackIntent", - "samples": [] - } - ], - "types": [ - { - "values": [ - { - "name": { - "value": "flower city" - } - }, - { - "name": { - "value": "temple city" - } - }, - { - "name": { - "value": "ramapuram" - } - }, - { - "name": { - "value": "guindy" - } - }, - { - "name": { - "value": "porur" - } - } - ], - "name": "myCustomCities" - }, - { - "values": [ - { - "name": { - "value": "almonds" - } - }, - { - "name": { - "value": "bread" - } - }, - { - "name": { - "value": "egg" - } - }, - { - "name": { - "value": "sauce" - } - }, - { - "name": { - "value": "jam" - } - }, - { - "name": { - "value": "cheese" - } - } - ], - "name": "Mix" - }, - { - "values": [ - { - "name": { - "value": "failure" - } - }, - { - "name": { - "value": "failed" - } - }, - { - "name": { - "value": "success" - } - } - ], - "name": "orderStatus" - }, - { - "values": [ - { - "name": { - "value": "blue" - } - }, - { - "name": { - "value": "red" - } - }, - { - "name": { - "value": "rocket" - } - } - ], - "name": "myColors" - }, - { - "values": [ - { - "name": { - "value": "satheesh" - } - }, - { - "name": { - "value": "raman" - } - }, - { - "name": { - "value": "yadhu" - } - } - ], - "name": "complexNames" - }, - { - "values": [ - { - "name": { - "value": "cancer" - } - }, - { - "name": { - "value": "scorpio" - } - }, - { - "name": { - "value": "scorpion" - } - } - ], - "name": "signs" - } - ] - } - } -} diff --git a/test/fixture/dialog-evaluate/test-project-1/skill-package/response/display/confirm_city_apl_display/document.json b/test/fixture/dialog-evaluate/test-project-1/skill-package/response/display/confirm_city_apl_display/document.json deleted file mode 100644 index 6fea1ff7..00000000 --- a/test/fixture/dialog-evaluate/test-project-1/skill-package/response/display/confirm_city_apl_display/document.json +++ /dev/null @@ -1,331 +0,0 @@ -{ - "type": "APL", - "version": "1.1", - "settings": {}, - "theme": "dark", - "import": [ - { - "name": "alexa-layouts", - "version": "1.0.0" - } - ], - "resources": [ - { - "description": "Stock color for the light theme", - "colors": { - "colorTextPrimary": "#151920" - } - }, - { - "description": "Stock color for the dark theme", - "when": "${viewport.theme == 'dark'}", - "colors": { - "colorTextPrimary": "#f0f1ef" - } - }, - { - "description": "Standard font sizes", - "dimensions": { - "textSizeBody": 48, - "textSizePrimary": 27, - "textSizeSecondary": 23, - "textSizeDetails": 20, - "textSizeSecondaryHint": 25 - } - }, - { - "description": "Common spacing values", - "dimensions": { - "spacingThin": 6, - "spacingSmall": 12, - "spacingMedium": 24, - "spacingLarge": 48, - "spacingExtraLarge": 72 - } - }, - { - "description": "Common margins and padding", - "dimensions": { - "marginTop": 40, - "marginLeft": 60, - "marginRight": 60, - "marginBottom": 40 - } - } - ], - "styles": { - "textStyleBase": { - "description": "Base font description; set color", - "values": [ - { - "color": "@colorTextPrimary" - } - ] - }, - "textStyleBase0": { - "description": "Thin version of basic font", - "extend": "textStyleBase", - "values": { - "fontWeight": "100" - } - }, - "textStyleBase1": { - "description": "Light version of basic font", - "extend": "textStyleBase", - "values": { - "fontWeight": "300" - } - }, - "textStyleBase2": { - "description": "Regular version of basic font", - "extend": "textStyleBase", - "values": { - "fontWeight": "500" - } - }, - "mixinBody": { - "values": { - "fontSize": "@textSizeBody" - } - }, - "mixinPrimary": { - "values": { - "fontSize": "@textSizePrimary" - } - }, - "mixinDetails": { - "values": { - "fontSize": "@textSizeDetails" - } - }, - "mixinSecondary": { - "values": { - "fontSize": "@textSizeSecondary" - } - }, - "textStylePrimary": { - "extend": ["textStyleBase1", "mixinPrimary"] - }, - "textStyleSecondary": { - "extend": ["textStyleBase0", "mixinSecondary"] - }, - "textStyleBody": { - "extend": ["textStyleBase1", "mixinBody"] - }, - "textStyleSecondaryHint": { - "values": { - "fontFamily": "Bookerly", - "fontStyle": "italic", - "fontSize": "@textSizeSecondaryHint", - "color": "@colorTextPrimary" - } - }, - "textStyleDetails": { - "extend": ["textStyleBase2", "mixinDetails"] - } - }, - "onMount": [], - "graphics": {}, - "commands": {}, - "layouts": { - "ListTemplate1": { - "parameters": ["backgroundImage", "title", "logo", "hintText", "listData"], - "item": [ - { - "type": "Container", - "width": "100vw", - "height": "100vh", - "direction": "column", - "items": [ - { - "type": "Image", - "source": "${backgroundImage}", - "scale": "best-fill", - "width": "100vw", - "height": "100vh", - "position": "absolute" - }, - { - "type": "AlexaHeader", - "headerTitle": "${title}", - "headerAttributionImage": "${logo}" - }, - { - "type": "Sequence", - "grow": 1, - "height": "80vh", - "scrollDirection": "vertical", - "paddingLeft": "@marginLeft", - "paddingRight": "@marginRight", - "data": "${listData}", - "numbered": true, - "items": [ - { - "type": "VerticalListItem", - "image": "${data.image.sources[0].url}", - "primaryText": "${data.textContent.primaryText.text}", - "secondaryText": "${data.textContent.secondaryText.text}", - "tertiaryText": "${data.textContent.tertiaryText.text}" - } - ] - } - ] - } - ] - }, - "VerticalListItem": { - "parameters": ["primaryText", "secondaryText", "tertiaryText", "image"], - "item": [ - { - "when": "${viewport.shape == 'round'}", - "type": "Container", - "direction": "row", - "height": 200, - "width": 500, - "alignItems": "center", - "items": [ - { - "type": "Text", - "text": "${ordinal}", - "paddingBottom": "20dp", - "color": "white", - "spacing": "5dp" - }, - { - "type": "Image", - "when": "${image}", - "source": "${image}", - "height": 150, - "width": 150, - "spacing": 15, - "scale": "best-fit", - "align": "top" - }, - { - "type": "Container", - "direction": "column", - "spacing": 25, - "items": [ - { - "type": "Text", - "text": "${primaryText}", - "style": "textStyleDetail", - "grow": 1, - "shrink": 1, - "fontWeight": "300", - "maxLines": 1 - }, - { - "type": "Text", - "text": "${secondaryText}", - "style": "textStyleCaption", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - }, - { - "type": "Text", - "text": "${tertiaryText}", - "style": "textStyleDetails", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - } - ] - } - ] - }, - { - "type": "Container", - "direction": "row", - "height": 125, - "width": 800, - "alignItems": "center", - "items": [ - { - "type": "Text", - "text": "${ordinal}", - "paddingBottom": "20dp", - "color": "white", - "spacing": "5dp" - }, - { - "type": "Image", - "when": "${image}", - "source": "${image}", - "height": 100, - "width": 100, - "align": "top", - "spacing": 50, - "scale": "best-fit" - }, - { - "type": "Container", - "spacing": 30, - "direction": "column", - "items": [ - { - "type": "Text", - "text": "${primaryText}", - "style": "textStyleBody", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - }, - { - "type": "Text", - "text": "${secondaryText}", - "style": "textStyleDetails", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - } - ] - }, - { - "type": "Text", - "text": "${tertiaryText}", - "style": "textStyleBody", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "textAlign": "right", - "maxLines": 1 - } - ] - } - ] - } - }, - "mainTemplate": { - "parameters": ["payload"], - "item": [ - { - "type": "Container", - "id": "BookCabSimpleDialogAPL", - "items": [ - { - "type": "TouchWrapper", - "onPress": { - "type": "SendEvent", - "arguments": ["delegateToColtraneOld"] - }, - "item": { - "type": "Text", - "id": "BookCabSimpleDialogAPL", - "paddingTop": "100", - "paddingLeft": "100", - "color": "green", - "size": 50, - "text": "which city ?" - } - } - ] - } - ] - } -} diff --git a/test/fixture/dialog-evaluate/test-project-1/skill-package/response/display/confirm_date_apl_display/document.json b/test/fixture/dialog-evaluate/test-project-1/skill-package/response/display/confirm_date_apl_display/document.json deleted file mode 100644 index d41ea236..00000000 --- a/test/fixture/dialog-evaluate/test-project-1/skill-package/response/display/confirm_date_apl_display/document.json +++ /dev/null @@ -1,331 +0,0 @@ -{ - "type": "APL", - "version": "1.1", - "settings": {}, - "theme": "dark", - "import": [ - { - "name": "alexa-layouts", - "version": "1.0.0" - } - ], - "resources": [ - { - "description": "Stock color for the light theme", - "colors": { - "colorTextPrimary": "#151920" - } - }, - { - "description": "Stock color for the dark theme", - "when": "${viewport.theme == 'dark'}", - "colors": { - "colorTextPrimary": "#f0f1ef" - } - }, - { - "description": "Standard font sizes", - "dimensions": { - "textSizeBody": 48, - "textSizePrimary": 27, - "textSizeSecondary": 23, - "textSizeDetails": 20, - "textSizeSecondaryHint": 25 - } - }, - { - "description": "Common spacing values", - "dimensions": { - "spacingThin": 6, - "spacingSmall": 12, - "spacingMedium": 24, - "spacingLarge": 48, - "spacingExtraLarge": 72 - } - }, - { - "description": "Common margins and padding", - "dimensions": { - "marginTop": 40, - "marginLeft": 60, - "marginRight": 60, - "marginBottom": 40 - } - } - ], - "styles": { - "textStyleBase": { - "description": "Base font description; set color", - "values": [ - { - "color": "@colorTextPrimary" - } - ] - }, - "textStyleBase0": { - "description": "Thin version of basic font", - "extend": "textStyleBase", - "values": { - "fontWeight": "100" - } - }, - "textStyleBase1": { - "description": "Light version of basic font", - "extend": "textStyleBase", - "values": { - "fontWeight": "300" - } - }, - "textStyleBase2": { - "description": "Regular version of basic font", - "extend": "textStyleBase", - "values": { - "fontWeight": "500" - } - }, - "mixinBody": { - "values": { - "fontSize": "@textSizeBody" - } - }, - "mixinPrimary": { - "values": { - "fontSize": "@textSizePrimary" - } - }, - "mixinDetails": { - "values": { - "fontSize": "@textSizeDetails" - } - }, - "mixinSecondary": { - "values": { - "fontSize": "@textSizeSecondary" - } - }, - "textStylePrimary": { - "extend": ["textStyleBase1", "mixinPrimary"] - }, - "textStyleSecondary": { - "extend": ["textStyleBase0", "mixinSecondary"] - }, - "textStyleBody": { - "extend": ["textStyleBase1", "mixinBody"] - }, - "textStyleSecondaryHint": { - "values": { - "fontFamily": "Bookerly", - "fontStyle": "italic", - "fontSize": "@textSizeSecondaryHint", - "color": "@colorTextPrimary" - } - }, - "textStyleDetails": { - "extend": ["textStyleBase2", "mixinDetails"] - } - }, - "onMount": [], - "graphics": {}, - "commands": {}, - "layouts": { - "ListTemplate1": { - "parameters": ["backgroundImage", "title", "logo", "hintText", "listData"], - "item": [ - { - "type": "Container", - "width": "100vw", - "height": "100vh", - "direction": "column", - "items": [ - { - "type": "Image", - "source": "${backgroundImage}", - "scale": "best-fill", - "width": "100vw", - "height": "100vh", - "position": "absolute" - }, - { - "type": "AlexaHeader", - "headerTitle": "${title}", - "headerAttributionImage": "${logo}" - }, - { - "type": "Sequence", - "grow": 1, - "height": "80vh", - "scrollDirection": "vertical", - "paddingLeft": "@marginLeft", - "paddingRight": "@marginRight", - "data": "${listData}", - "numbered": true, - "items": [ - { - "type": "VerticalListItem", - "image": "${data.image.sources[0].url}", - "primaryText": "${data.textContent.primaryText.text}", - "secondaryText": "${data.textContent.secondaryText.text}", - "tertiaryText": "${data.textContent.tertiaryText.text}" - } - ] - } - ] - } - ] - }, - "VerticalListItem": { - "parameters": ["primaryText", "secondaryText", "tertiaryText", "image"], - "item": [ - { - "when": "${viewport.shape == 'round'}", - "type": "Container", - "direction": "row", - "height": 200, - "width": 500, - "alignItems": "center", - "items": [ - { - "type": "Text", - "text": "${ordinal}", - "paddingBottom": "20dp", - "color": "white", - "spacing": "5dp" - }, - { - "type": "Image", - "when": "${image}", - "source": "${image}", - "height": 150, - "width": 150, - "spacing": 15, - "scale": "best-fit", - "align": "top" - }, - { - "type": "Container", - "direction": "column", - "spacing": 25, - "items": [ - { - "type": "Text", - "text": "${primaryText}", - "style": "textStyleDetail", - "grow": 1, - "shrink": 1, - "fontWeight": "300", - "maxLines": 1 - }, - { - "type": "Text", - "text": "${secondaryText}", - "style": "textStyleCaption", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - }, - { - "type": "Text", - "text": "${tertiaryText}", - "style": "textStyleDetails", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - } - ] - } - ] - }, - { - "type": "Container", - "direction": "row", - "height": 125, - "width": 800, - "alignItems": "center", - "items": [ - { - "type": "Text", - "text": "${ordinal}", - "paddingBottom": "20dp", - "color": "white", - "spacing": "5dp" - }, - { - "type": "Image", - "when": "${image}", - "source": "${image}", - "height": 100, - "width": 100, - "align": "top", - "spacing": 50, - "scale": "best-fit" - }, - { - "type": "Container", - "spacing": 30, - "direction": "column", - "items": [ - { - "type": "Text", - "text": "${primaryText}", - "style": "textStyleBody", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - }, - { - "type": "Text", - "text": "${secondaryText}", - "style": "textStyleDetails", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - } - ] - }, - { - "type": "Text", - "text": "${tertiaryText}", - "style": "textStyleBody", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "textAlign": "right", - "maxLines": 1 - } - ] - } - ] - } - }, - "mainTemplate": { - "parameters": ["payload"], - "item": [ - { - "type": "Container", - "id": "BookCabSimpleDialogAPL", - "items": [ - { - "type": "TouchWrapper", - "onPress": { - "type": "SendEvent", - "arguments": ["delegateToColtraneOld"] - }, - "item": { - "type": "Text", - "id": "BookCabSimpleDialogAPL", - "paddingTop": "100", - "paddingLeft": "100", - "color": "green", - "size": 50, - "text": "which date ?" - } - } - ] - } - ] - } -} diff --git a/test/fixture/dialog-evaluate/test-project-1/skill-package/response/display/confirm_weather_apla_display/document.json b/test/fixture/dialog-evaluate/test-project-1/skill-package/response/display/confirm_weather_apla_display/document.json deleted file mode 100644 index 3bcc0e4a..00000000 --- a/test/fixture/dialog-evaluate/test-project-1/skill-package/response/display/confirm_weather_apla_display/document.json +++ /dev/null @@ -1,379 +0,0 @@ -{ - "type": "APL", - "version": "1.1", - "settings": {}, - "theme": "dark", - "import": [ - { - "name": "alexa-layouts", - "version": "1.0.0" - } - ], - "resources": [ - { - "description": "Stock color for the light theme", - "colors": { - "colorTextPrimary": "#151920" - } - }, - { - "description": "Stock color for the dark theme", - "when": "${viewport.theme == 'dark'}", - "colors": { - "colorTextPrimary": "#f0f1ef" - } - }, - { - "description": "Standard font sizes", - "dimensions": { - "textSizeBody": 48, - "textSizePrimary": 27, - "textSizeSecondary": 23, - "textSizeDetails": 20, - "textSizeSecondaryHint": 25 - } - }, - { - "description": "Common spacing values", - "dimensions": { - "spacingThin": 6, - "spacingSmall": 12, - "spacingMedium": 24, - "spacingLarge": 48, - "spacingExtraLarge": 72 - } - }, - { - "description": "Common margins and padding", - "dimensions": { - "marginTop": 40, - "marginLeft": 60, - "marginRight": 60, - "marginBottom": 40 - } - } - ], - "styles": { - "textStyleBase": { - "description": "Base font description; set color", - "values": [ - { - "color": "@colorTextPrimary" - } - ] - }, - "textStyleBase0": { - "description": "Thin version of basic font", - "extend": "textStyleBase", - "values": { - "fontWeight": "100" - } - }, - "textStyleBase1": { - "description": "Light version of basic font", - "extend": "textStyleBase", - "values": { - "fontWeight": "300" - } - }, - "textStyleBase2": { - "description": "Regular version of basic font", - "extend": "textStyleBase", - "values": { - "fontWeight": "500" - } - }, - "mixinBody": { - "values": { - "fontSize": "@textSizeBody" - } - }, - "mixinPrimary": { - "values": { - "fontSize": "@textSizePrimary" - } - }, - "mixinDetails": { - "values": { - "fontSize": "@textSizeDetails" - } - }, - "mixinSecondary": { - "values": { - "fontSize": "@textSizeSecondary" - } - }, - "textStylePrimary": { - "extend": ["textStyleBase1", "mixinPrimary"] - }, - "textStyleSecondary": { - "extend": ["textStyleBase0", "mixinSecondary"] - }, - "textStyleBody": { - "extend": ["textStyleBase1", "mixinBody"] - }, - "textStyleSecondaryHint": { - "values": { - "fontFamily": "Bookerly", - "fontStyle": "italic", - "fontSize": "@textSizeSecondaryHint", - "color": "@colorTextPrimary" - } - }, - "textStyleDetails": { - "extend": ["textStyleBase2", "mixinDetails"] - } - }, - "onMount": [], - "graphics": {}, - "commands": {}, - "layouts": { - "ListTemplate1": { - "parameters": ["backgroundImage", "title", "logo", "hintText", "listData"], - "item": [ - { - "type": "Container", - "width": "100vw", - "height": "100vh", - "direction": "column", - "items": [ - { - "type": "Image", - "source": "${backgroundImage}", - "scale": "best-fill", - "width": "100vw", - "height": "100vh", - "position": "absolute" - }, - { - "type": "AlexaHeader", - "headerTitle": "${title}", - "headerAttributionImage": "${logo}" - }, - { - "type": "Sequence", - "grow": 1, - "height": "80vh", - "scrollDirection": "vertical", - "paddingLeft": "@marginLeft", - "paddingRight": "@marginRight", - "data": "${listData}", - "numbered": true, - "items": [ - { - "type": "VerticalListItem", - "image": "${data.image.sources[0].url}", - "primaryText": "${data.textContent.primaryText.text}", - "secondaryText": "${data.textContent.secondaryText.text}", - "tertiaryText": "${data.textContent.tertiaryText.text}" - } - ] - } - ] - } - ] - }, - "VerticalListItem": { - "parameters": ["primaryText", "secondaryText", "tertiaryText", "image"], - "item": [ - { - "when": "${viewport.shape == 'round'}", - "type": "Container", - "direction": "row", - "height": 200, - "width": 500, - "alignItems": "center", - "items": [ - { - "type": "Text", - "text": "${ordinal}", - "paddingBottom": "20dp", - "color": "white", - "spacing": "5dp" - }, - { - "type": "Image", - "when": "${image}", - "source": "${image}", - "height": 150, - "width": 150, - "spacing": 15, - "scale": "best-fit", - "align": "top" - }, - { - "type": "Container", - "direction": "column", - "spacing": 25, - "items": [ - { - "type": "Text", - "text": "${primaryText}", - "style": "textStyleDetail", - "grow": 1, - "shrink": 1, - "fontWeight": "300", - "maxLines": 1 - }, - { - "type": "Text", - "text": "${secondaryText}", - "style": "textStyleCaption", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - }, - { - "type": "Text", - "text": "${tertiaryText}", - "style": "textStyleDetails", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - } - ] - } - ] - }, - { - "type": "Container", - "direction": "row", - "height": 125, - "width": 800, - "alignItems": "center", - "items": [ - { - "type": "Text", - "text": "${ordinal}", - "paddingBottom": "20dp", - "color": "white", - "spacing": "5dp" - }, - { - "type": "Image", - "when": "${image}", - "source": "${image}", - "height": 100, - "width": 100, - "align": "top", - "spacing": 50, - "scale": "best-fit" - }, - { - "type": "Container", - "spacing": 30, - "direction": "column", - "items": [ - { - "type": "Text", - "text": "${primaryText}", - "style": "textStyleBody", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - }, - { - "type": "Text", - "text": "${secondaryText}", - "style": "textStyleDetails", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - } - ] - }, - { - "type": "Text", - "text": "${tertiaryText}", - "style": "textStyleBody", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "textAlign": "right", - "maxLines": 1 - } - ] - } - ] - } - }, - "mainTemplate": { - "parameters": ["payload"], - "item": [ - { - "type": "Container", - "id": "BookCabSimpleDialogAPL", - "items": [ - { - "type": "TouchWrapper", - "onPress": { - "type": "SendEvent", - "arguments": ["delegateToSkillNew"] - }, - "item": { - "type": "Text", - "id": "BookCabSimpleDialogAPL", - "paddingTop": "100", - "paddingLeft": "100", - "color": "green", - "size": 50, - "text": "delegateToSkillNew" - } - }, - { - "type": "TouchWrapper", - "onPress": { - "type": "SendEvent", - "arguments": ["delegateToSkillOld"] - }, - "item": { - "type": "Text", - "id": "BookCabSimpleDialogAPL", - "paddingTop": "100", - "paddingLeft": "100", - "color": "green", - "size": 50, - "text": "delegateToSkillOld" - } - }, - { - "type": "TouchWrapper", - "onPress": { - "type": "SendEvent", - "arguments": ["delegateToColtraneNew"] - }, - "item": { - "type": "Text", - "id": "BookCabSimpleDialogAPL", - "paddingTop": "100", - "paddingLeft": "100", - "color": "green", - "size": 50, - "text": "delegateToColtraneNew" - } - }, - { - "type": "TouchWrapper", - "onPress": { - "type": "SendEvent", - "arguments": ["delegateToColtraneOld"] - }, - "item": { - "type": "Text", - "id": "BookCabSimpleDialogAPL", - "paddingTop": "100", - "paddingLeft": "100", - "color": "green", - "size": 50, - "text": "delegateToColtraneOld" - } - } - ] - } - ] - } -} diff --git a/test/fixture/dialog-evaluate/test-project-1/skill-package/response/display/request_city_apl_display/document.json b/test/fixture/dialog-evaluate/test-project-1/skill-package/response/display/request_city_apl_display/document.json deleted file mode 100644 index 6fea1ff7..00000000 --- a/test/fixture/dialog-evaluate/test-project-1/skill-package/response/display/request_city_apl_display/document.json +++ /dev/null @@ -1,331 +0,0 @@ -{ - "type": "APL", - "version": "1.1", - "settings": {}, - "theme": "dark", - "import": [ - { - "name": "alexa-layouts", - "version": "1.0.0" - } - ], - "resources": [ - { - "description": "Stock color for the light theme", - "colors": { - "colorTextPrimary": "#151920" - } - }, - { - "description": "Stock color for the dark theme", - "when": "${viewport.theme == 'dark'}", - "colors": { - "colorTextPrimary": "#f0f1ef" - } - }, - { - "description": "Standard font sizes", - "dimensions": { - "textSizeBody": 48, - "textSizePrimary": 27, - "textSizeSecondary": 23, - "textSizeDetails": 20, - "textSizeSecondaryHint": 25 - } - }, - { - "description": "Common spacing values", - "dimensions": { - "spacingThin": 6, - "spacingSmall": 12, - "spacingMedium": 24, - "spacingLarge": 48, - "spacingExtraLarge": 72 - } - }, - { - "description": "Common margins and padding", - "dimensions": { - "marginTop": 40, - "marginLeft": 60, - "marginRight": 60, - "marginBottom": 40 - } - } - ], - "styles": { - "textStyleBase": { - "description": "Base font description; set color", - "values": [ - { - "color": "@colorTextPrimary" - } - ] - }, - "textStyleBase0": { - "description": "Thin version of basic font", - "extend": "textStyleBase", - "values": { - "fontWeight": "100" - } - }, - "textStyleBase1": { - "description": "Light version of basic font", - "extend": "textStyleBase", - "values": { - "fontWeight": "300" - } - }, - "textStyleBase2": { - "description": "Regular version of basic font", - "extend": "textStyleBase", - "values": { - "fontWeight": "500" - } - }, - "mixinBody": { - "values": { - "fontSize": "@textSizeBody" - } - }, - "mixinPrimary": { - "values": { - "fontSize": "@textSizePrimary" - } - }, - "mixinDetails": { - "values": { - "fontSize": "@textSizeDetails" - } - }, - "mixinSecondary": { - "values": { - "fontSize": "@textSizeSecondary" - } - }, - "textStylePrimary": { - "extend": ["textStyleBase1", "mixinPrimary"] - }, - "textStyleSecondary": { - "extend": ["textStyleBase0", "mixinSecondary"] - }, - "textStyleBody": { - "extend": ["textStyleBase1", "mixinBody"] - }, - "textStyleSecondaryHint": { - "values": { - "fontFamily": "Bookerly", - "fontStyle": "italic", - "fontSize": "@textSizeSecondaryHint", - "color": "@colorTextPrimary" - } - }, - "textStyleDetails": { - "extend": ["textStyleBase2", "mixinDetails"] - } - }, - "onMount": [], - "graphics": {}, - "commands": {}, - "layouts": { - "ListTemplate1": { - "parameters": ["backgroundImage", "title", "logo", "hintText", "listData"], - "item": [ - { - "type": "Container", - "width": "100vw", - "height": "100vh", - "direction": "column", - "items": [ - { - "type": "Image", - "source": "${backgroundImage}", - "scale": "best-fill", - "width": "100vw", - "height": "100vh", - "position": "absolute" - }, - { - "type": "AlexaHeader", - "headerTitle": "${title}", - "headerAttributionImage": "${logo}" - }, - { - "type": "Sequence", - "grow": 1, - "height": "80vh", - "scrollDirection": "vertical", - "paddingLeft": "@marginLeft", - "paddingRight": "@marginRight", - "data": "${listData}", - "numbered": true, - "items": [ - { - "type": "VerticalListItem", - "image": "${data.image.sources[0].url}", - "primaryText": "${data.textContent.primaryText.text}", - "secondaryText": "${data.textContent.secondaryText.text}", - "tertiaryText": "${data.textContent.tertiaryText.text}" - } - ] - } - ] - } - ] - }, - "VerticalListItem": { - "parameters": ["primaryText", "secondaryText", "tertiaryText", "image"], - "item": [ - { - "when": "${viewport.shape == 'round'}", - "type": "Container", - "direction": "row", - "height": 200, - "width": 500, - "alignItems": "center", - "items": [ - { - "type": "Text", - "text": "${ordinal}", - "paddingBottom": "20dp", - "color": "white", - "spacing": "5dp" - }, - { - "type": "Image", - "when": "${image}", - "source": "${image}", - "height": 150, - "width": 150, - "spacing": 15, - "scale": "best-fit", - "align": "top" - }, - { - "type": "Container", - "direction": "column", - "spacing": 25, - "items": [ - { - "type": "Text", - "text": "${primaryText}", - "style": "textStyleDetail", - "grow": 1, - "shrink": 1, - "fontWeight": "300", - "maxLines": 1 - }, - { - "type": "Text", - "text": "${secondaryText}", - "style": "textStyleCaption", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - }, - { - "type": "Text", - "text": "${tertiaryText}", - "style": "textStyleDetails", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - } - ] - } - ] - }, - { - "type": "Container", - "direction": "row", - "height": 125, - "width": 800, - "alignItems": "center", - "items": [ - { - "type": "Text", - "text": "${ordinal}", - "paddingBottom": "20dp", - "color": "white", - "spacing": "5dp" - }, - { - "type": "Image", - "when": "${image}", - "source": "${image}", - "height": 100, - "width": 100, - "align": "top", - "spacing": 50, - "scale": "best-fit" - }, - { - "type": "Container", - "spacing": 30, - "direction": "column", - "items": [ - { - "type": "Text", - "text": "${primaryText}", - "style": "textStyleBody", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - }, - { - "type": "Text", - "text": "${secondaryText}", - "style": "textStyleDetails", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - } - ] - }, - { - "type": "Text", - "text": "${tertiaryText}", - "style": "textStyleBody", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "textAlign": "right", - "maxLines": 1 - } - ] - } - ] - } - }, - "mainTemplate": { - "parameters": ["payload"], - "item": [ - { - "type": "Container", - "id": "BookCabSimpleDialogAPL", - "items": [ - { - "type": "TouchWrapper", - "onPress": { - "type": "SendEvent", - "arguments": ["delegateToColtraneOld"] - }, - "item": { - "type": "Text", - "id": "BookCabSimpleDialogAPL", - "paddingTop": "100", - "paddingLeft": "100", - "color": "green", - "size": 50, - "text": "which city ?" - } - } - ] - } - ] - } -} diff --git a/test/fixture/dialog-evaluate/test-project-1/skill-package/response/display/request_date_apl_display/document.json b/test/fixture/dialog-evaluate/test-project-1/skill-package/response/display/request_date_apl_display/document.json deleted file mode 100644 index d41ea236..00000000 --- a/test/fixture/dialog-evaluate/test-project-1/skill-package/response/display/request_date_apl_display/document.json +++ /dev/null @@ -1,331 +0,0 @@ -{ - "type": "APL", - "version": "1.1", - "settings": {}, - "theme": "dark", - "import": [ - { - "name": "alexa-layouts", - "version": "1.0.0" - } - ], - "resources": [ - { - "description": "Stock color for the light theme", - "colors": { - "colorTextPrimary": "#151920" - } - }, - { - "description": "Stock color for the dark theme", - "when": "${viewport.theme == 'dark'}", - "colors": { - "colorTextPrimary": "#f0f1ef" - } - }, - { - "description": "Standard font sizes", - "dimensions": { - "textSizeBody": 48, - "textSizePrimary": 27, - "textSizeSecondary": 23, - "textSizeDetails": 20, - "textSizeSecondaryHint": 25 - } - }, - { - "description": "Common spacing values", - "dimensions": { - "spacingThin": 6, - "spacingSmall": 12, - "spacingMedium": 24, - "spacingLarge": 48, - "spacingExtraLarge": 72 - } - }, - { - "description": "Common margins and padding", - "dimensions": { - "marginTop": 40, - "marginLeft": 60, - "marginRight": 60, - "marginBottom": 40 - } - } - ], - "styles": { - "textStyleBase": { - "description": "Base font description; set color", - "values": [ - { - "color": "@colorTextPrimary" - } - ] - }, - "textStyleBase0": { - "description": "Thin version of basic font", - "extend": "textStyleBase", - "values": { - "fontWeight": "100" - } - }, - "textStyleBase1": { - "description": "Light version of basic font", - "extend": "textStyleBase", - "values": { - "fontWeight": "300" - } - }, - "textStyleBase2": { - "description": "Regular version of basic font", - "extend": "textStyleBase", - "values": { - "fontWeight": "500" - } - }, - "mixinBody": { - "values": { - "fontSize": "@textSizeBody" - } - }, - "mixinPrimary": { - "values": { - "fontSize": "@textSizePrimary" - } - }, - "mixinDetails": { - "values": { - "fontSize": "@textSizeDetails" - } - }, - "mixinSecondary": { - "values": { - "fontSize": "@textSizeSecondary" - } - }, - "textStylePrimary": { - "extend": ["textStyleBase1", "mixinPrimary"] - }, - "textStyleSecondary": { - "extend": ["textStyleBase0", "mixinSecondary"] - }, - "textStyleBody": { - "extend": ["textStyleBase1", "mixinBody"] - }, - "textStyleSecondaryHint": { - "values": { - "fontFamily": "Bookerly", - "fontStyle": "italic", - "fontSize": "@textSizeSecondaryHint", - "color": "@colorTextPrimary" - } - }, - "textStyleDetails": { - "extend": ["textStyleBase2", "mixinDetails"] - } - }, - "onMount": [], - "graphics": {}, - "commands": {}, - "layouts": { - "ListTemplate1": { - "parameters": ["backgroundImage", "title", "logo", "hintText", "listData"], - "item": [ - { - "type": "Container", - "width": "100vw", - "height": "100vh", - "direction": "column", - "items": [ - { - "type": "Image", - "source": "${backgroundImage}", - "scale": "best-fill", - "width": "100vw", - "height": "100vh", - "position": "absolute" - }, - { - "type": "AlexaHeader", - "headerTitle": "${title}", - "headerAttributionImage": "${logo}" - }, - { - "type": "Sequence", - "grow": 1, - "height": "80vh", - "scrollDirection": "vertical", - "paddingLeft": "@marginLeft", - "paddingRight": "@marginRight", - "data": "${listData}", - "numbered": true, - "items": [ - { - "type": "VerticalListItem", - "image": "${data.image.sources[0].url}", - "primaryText": "${data.textContent.primaryText.text}", - "secondaryText": "${data.textContent.secondaryText.text}", - "tertiaryText": "${data.textContent.tertiaryText.text}" - } - ] - } - ] - } - ] - }, - "VerticalListItem": { - "parameters": ["primaryText", "secondaryText", "tertiaryText", "image"], - "item": [ - { - "when": "${viewport.shape == 'round'}", - "type": "Container", - "direction": "row", - "height": 200, - "width": 500, - "alignItems": "center", - "items": [ - { - "type": "Text", - "text": "${ordinal}", - "paddingBottom": "20dp", - "color": "white", - "spacing": "5dp" - }, - { - "type": "Image", - "when": "${image}", - "source": "${image}", - "height": 150, - "width": 150, - "spacing": 15, - "scale": "best-fit", - "align": "top" - }, - { - "type": "Container", - "direction": "column", - "spacing": 25, - "items": [ - { - "type": "Text", - "text": "${primaryText}", - "style": "textStyleDetail", - "grow": 1, - "shrink": 1, - "fontWeight": "300", - "maxLines": 1 - }, - { - "type": "Text", - "text": "${secondaryText}", - "style": "textStyleCaption", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - }, - { - "type": "Text", - "text": "${tertiaryText}", - "style": "textStyleDetails", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - } - ] - } - ] - }, - { - "type": "Container", - "direction": "row", - "height": 125, - "width": 800, - "alignItems": "center", - "items": [ - { - "type": "Text", - "text": "${ordinal}", - "paddingBottom": "20dp", - "color": "white", - "spacing": "5dp" - }, - { - "type": "Image", - "when": "${image}", - "source": "${image}", - "height": 100, - "width": 100, - "align": "top", - "spacing": 50, - "scale": "best-fit" - }, - { - "type": "Container", - "spacing": 30, - "direction": "column", - "items": [ - { - "type": "Text", - "text": "${primaryText}", - "style": "textStyleBody", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - }, - { - "type": "Text", - "text": "${secondaryText}", - "style": "textStyleDetails", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - } - ] - }, - { - "type": "Text", - "text": "${tertiaryText}", - "style": "textStyleBody", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "textAlign": "right", - "maxLines": 1 - } - ] - } - ] - } - }, - "mainTemplate": { - "parameters": ["payload"], - "item": [ - { - "type": "Container", - "id": "BookCabSimpleDialogAPL", - "items": [ - { - "type": "TouchWrapper", - "onPress": { - "type": "SendEvent", - "arguments": ["delegateToColtraneOld"] - }, - "item": { - "type": "Text", - "id": "BookCabSimpleDialogAPL", - "paddingTop": "100", - "paddingLeft": "100", - "color": "green", - "size": 50, - "text": "which date ?" - } - } - ] - } - ] - } -} diff --git a/test/fixture/dialog-evaluate/test-project-1/skill-package/response/display/weather_success_apl_display/document.json b/test/fixture/dialog-evaluate/test-project-1/skill-package/response/display/weather_success_apl_display/document.json deleted file mode 100644 index 3bcc0e4a..00000000 --- a/test/fixture/dialog-evaluate/test-project-1/skill-package/response/display/weather_success_apl_display/document.json +++ /dev/null @@ -1,379 +0,0 @@ -{ - "type": "APL", - "version": "1.1", - "settings": {}, - "theme": "dark", - "import": [ - { - "name": "alexa-layouts", - "version": "1.0.0" - } - ], - "resources": [ - { - "description": "Stock color for the light theme", - "colors": { - "colorTextPrimary": "#151920" - } - }, - { - "description": "Stock color for the dark theme", - "when": "${viewport.theme == 'dark'}", - "colors": { - "colorTextPrimary": "#f0f1ef" - } - }, - { - "description": "Standard font sizes", - "dimensions": { - "textSizeBody": 48, - "textSizePrimary": 27, - "textSizeSecondary": 23, - "textSizeDetails": 20, - "textSizeSecondaryHint": 25 - } - }, - { - "description": "Common spacing values", - "dimensions": { - "spacingThin": 6, - "spacingSmall": 12, - "spacingMedium": 24, - "spacingLarge": 48, - "spacingExtraLarge": 72 - } - }, - { - "description": "Common margins and padding", - "dimensions": { - "marginTop": 40, - "marginLeft": 60, - "marginRight": 60, - "marginBottom": 40 - } - } - ], - "styles": { - "textStyleBase": { - "description": "Base font description; set color", - "values": [ - { - "color": "@colorTextPrimary" - } - ] - }, - "textStyleBase0": { - "description": "Thin version of basic font", - "extend": "textStyleBase", - "values": { - "fontWeight": "100" - } - }, - "textStyleBase1": { - "description": "Light version of basic font", - "extend": "textStyleBase", - "values": { - "fontWeight": "300" - } - }, - "textStyleBase2": { - "description": "Regular version of basic font", - "extend": "textStyleBase", - "values": { - "fontWeight": "500" - } - }, - "mixinBody": { - "values": { - "fontSize": "@textSizeBody" - } - }, - "mixinPrimary": { - "values": { - "fontSize": "@textSizePrimary" - } - }, - "mixinDetails": { - "values": { - "fontSize": "@textSizeDetails" - } - }, - "mixinSecondary": { - "values": { - "fontSize": "@textSizeSecondary" - } - }, - "textStylePrimary": { - "extend": ["textStyleBase1", "mixinPrimary"] - }, - "textStyleSecondary": { - "extend": ["textStyleBase0", "mixinSecondary"] - }, - "textStyleBody": { - "extend": ["textStyleBase1", "mixinBody"] - }, - "textStyleSecondaryHint": { - "values": { - "fontFamily": "Bookerly", - "fontStyle": "italic", - "fontSize": "@textSizeSecondaryHint", - "color": "@colorTextPrimary" - } - }, - "textStyleDetails": { - "extend": ["textStyleBase2", "mixinDetails"] - } - }, - "onMount": [], - "graphics": {}, - "commands": {}, - "layouts": { - "ListTemplate1": { - "parameters": ["backgroundImage", "title", "logo", "hintText", "listData"], - "item": [ - { - "type": "Container", - "width": "100vw", - "height": "100vh", - "direction": "column", - "items": [ - { - "type": "Image", - "source": "${backgroundImage}", - "scale": "best-fill", - "width": "100vw", - "height": "100vh", - "position": "absolute" - }, - { - "type": "AlexaHeader", - "headerTitle": "${title}", - "headerAttributionImage": "${logo}" - }, - { - "type": "Sequence", - "grow": 1, - "height": "80vh", - "scrollDirection": "vertical", - "paddingLeft": "@marginLeft", - "paddingRight": "@marginRight", - "data": "${listData}", - "numbered": true, - "items": [ - { - "type": "VerticalListItem", - "image": "${data.image.sources[0].url}", - "primaryText": "${data.textContent.primaryText.text}", - "secondaryText": "${data.textContent.secondaryText.text}", - "tertiaryText": "${data.textContent.tertiaryText.text}" - } - ] - } - ] - } - ] - }, - "VerticalListItem": { - "parameters": ["primaryText", "secondaryText", "tertiaryText", "image"], - "item": [ - { - "when": "${viewport.shape == 'round'}", - "type": "Container", - "direction": "row", - "height": 200, - "width": 500, - "alignItems": "center", - "items": [ - { - "type": "Text", - "text": "${ordinal}", - "paddingBottom": "20dp", - "color": "white", - "spacing": "5dp" - }, - { - "type": "Image", - "when": "${image}", - "source": "${image}", - "height": 150, - "width": 150, - "spacing": 15, - "scale": "best-fit", - "align": "top" - }, - { - "type": "Container", - "direction": "column", - "spacing": 25, - "items": [ - { - "type": "Text", - "text": "${primaryText}", - "style": "textStyleDetail", - "grow": 1, - "shrink": 1, - "fontWeight": "300", - "maxLines": 1 - }, - { - "type": "Text", - "text": "${secondaryText}", - "style": "textStyleCaption", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - }, - { - "type": "Text", - "text": "${tertiaryText}", - "style": "textStyleDetails", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - } - ] - } - ] - }, - { - "type": "Container", - "direction": "row", - "height": 125, - "width": 800, - "alignItems": "center", - "items": [ - { - "type": "Text", - "text": "${ordinal}", - "paddingBottom": "20dp", - "color": "white", - "spacing": "5dp" - }, - { - "type": "Image", - "when": "${image}", - "source": "${image}", - "height": 100, - "width": 100, - "align": "top", - "spacing": 50, - "scale": "best-fit" - }, - { - "type": "Container", - "spacing": 30, - "direction": "column", - "items": [ - { - "type": "Text", - "text": "${primaryText}", - "style": "textStyleBody", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - }, - { - "type": "Text", - "text": "${secondaryText}", - "style": "textStyleDetails", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "maxLines": 1 - } - ] - }, - { - "type": "Text", - "text": "${tertiaryText}", - "style": "textStyleBody", - "fontWeight": "300", - "grow": 1, - "shrink": 1, - "textAlign": "right", - "maxLines": 1 - } - ] - } - ] - } - }, - "mainTemplate": { - "parameters": ["payload"], - "item": [ - { - "type": "Container", - "id": "BookCabSimpleDialogAPL", - "items": [ - { - "type": "TouchWrapper", - "onPress": { - "type": "SendEvent", - "arguments": ["delegateToSkillNew"] - }, - "item": { - "type": "Text", - "id": "BookCabSimpleDialogAPL", - "paddingTop": "100", - "paddingLeft": "100", - "color": "green", - "size": 50, - "text": "delegateToSkillNew" - } - }, - { - "type": "TouchWrapper", - "onPress": { - "type": "SendEvent", - "arguments": ["delegateToSkillOld"] - }, - "item": { - "type": "Text", - "id": "BookCabSimpleDialogAPL", - "paddingTop": "100", - "paddingLeft": "100", - "color": "green", - "size": 50, - "text": "delegateToSkillOld" - } - }, - { - "type": "TouchWrapper", - "onPress": { - "type": "SendEvent", - "arguments": ["delegateToColtraneNew"] - }, - "item": { - "type": "Text", - "id": "BookCabSimpleDialogAPL", - "paddingTop": "100", - "paddingLeft": "100", - "color": "green", - "size": 50, - "text": "delegateToColtraneNew" - } - }, - { - "type": "TouchWrapper", - "onPress": { - "type": "SendEvent", - "arguments": ["delegateToColtraneOld"] - }, - "item": { - "type": "Text", - "id": "BookCabSimpleDialogAPL", - "paddingTop": "100", - "paddingLeft": "100", - "color": "green", - "size": 50, - "text": "delegateToColtraneOld" - } - } - ] - } - ] - } -} diff --git a/test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/AlexaConversationsBye/document.json b/test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/AlexaConversationsBye/document.json deleted file mode 100644 index a0e2b3a8..00000000 --- a/test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/AlexaConversationsBye/document.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": ["payload"], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "Bye.", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} diff --git a/test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/AlexaConversationsNotifyFailure/document.json b/test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/AlexaConversationsNotifyFailure/document.json deleted file mode 100644 index 61d75e08..00000000 --- a/test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/AlexaConversationsNotifyFailure/document.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": ["payload"], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "Sorry, there was an error in the request.", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} diff --git a/test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/AlexaConversationsOutOfDomain/document.json b/test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/AlexaConversationsOutOfDomain/document.json deleted file mode 100644 index e23d5986..00000000 --- a/test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/AlexaConversationsOutOfDomain/document.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": ["payload"], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "Sorry, I don't understand.", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} diff --git a/test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/AlexaConversationsProvideHelp/document.json b/test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/AlexaConversationsProvideHelp/document.json deleted file mode 100644 index 612a6f6e..00000000 --- a/test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/AlexaConversationsProvideHelp/document.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": ["payload"], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "I can give you the weather report. Just say \"what's the weather\" to start.", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} diff --git a/test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/AlexaConversationsRequestMore/document.json b/test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/AlexaConversationsRequestMore/document.json deleted file mode 100644 index 32a98507..00000000 --- a/test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/AlexaConversationsRequestMore/document.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": ["payload"], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "What do you want to do.", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} diff --git a/test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/AlexaConversationsThankYou/document.json b/test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/AlexaConversationsThankYou/document.json deleted file mode 100644 index 4aeb6f4b..00000000 --- a/test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/AlexaConversationsThankYou/document.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": ["payload"], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "Thank you.", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} diff --git a/test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/AlexaConversationsWelcome/document.json b/test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/AlexaConversationsWelcome/document.json deleted file mode 100644 index b4ce85fe..00000000 --- a/test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/AlexaConversationsWelcome/document.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": ["payload"], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "Welcome to the weather bot, I can give you the weather report. Just say \"what's the weather\" to start.", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} diff --git a/test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/AlexaConversationsYouAreWelcome/document.json b/test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/AlexaConversationsYouAreWelcome/document.json deleted file mode 100644 index 2cd1b9a8..00000000 --- a/test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/AlexaConversationsYouAreWelcome/document.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": ["payload"], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "You are welcome.", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} diff --git a/test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/confirmAction_complexNames_apla/document.json b/test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/confirmAction_complexNames_apla/document.json deleted file mode 100644 index d4f492d7..00000000 --- a/test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/confirmAction_complexNames_apla/document.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": ["payload"], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "confirm Action your cool name ${payload.name} ? ", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} diff --git a/test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/confirmArgs_complexNames_apla/document.json b/test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/confirmArgs_complexNames_apla/document.json deleted file mode 100644 index a5a3eec5..00000000 --- a/test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/confirmArgs_complexNames_apla/document.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": ["payload"], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "confirm args your cool name ${payload.name} ? ", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} diff --git a/test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/confirm_colorName_apla/document.json b/test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/confirm_colorName_apla/document.json deleted file mode 100644 index 62c9758b..00000000 --- a/test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/confirm_colorName_apla/document.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": ["payload"], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "confirm color is ${payload.colorName} ? ", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} diff --git a/test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/confirm_main_addon_list_apla/document.json b/test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/confirm_main_addon_list_apla/document.json deleted file mode 100644 index 113da0d0..00000000 --- a/test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/confirm_main_addon_list_apla/document.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": ["payload"], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "confirm ${payload.foodName} with ${payload.addOn} ? ", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} diff --git a/test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/notused_apla/document.json b/test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/notused_apla/document.json deleted file mode 100644 index 91cdb444..00000000 --- a/test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/notused_apla/document.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": ["payload"], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "dummy response not used", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} diff --git a/test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/numericfeedback_apla/document.json b/test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/numericfeedback_apla/document.json deleted file mode 100644 index 2219120c..00000000 --- a/test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/numericfeedback_apla/document.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": ["payload"], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "Your random number was ${payload.num}. How did we do? Please give this interaction a rating between 1-5, where 5 is the highest rating", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} diff --git a/test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/rating_apla/document.json b/test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/rating_apla/document.json deleted file mode 100644 index 06b50d68..00000000 --- a/test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/rating_apla/document.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": ["payload"], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "rating please?", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} diff --git a/test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/request_city_apla/document.json b/test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/request_city_apla/document.json deleted file mode 100644 index 64297b5e..00000000 --- a/test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/request_city_apla/document.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": ["payload"], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "Which city?", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} diff --git a/test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/request_city_date_apla/document.json b/test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/request_city_date_apla/document.json deleted file mode 100644 index a55ea5e1..00000000 --- a/test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/request_city_date_apla/document.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": ["payload"], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "Which city and for which date?", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} diff --git a/test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/request_colorName_apla/document.json b/test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/request_colorName_apla/document.json deleted file mode 100644 index 5e5891e1..00000000 --- a/test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/request_colorName_apla/document.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": ["payload"], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "which color?", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} diff --git a/test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/request_date_apla/document.json b/test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/request_date_apla/document.json deleted file mode 100644 index af3a3f7d..00000000 --- a/test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/request_date_apla/document.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": ["payload"], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "Which date?", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} diff --git a/test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/request_fruitName_apla/document.json b/test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/request_fruitName_apla/document.json deleted file mode 100644 index 5e5d608a..00000000 --- a/test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/request_fruitName_apla/document.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": ["payload"], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "tell me the fruit name ?", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - }, - { - "type": "Speech", - "contentType": "text", - "content": "random slection tell me the fruit name ?", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} diff --git a/test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/request_listAddOns_apla/document.json b/test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/request_listAddOns_apla/document.json deleted file mode 100644 index 50faed8e..00000000 --- a/test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/request_listAddOns_apla/document.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": ["payload"], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "what are the add ons?", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} diff --git a/test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/request_mainFoodName_apla/document.json b/test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/request_mainFoodName_apla/document.json deleted file mode 100644 index 316161b3..00000000 --- a/test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/request_mainFoodName_apla/document.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": ["payload"], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "What is the main food name?", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} diff --git a/test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/request_name_apla/document.json b/test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/request_name_apla/document.json deleted file mode 100644 index db05dfee..00000000 --- a/test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/request_name_apla/document.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": ["payload"], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "SSML", - "content": "what is your cool name?", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} diff --git a/test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/success_colorFruitAPI_apla/document.json b/test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/success_colorFruitAPI_apla/document.json deleted file mode 100644 index b566e3fb..00000000 --- a/test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/success_colorFruitAPI_apla/document.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": ["payload"], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "price of an ${payload.result.fruitName} is free bucks ", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} diff --git a/test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/success_cookingAPI_apla/document.json b/test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/success_cookingAPI_apla/document.json deleted file mode 100644 index 2b920b3d..00000000 --- a/test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/success_cookingAPI_apla/document.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": ["payload"], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "we have ${payload.status.orderStatus}", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} diff --git a/test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/success_favColorSign_Name_apla/document.json b/test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/success_favColorSign_Name_apla/document.json deleted file mode 100644 index 65211056..00000000 --- a/test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/success_favColorSign_Name_apla/document.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": ["payload"], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "Fav color of ${payload.result.name}, is ${payload.result.color}", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} diff --git a/test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/success_fruitNameAPI_apla/document.json b/test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/success_fruitNameAPI_apla/document.json deleted file mode 100644 index 0db81389..00000000 --- a/test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/success_fruitNameAPI_apla/document.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": ["payload"], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "price of an ${payload.result.fruitName} is ${payload.result.price} bucks ", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} diff --git a/test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/success_weather_apla/document.json b/test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/success_weather_apla/document.json deleted file mode 100644 index 14fa169d..00000000 --- a/test/fixture/dialog-evaluate/test-project-1/skill-package/response/prompts/success_weather_apla/document.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "type": "APL-A", - "version": "0.1", - "mainTemplate": { - "parameters": ["payload"], - "item": { - "type": "RandomSelector", - "description": "Change 'type' above to try different Selector Component Types like Sequential", - "items": [ - { - "type": "Speech", - "contentType": "text", - "content": "In ${payload.weatherResult.cityName}, it's a high of ${payload.weatherResult.highTemp} degrees and a low of ${payload.weatherResult.lowTemp} degrees.", - "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that" - } - ] - } - } -} diff --git a/test/fixture/dialog-evaluate/test-project-1/skill-package/skill.json b/test/fixture/dialog-evaluate/test-project-1/skill-package/skill.json deleted file mode 100644 index 9ba5d6aa..00000000 --- a/test/fixture/dialog-evaluate/test-project-1/skill-package/skill.json +++ /dev/null @@ -1,92 +0,0 @@ -{ - "manifest": { - "apis": { - "custom": { - "dialogManagement": { - "dialogManagers": [ - { - "type": "AMAZON.Conversations" - } - ], - "sessionStartDelegationStrategy": { - "target": "AMAZON.Conversations" - } - }, - "endpoint": { - "uri": "arn:aws:lambda:us-east-1:12345678:function:123456:Release_0" - }, - "interfaces": [ - { - "supportedViewports": [ - { - "maxHeight": 480, - "maxWidth": 480, - "minHeight": 480, - "minWidth": 480, - "mode": "HUB", - "shape": "ROUND" - }, - { - "maxHeight": 600, - "maxWidth": 1024, - "minHeight": 600, - "minWidth": 1024, - "mode": "HUB", - "shape": "RECTANGLE" - }, - { - "maxHeight": 800, - "maxWidth": 1280, - "minHeight": 800, - "minWidth": 1280, - "mode": "HUB", - "shape": "RECTANGLE" - }, - { - "maxHeight": 540, - "maxWidth": 960, - "minHeight": 540, - "minWidth": 960, - "mode": "TV", - "shape": "RECTANGLE" - } - ], - "type": "ALEXA_PRESENTATION_APL" - } - ], - "regions": { - "EU": { - "endpoint": { - "uri": "arn:aws:lambda:us-east-1:12345678:function:123456:Release_0" - } - }, - "NA": { - "endpoint": { - "uri": "arn:aws:lambda:us-east-1:12345678:function:123456:Release_0" - } - }, - "FE": { - "endpoint": { - "uri": "arn:aws:lambda:us-east-1:12345678:function:123456:Release_0" - } - } - } - } - }, - "manifestVersion": "1.0", - "publishingInformation": { - "category": "KNOWLEDGE_AND_TRIVIA", - "distributionCountries": [], - "isAvailableWorldwide": true, - "locales": { - "en-US": { - "description": "Sample Full Description", - "examplePhrases": ["Alexa open hello world", "hello", "help"], - "name": "engineering test skill one", - "summary": "Sample Short Description" - } - }, - "testingInstructions": "Sample Testing Instructions." - } - } -}